NetGo2OO | 22 Feb, 2006 09:00
會想要談論這個題目其實是有緣故的。
自從.Net Go2 OO這個部落格成立以來,我們發表了幾篇關於物件導向基礎的文章,關心的眼光都停留在介面這個重量級的角色上,其中包含了介面使用的時機以及為何要使用介面的正確觀念;另一方面我們也發表了幾篇較為進階的文章,初步的介紹了Design Patterns中較為簡單的幾個樣式,其中也包含了一篇如何應用Pattern來實做的案例。
但是我們逐漸聽到了類似下面的問題:「究竟為什麼要使用物件導向設計,在現實面究竟有什麼好處存在?在現實上這麼辛苦麻煩的設計架構究竟有沒有價值?」
我不禁回想起這些年來學習程式設計以及物件導向設計的過程,這中間我不斷的聽到這樣的標準答案,所謂物件導向就是封裝(Encapsulation)、繼承(Inheritance)、多型(Polymorphism)。我也在許多書本上學習了這些詞彙的解釋,也懂得了如何利用這些特性來撰寫程式(OOP),但是即便如此,我還是沒辦法很輕易的回答上面的問題,我也很少聽到或者看到一個可以讓我由衷讚嘆「對啦,就是這樣!」的說法。
接著我開始接觸物件導向設計(OOD),解釋物件導向的說法開始變的更加虛無飄渺了,每個人都用「汽車與卡車都是車子」的故事來為我解釋物件導向。可是就算我知道汽車跟卡車其實有親戚關係,我還是沒辦法自圓其說為什麼我要使用物件導向設計。難道就因為大家都說它好所以它就好嗎?
然而隨著接觸的層面越來越廣,對於物件導向設計我逐漸有了另外一種看法。
我們時常提及的封裝、繼承、多型或者物件的分析本質都是物件導向設計的特色,又或者說物件導向設計是由這些特質所組合而成的。但是這並不足以構成物件導向成為主流的原因。
一個男人的如果長的很帥可以是他的特色,但是如果長的帥沒辦法為他帶來好處,那我們就不能說長的帥是他的優點。
那麼封裝、繼承、多型這些特色究竟可以為我們帶來什麼好處?
- 這裡不打算解釋什麼是封裝、繼承、多型,有許多書本都講解的非常的清楚明白,要麻煩不瞭解的朋友們去查閱這些書籍。
換個角度
首先,封裝讓程式碼易於理解。我們可以從一個類別的名稱以及他的行為去理解與記憶它和系統之間的關係與責任,這樣的特性可以縮短日後我們重新檢視程式碼時所要花費的時間,沒有人會說這不是好處吧?
再來,繼承讓程式碼可以重複使用。就拿剛剛提到的車子、汽車與卡車的例子來說吧。我們把大部分重複的程式碼寫在車子的類別裡,以後的十種汽車跟八種卡車都可以直接享用車子中已經定義好的程式碼與功能。我們因此縮短了浪費在重複性工作上的時間。
最後,多型讓程式易於擴充與維護。針對共通的介面來撰寫程式時,可以使得物件之間的關係被鬆綁,讓軟體在日後進行擴充或者個別物件修改時不需要更動到既有的程式碼。當軟體龐大到一定程度之後,擴充與修改對程式設計師而言往往是非常痛苦的一件事情,我對於善用介面可以達到的效果非常推崇,可以說相當程度的提供了軟體品質的穩定。
撇開所有美輪美奐的說詞,回來面對現實,我們就是為了能夠讓程式碼重複利用,讓系統易於擴充與維護所以才要使用物件導向。這一切最直接的效果就反應在縮短軟體開發的時間以及增進軟體的品質穩定度上,讓我們能夠專注在真正重要的工作上面。美麗或者基本教義派的崇拜都不是物件導向之所以存在的原因。
站在實作的角度來看,物件導向的存在就是為了增進程式設計師工作的效率以及軟體的品質,以這樣的觀點而言,使用物件導向設計是再實際也不過了,千萬別說使用物件導向是天真而不肯面對現實。
水能載舟亦能覆舟
不過問題來了,既然物件導向這麼優秀,為什麼還會有這麼多人不願意把她娶進門,仍然嫌東嫌西的呢?
其實上帝是公平的,這世界上本來就不存在十全十美的事物,物件導向既然擁有這麼抽象而複雜的特性,也就造成了它在撰寫上一開始就必須克服的時間成本。為了能夠做到封裝,所以我們必須多花一些時間在分析物件的責任歸屬,為了做到繼承,所以我們必須多花一些時間在分析物件之間共有的責任與資料,為了日後擴充方便,我們必須多花一些時間創造出合適的抽象介面來讓物件實做。
這些都是伴隨著物件導向設計而來的工作。我們不能否認,使用結構式的程式設計不必付出這些時間成本;當然,自然也享受不到繼承與介面的優點。
持平而論,物件導向的出現是為了讓程式設計師能夠用更短的時間開發出更優良的軟體,如果在某些現實條件下的評估結果是,不使用複雜的物件導向設計勝於使用的話,又為何不選擇簡單一點架構呢?明明不會有擴充或者變動的可能性,硬要放個抽象介面在那邊礙眼,這是最不智的行為。
吃路邊攤的時候穿晚禮服,就算你長的再美,也只會讓人家覺得你有毛病而已,不是嗎?
結論
在現實生活中開發任何軟體專案時,我們通常希望在專案的進度、品質以及成本之間取得平衡,極端的要求在最短的時間內花掉最少的成本來取得最高的品質是不可能實現的夢想。
物件導向設計是軟體開發歷史演進下的產物,集結了許多前輩的智慧與經驗而成,即便是如此,也不可能達到上述夢想中的境界。我們當然可以追求最完美的物件導向設計架構,但是必然將犧牲開發的進度以及成本。相對的,一昧追求時效捨棄良好的軟體設計也不可能得到合理的品質。
許多時候並非物件導向設計無用,只是在有條件的選擇下被捨棄罷了。