• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
    • 軟件測試技術
    • 軟件測試博客
    • 軟件測試視頻
    • 開源軟件測試技術
    • 軟件測試論壇
    • 軟件測試沙龍
    • 軟件測試資料下載
    • 軟件測試雜志
    • 軟件測試人才招聘
      暫時沒有公告

    字號: | 推薦給好友 上一篇 | 下一篇

    Interlude之深入淺出OOD(一)

    發布: 2007-5-25 11:48 | 作者: 佚名 | 來源: uml中國 | 查看: 56次 | 進入軟件測試論壇討論

    領測軟件測試網

    有物昆成,先天地生。蕭呵!謬呵!獨立而不改,可以為天地母。吾未知其名,字之曰道。吾強為之名曰大,大曰逝,逝曰遠,遠曰反。道大,天大,地大,王亦大。

    ——《道德經》,第二十五章

    軟件不軟
    從60年代的軟件危機,到今天傳統軟件工程方法處處碰壁的處境,都說明一個問題:軟件不軟(Software is Hard)[Martin, 95]。說實話,軟件是一塊硬骨頭,真正開發過軟件的人都會有此感覺。一個應用總是包含無數錯綜復雜的細節,而軟件開發者則要把所有這些細節都組織起來,使之形成一個可以正常運轉的程序,這實在不是一件簡單的事。

    為什么會這樣?舉個例子來說:用戶可以很輕松地說“我要一個字處理軟件”,他覺得“字處理軟件”這樣一個概念是再清楚不過的了,根本不需要更多的描述;而真正開發一個字處理軟件卻是一件困難無比的事情——我曾經親眼看到開發字處理軟件的人們是怎樣受盡折磨的。為什么表述一個概念很容易,而實現一個概念很困難?因為人們太擅長抽象、太擅長剝離細節問題了。

    軟件不軟,癥結就在這里:用戶很容易抽象地表達自己的需求,而這種抽象卻很難轉化為程序代碼;軟件不軟,因為很簡單的設想也需要大量的時間去實現;軟件不軟,因為滿足用戶的需求和期望實在太困難;軟件不軟,因為軟件太容易讓用戶產生幻想。

    而另一方面,計算機硬件技術卻在飛速發展。從幾十年前神秘的龐然大物,到現在隨身攜帶的移動芯片;從每秒數千次運算到每秒上百億次運算。當軟件開發者們還在尋找能讓軟件開發生產力提高一個數量級的“銀彈”[Brooks, 95]時,硬件開發的生產力早已提升了百倍千倍。這是為什么?

    硬件工程師們能夠如此高效,是因為他們都很懶惰。他們永遠恪守“不要去重新發明輪子”的古訓,他們盡量利用別人的成果。你看到有硬件工程師自己設計撥碼開關的嗎?你看到有硬件工程師自己設計低通濾波電路的嗎?你看到有硬件工程師自己設計計時器的嗎?他們有一套非常好的封裝技術,他們可以把電路封裝在一個接插件里面,只露出接口。別人要用的時候,只管按照接口去用,完全不必操心接插件內部的實現。

    而軟件工程師們呢?在STL被C++標準委員會采納之前(甚至之后),每個C++程序員都寫過自己的排序算法和鏈表,并都認為自己比別人寫得更好…真是令人傷心。

    OOD可以讓軟件稍微“軟”一點
    軟件不軟,不過OOD可以幫助它稍微“軟”一點。OOD為我們提供了封裝某一層面上的功能和復雜性的工具。使用OOD,我們可以創建黑箱軟件模塊,將一大堆復雜的東西藏到一個簡單的接口背后。然后,軟件工程師們就可以使用標準的軟件技術把這些黑箱組合起來,形成他們想要的應用程序。

    Grady Booch把這些黑箱稱為類屬(class category),現在我們則通常把它們稱為“組件(component)”。類屬是由被稱為類(class)的實體組成的,類與類之間通過關聯(relationship)結合在一起。一個類可以把大量的細節隱藏起來,只露出一個簡單的接口,這正好符合人們喜歡抽象的心理。所以,這是一個非常偉大的概念,因為它給我們提供了封裝和復用的基礎,讓我們可以從問題的角度來看問題,而不是從機器的角度來看問題。

    軟件的復用最初是從函數庫和類庫開始的,這兩種復用形式實際上都是白箱復用。到90年代,開始有人開發并出售真正的黑箱軟件模塊:框架(framework)和控件(control)?蚣芎涂丶受平臺和語言的限制,現在軟件技術的新潮流是用SOAP作為傳輸介質的Web Service,它可以使軟件模塊脫離平臺和語言的束縛,實現更高程度的復用。但是想一想,其實Web Service也是面向對象,只不過是把類與類之間的關聯用XML來描述而已[Li, 02]。在過去的十多年里,面向對象技術對軟件行業起到了極大的推動作用。在可以預測的將來,它仍將是軟件設計的主要技術——至少我看不到有什么技術可以取代它的。

    上面,我向讀者介紹了一些背景知識,也稍微介紹了OOD的好處。下面,我將回答幾個常見的問題,希望能借這幾個問題讓讀者看清OOD的輪廓。

    什么是OOD?
    面向對象設計(Object-Oriented Design,OOD)是一種軟件設計方法,是一種工程化規范。這是毫無疑問的。按照Bjarne Stroustrup的說法,面向對象的編程范式(paradigm)是[Stroustrup, 97]:

    決定你要的類;
    給每個類提供完整的一組操作;
    明確地使用繼承來表現共同點。
    由這個定義,我們可以看出:OOD就是“根據需求決定所需的類、類的操作以及類之間關聯的過程”。
    OOD的目標是管理程序內部各部分的相互依賴。為了達到這個目標,OOD要求將程序分成塊,每個塊的規模應該小到可以管理的程度,然后分別將各個塊隱藏在接口(interface)的后面,讓它們只通過接口相互交流。比如說,如果用OOD的方法來設計一個服務器-客戶端(client-server)應用,那么服務器和客戶端之間不應該有直接的依賴,而是應該讓服務器的接口和客戶端的接口相互依賴。

    這種依賴關系的轉換使得系統的各部分具有了可復用性。還是拿上面那個例子來說,客戶端就不必依賴于特定的服務器,所以就可以復用到其他的環境下。如果要復用某一個程序塊,只要實現必須的接口就行了。

    OOD是一種解決軟件問題的設計范式(paradigm),一種抽象的范式。使用OOD這種設計范式,我們可以用對象(object)來表現問題領域(problem domain)的實體,每個對象都有相應的狀態和行為。我們剛才說到:OOD是一種抽象的范式。抽象可以分成很多層次,從非常概括的到非常特殊的都有,而對象可能處于任何一個抽象層次上。另外,彼此不同但又互有關聯的對象可以共同構成抽象:只要這些對象之間有相似性,就可以把它們當成同一類的對象來處理。

    OOD到底從哪兒來?
    有很多人都認為:OOD是對結構化設計(Structured Design,SD)的擴展,其實這是不對的。OOD的軟件設計觀念和SD完全不同。SD注重的是數據結構和處理數據結構的過程。而在OOD中,過程和數據結構都被對象隱藏起來,兩者幾乎是互不相關的。不過,追根溯源,OOD和SD有著非常深的淵源。

    1967年前后,OOD和SD的概念幾乎同時誕生,它們分別以不同的方式來表現數據結構和算法。當時,圍繞著這兩個概念,很多科學家寫了大量的論文。其中,由Dijkstra和Hoare兩人所寫的一些論文講到了“恰當的程序控制結構”這個話題,聲稱goto語句是有害的,應該用順序、循環、分支這三種控制結構來構成整個程序流程。這些概念發展構成了結構化程序設計方法;而由Ole-Johan Dahl所寫的另一些論文則主要討論編程語言中的單位劃分,其中的一種程序單位就是類,它已經擁有了面向對象程序設計的主要特征。

    這兩種概念立刻就分道揚鑣了。在結構化這邊的歷史大家都很熟悉:NATO會議采納了Dijkstra的思想,整個軟件產業都同意goto語句的確是有害的,結構化方法、瀑布模型從70年代開始大行其道。同時,無數的科學家和軟件工程師也幫助結構化方法不斷發展完善,其中有很多今天足以使我們振聾發聵的名字,例如Constantine、Yourdon、DeMarco和Dijkstra。有很長一段時間,整個世界都相信:結構化方法就是拯救軟件工業的“銀彈”。當然,時間最后證明了一切。

    而此時,面向對象則在研究和教育領域緩慢發展。結構化程序設計幾乎可以應用于任何編程語言之上,而面向對象程序設計則需要語言的支持[*],這也妨礙了面向對象技術的發展。實際上,在60年代后期,支持面向對象特性的語言只有Simula-67這一種。到70年代,施樂帕洛阿爾托研究中心(PARC)的Alan Key等人又發明了另一種基于面向對象方法的語言,那就是大名鼎鼎的Smalltalk。但是,直到80年代中期,Smalltalk和另外幾種面向對象語言仍然只停留在實驗室里。

    到90年代,OOD突然就風靡了整個軟件行業,這絕對是軟件開發史上的一次革命。不過,登高才能望遠,新事物總是站在舊事物的基礎之上的。70年代和80年代的設計方法揭示出許多有價值的概念,誰都不能也不敢忽視它們,OOD也一樣。

    OOD和傳統方法有什么區別?
    還記得結構化設計方法嗎?程序被劃分成許多個模塊,這些模塊被組織成一個樹型結構。這棵樹的根就是主模塊,葉子就是工具模塊和最低級的功能模塊。同時,這棵樹也表示調用結構:每個模塊都調用自己的直接下級模塊,并被自己的直接上級模塊調用。

    那么,哪個模塊負責收集應用程序最重要的那些策略?當然是最頂端的那些。在底下的那些模塊只管實現最小的細節,最頂端的模塊關心規模最大的問題。所以,在這個體系結構中越靠上,概念的抽象層次就越高,也越接近問題領域;體系結構中位置越低,概念就越接近細節,與問題領域的關系就越少,而與解決方案領域的關系就越多。

    但是,由于上方的模塊需要調用下方的模塊,所以這些上方的模塊就依賴于下方的細節。換句話說,與問題領域相關的抽象要依賴于與問題領域無關的細節!這也就是說,當實現細節發生變化時,抽象也會受到影響。而且,如果我們想復用某一個抽象的話,就必須把它依賴的細節都一起拖過去。

    而在OOD中,我們希望倒轉這種依賴關系:我們創建的抽象不依賴于任何細節,而細節則高度依賴于上面的抽象。這種依賴關系的倒轉正是OOD和傳統技術之間根本的差異,也正是OOD思想的精華所在。

    OOD能給我帶來什么?
    問這個問題的人,腦子里通常是在想“OOD能解決所有的設計問題嗎?”沒有銀彈。OOD也不是解決一切設計問題、避免軟件危機、捍衛世界和平……的銀彈。OOD只是一種技術。但是,它是一種優秀的技術,它可以很好地解決目前的大多數軟件設計問題——當然,這要求設計者有足夠的能力。

    OOD可能會讓你頭疼,因為要學會它、掌握它是很困難的;OOD甚至會讓你失望,因為它也并不成熟、并不完美。OOD也會給你帶來欣喜,它讓你可以專注于設計,而不必操心那些細枝末節;OOD也會使你成為一個更好的設計師,它能提供給你很好的工具,讓你能開發出更堅固、更可維護、更可復用的軟件。

    C++是一種“真正的”面向對象編程語言嗎?
    最后這個問題和我們今天的主題關系不大,不過這是一個由來已久的問題,而且以后也不一定會有合適的時機說明這個問題,所以今天一起回答了。

    很多人都覺得C++缺少“真正的”面向對象語言所必須的一些特性,例如垃圾收集(garbage collection)、多分配(multiple-dispatch)之類的。但是,缺少這些特性并不影響開發者們用C++實現面向對象的設計思路。

    在我看來,任何語言,只要它直接支持面向對象設計的實現,那它就是“真正的”面向對象語言。用這個標準來評價,C++是完全符合的:它直接支持繼承、多態、封裝和抽象,而這些才是面向對象最重要的。而VB和C這樣的語言不能直接支持這些(盡管可以用特殊的技巧來實現),所以不是“真正的”面向對象語言。

    參考書目
    [Brooks, 95] Frederick Brooks, The Mythical Man-Month, Addison-Wesley, 1995.
    [Li, 02] 李維,《Delphi 6/Kylix 2 SOAP/Web Service程序設計篇》,機械工業出版社,2002年。
    [Martin, 95] Robert Martin, Designing Object-Oriented C++ Applications Using the Booch Method, Prentice-Hall, 1995.
    [Stroustrup, 97] Bjarne Stroustrup, The C++ Programming Language (Special Edition), Addison-Wesley, 1997.
    *注:我聽見有人說“我可以用C語言實現面向對象”,不過我不希望你也會說“我喜歡這樣做法”。很明顯,如果沒有語言特性的支持,面向對象方法將寸步難行。其實結構化設計也是一樣,不過幾乎所有的編程語言都提供了對三種基本流程結構(順序,條件,以及循環)的支持,所以基本不會遇到這個問題。

    延伸閱讀

    文章來源于領測軟件測試網 http://www.kjueaiud.com/


    關于領測軟件測試網 | 領測軟件測試網合作伙伴 | 廣告服務 | 投稿指南 | 聯系我們 | 網站地圖 | 友情鏈接
    版權所有(C) 2003-2010 TestAge(領測軟件測試網)|領測國際科技(北京)有限公司|軟件測試工程師培訓網 All Rights Reserved
    北京市海淀區中關村南大街9號北京理工科技大廈1402室 京ICP備2023014753號-2
    技術支持和業務聯系:info@testage.com.cn 電話:010-51297073

    軟件測試 | 領測國際ISTQBISTQB官網TMMiTMMi認證國際軟件測試工程師認證領測軟件測試網

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>