我們先從一個簡單的問題開始介紹。
“為什么要基于面向?qū)ο髞黹_發(fā)軟件?”
不管誰問這樣的問題,筆者都會這樣回答:
“為了輕松地開發(fā)軟件?!?/p>
可能有的人聽到“輕松”二字會感覺很意外。這是因為當提到面向?qū)ο髸r,不少人仍感覺“很難,難以對付”。
面向?qū)ο蟀烁鞣N技術(shù),幾乎涵蓋了從 Java、Ruby 等編程語言到需求規(guī)格書和設(shè)計內(nèi)容的圖形表示、可重用的軟件構(gòu)件群、優(yōu)秀設(shè)計的技術(shù)竅門、業(yè)務(wù)分析和需求定義的有效推進方法、順利推進系統(tǒng)開發(fā)的開發(fā)方法等軟件開發(fā)的所有領(lǐng)域。
不過,這些技術(shù)單獨來看是完全不同的。如果要找出它們的共同點,大概就是它們都是軟件開發(fā)相關(guān)的技術(shù),都是用來順利推進軟件開發(fā)的。
因此,如果用一句話來概括面向?qū)ο?,那就是“能夠輕松地進行較難的軟件開發(fā)的綜合技術(shù)”。
面向?qū)ο蟮挠⑽氖?Object Oriented,直譯為“以對象為中心”。
在面向?qū)ο笃占爸埃髁鞯拈_發(fā)方法是“面向功能”的,具體地說,就是把握目標系統(tǒng)整體的功能,將其按階段進行細化,分解為更小的部分。如果采用面向功能的開發(fā)方法來編寫軟件,當規(guī)格發(fā)生改變或者增加功能時,修改范圍就會變得很廣,軟件也很難重用。
面向?qū)ο蠹夹g(shù)的目的是使軟件的維護和重用變得更容易,其基本思想是重點關(guān)注各個構(gòu)件,提高構(gòu)件的獨立性,將構(gòu)件組合起來,實現(xiàn)系統(tǒng)整體的功能。通過提高構(gòu)件的獨立性,當發(fā)生修改時,能夠使影響范圍最小,在其他系統(tǒng)中也可以重用。
面向?qū)ο笞畛跏且跃幊陶Z言的身份出現(xiàn)的,經(jīng)過不斷發(fā)展,逐漸被應(yīng)用到了開發(fā)的各個領(lǐng)域。這里我們來簡單回顧一下面向?qū)ο蟮娜埠桶l(fā)展過程。
面向?qū)ο笃鹪从?1967 年在挪威設(shè)計的 Simula 67 編程語言。該語言擁有類、多態(tài)和繼承等以往的編程語言中沒有的優(yōu)良結(jié)構(gòu),被稱為最早的面向?qū)ο缶幊陶Z言(Object Oriented Programming language,OOP 1)。后來,艾倫·凱率領(lǐng)的團隊開發(fā)的 Smalltalk 沿用了該結(jié)構(gòu),確立了“面向?qū)ο蟆钡母拍?。此后,具有相同結(jié)構(gòu)的 C 、Objective-C、Java、C# 和 Ruby 等諸多編程語言相繼被開發(fā)出來,并延續(xù)至今。
嚴格來說,正確的表達方式是,將面向?qū)ο缶幊陶Z言(Object Oriented Programming Language)稱為 OOPL,使用 OOPL 進行編程的操作稱為面向?qū)ο缶幊蹋∣OP)。
OOP 使得大規(guī)模軟件的可重用構(gòu)件群的創(chuàng)建成為可能,這些被稱為類庫或者框架。另外,創(chuàng)建可重用構(gòu)件群時使用的固定的設(shè)計思想被提煉為設(shè)計模式。
另外,使用圖形來表示利用 OOP 結(jié)構(gòu)創(chuàng)建的軟件結(jié)構(gòu)的方法稱為統(tǒng)一建模語言(Unified Modeling Language,UML)。在此基礎(chǔ)上,還出現(xiàn)了將 OOP 思想應(yīng)用于上流工程的建模,以及用于順利推進系統(tǒng)開發(fā)的開發(fā)流程。
如今,面向?qū)ο笠呀?jīng)成為一門覆蓋軟件開發(fā)整體的綜合技術(shù)。雖然這些技術(shù)所涉及的領(lǐng)域和內(nèi)容并不相同,但目的都是順利推進軟件開發(fā)。因此,通過以各種形式靈活運用前人的研究和技術(shù)竅門,有助于我們提高軟件的質(zhì)量和開發(fā)效率。
盡管面向?qū)ο笫潜姸鄡?yōu)秀技術(shù)的集大成,卻經(jīng)常被認為很難理解,難以對付。也有人認為不擅長抽象思考的人在學(xué)習(xí)面向?qū)ο髸r會感覺很難,要經(jīng)過很多年才能掌握,等等。不管是多么方便的工具,如果很難理解其內(nèi)涵,無法熟練使用,那就沒有辦法了。
不過,筆者認為,相較于技術(shù)本身的復(fù)雜性,面向?qū)ο笞屓烁杏X很難的更主要的原因在于混亂的現(xiàn)狀。造成混亂的主要原因大致有三點:術(shù)語洪流、比喻濫用和“一切都是對象”綜合征。下面我們就來分別介紹一下。
第一點是術(shù)語洪流。
想必很多人在最開始接觸面向?qū)ο髸r都是被灌輸大量陌生的術(shù)語吧。下面列舉了一些具有代表性的術(shù)語,但其實人們被灌輸?shù)男g(shù)語遠不止這些。
繼承、泛化、特化、超類、子類、接口、多重繼承、屬性、關(guān)聯(lián)、集合、委托、重寫、重載、訪問控制、構(gòu)造函數(shù)、包、異常、垃圾回收機制、框架、類庫、組件、設(shè)計模式、用例、建模、UML、重構(gòu)、敏捷開發(fā)流程、RUP、XP……
簡直就是術(shù)語大集合!在深入了解技術(shù)內(nèi)容之前就被這么多術(shù)語嚇退的人應(yīng)該不在少數(shù)吧。
存在如此大量的術(shù)語的原因如下所示。
首先是面向?qū)ο笏婕暗姆秶軓V。如今面向?qū)ο髱缀鹾w了軟件開發(fā)的所有領(lǐng)域,在這些領(lǐng)域中,之前沒有的新結(jié)構(gòu)和新思想層出不窮。這些術(shù)語中也有不少英文詞匯,可以說這是以歐美為中心迅速發(fā)展起來的技術(shù)的宿命。此外,還有一些詞語被作為業(yè)界的宣傳用語而被過度解釋。像這樣,術(shù)語多少本身源自該技術(shù)的廣度,從一定意義上來說也是沒有辦法的事情。
而更本質(zhì)的問題是基本術(shù)語的定義混亂,我們將在隨后的第三點中對此進行討論。
第二點是比喻濫用。
這與其說是技術(shù)本身的問題,倒不如說是說明方法的問題。一般來說,比喻并不一定就是不好的。使用恰當?shù)谋扔髂軌蛑苯亓水敗⑿蜗蟮卣f明內(nèi)容;反之,如果比喻不恰當或者使用過度,就有可能造成混亂。尤其是在僅通過比喻來說明編程語言等的具體結(jié)構(gòu)的情況下,由于每個人的理解各不相同,所以特別容易造成誤解。
我們來舉例說明一下。面向?qū)ο蟮幕窘Y(jié)構(gòu)有時會像下面這樣說明。
“動物是超類,哺乳類和魚類是子類。既產(chǎn)卵又用乳汁哺乳幼仔
的鴨嘴獸也就相當于爬蟲類和哺乳類的多重繼承。”“人具有‘出生年月日’的屬性。如果給小王這樣具體的一個人發(fā)
出‘請告訴我你的年齡’的消息,就會得到‘28 歲’的回答。”
“正如醫(yī)院里的醫(yī)生、護士和藥劑師互相聯(lián)系、協(xié)同工作一樣,對象也是通過在計算機中互相發(fā)送消息來進行工作的?!?/p>
從直觀理解 OOP 的結(jié)構(gòu)來說,這樣的講解也不一定就是不好的做法。不過,如果只強調(diào)比喻而不詳細介紹編程語言的結(jié)構(gòu)和目的,那么就只有比喻能給人留下深刻的印象,而且聽眾很有可能會根據(jù)自己的理解,對實際的結(jié)構(gòu)產(chǎn)生錯誤的認識。特別是在不考慮系統(tǒng)化范圍,即計算機的作業(yè)范圍的情況下亂用比喻,再加上隨后介紹的“一切都是對象”綜合征的影響,讀者就有可能會產(chǎn)生“當使用面向?qū)ο髸r,可以直接將現(xiàn)實世界表示為程序”的重大誤解。
第三點是“一切都是對象”綜合征。
面向?qū)ο蟮暮x是“以對象為中心”。如果按照字面意思進行解釋,那么現(xiàn)實世界的人、組織、事件、計算機系統(tǒng)的功能、系統(tǒng)管理的信息和程序的構(gòu)成元素等一切事物都可以說是對象。這里,我們將這種極端的抽象稱為“一切都是對象”綜合征。
這種極端看法大概源自“萬物都是變化的”這一點。立足于這種觀點是很難說明和理解編程語言的結(jié)構(gòu),以及現(xiàn)實世界中業(yè)務(wù)流程的整理方法等具體技術(shù)的。盡管如此,但就像“正如現(xiàn)實世界是由對象(物)組成的,在面向?qū)ο笾?,程序也是以對象為中心?chuàng)建的”這句話所說的那樣,我們經(jīng)常會見到實際上不同的對象都被解釋為“對象”這一個詞語的情況。這樣的解釋的確會對直觀理解面向?qū)ο蟮慕Y(jié)構(gòu)有所幫助,但反過來也有可能引起“只要使用面向?qū)ο螅涂梢灾苯訉F(xiàn)實世界表示為程序”的誤解。
不過,這種混亂并不只是說明方法的問題,也是面向?qū)ο蟊旧淼膯栴}。這是因為面向?qū)ο蟮募夹g(shù)范圍很廣,比如對象和類等詞語有時指編程語言的結(jié)構(gòu),但在其他情況下也指管理的信息、現(xiàn)實世界的人和物。
“一切都是對象”綜合征才是造成面向?qū)ο蠡靵y的最大原因)。
在很多情況下,以上為大家介紹的三點引發(fā)混亂的原因,即術(shù)語洪流、比喻濫用和“一切都是對象”綜合征會同時出現(xiàn)。也就是說,在講解面向?qū)ο髸r,講解的人往往會一下子介紹很多陌生的術(shù)語,并以比喻為中心,只強調(diào)現(xiàn)實世界和程序結(jié)構(gòu)的共同之處。然而,這樣的講解非但不能讓人正確地理解該技術(shù),反而會容易引起混亂和誤解。
由于面向?qū)ο笠苑秶軓V、難度較大的軟件開發(fā)為對象,所以在技術(shù)層面上原本就非常復(fù)雜,而以上幾點混亂又進一步增大了理解該技術(shù)的難度,使其本質(zhì)難以被看透。
不理解的事情有時會為我們帶來意外的驚喜。
如果某項技術(shù)只是比較難,讓人無法理解,那么放棄學(xué)習(xí)也沒什么,而面向?qū)ο笏婕暗木幊陶Z言、UML 以及大規(guī)模的可重用構(gòu)件等技術(shù)都很基礎(chǔ),而且這些技術(shù)正在不斷地滲透到軟件開發(fā)的實際應(yīng)用場景,所以現(xiàn)階段很難完全避開面向?qū)ο蟆?/p>
“雖然將現(xiàn)實世界直接表示為程序這種解釋我怎么都想不通,但是由于 Java 和 UML 使用起來比較方便,所以我正在使用。”“雖然其中的個別技術(shù)非常有用,但是整體上卻很難理解?!薄氡乇в羞@些想法的人不在少數(shù)吧。
面向?qū)ο笥袝r會被比作魔法,雖然無法用道理解釋清楚,但效果很好,或者被解釋為一般人難以觸及的理想的開發(fā)方法。這是將“不理解但有用的事物”神秘化,并推崇為“超越人類智慧的存在”的心理在起作用。
不過,面向?qū)ο蟮哪康氖球?qū)動邏輯電路組成的計算機,是具有實踐性的一門極為有用的技術(shù),因此完全不存在無法解釋的內(nèi)容。