1. 程式人生 > >面向物件與面向過程理解

面向物件與面向過程理解

本文源地址:

面向過程與面向物件

一位計算機界的大師曾說過,“我認為,面向物件的目標從來都不是複用和擴充套件,而是提供一種處理複雜問題的方法”。

面向過程講究自頂向下逐步求精。找到一個系統的入口然後順藤摸瓜,分析出每一步以及影響這一步的其他因素,我們就能夠定義這個系統。

面向物件認為世界是有很多物件組成的,各個物件之間相互獨立,平時並沒有什麼關係。在某些外力的作用之下物件之間相互協作,表現出一定的行為,最終塑造了這個複雜的世界。面向過程和麵向物件都是人們認識和了解這個世界的手段和方法,並無優劣之分,只有是否適用之差別。

面向物件和麵向過程的最根本區別就是提供了一種新的認識和了解複雜系統的方法。面向物件有一個術語:抽象層次。比如對一輛汽車來說,從整體上來看,它是由底盤、懸掛、發動機、變速箱、外殼等部件組成的。而從發動機這個抽象層次來看,它是由活塞、曲軸、連桿、火花塞、油底殼、缸壁等組成。不同的抽象層次上會有不同的認識。通過不斷變換抽象層次,我們能對系統有個更好的認識。在每個層次上我們只需要關心當前層次上的物件和它們之間的互動。其他層次上的東西,與本層次無關。這樣帶來的好處是:無論出於哪個層次上,我們都面臨有限的物件和複雜度,從而可以更專心的瞭解這個層次上的物件是如何工作的。通過不斷分離關注點,達到降低複雜度的目的。

抽象層次的另一個好處就是更換低層次的零件不會對高層次進行影響。比如,更換全新的發動機之後不會導致汽車無法行駛,更換火花塞之後不會導致發動機無法運轉。低層次的資訊對高層次隱藏,高層次不知道也不想知道低層次的零件如何工作。

回到大師的話,面向過程需要分析出整個系統的所有細節,當系統規模足夠複雜,複雜到了超越其處理能力,使用結構化程式設計常常有無處下手的無力感。採用面向物件方法,引入了有個抽象層次的概念,我們就能通過不斷提升抽象級別來構建更大更復雜的系統。

抽象層次越高,具體資訊越少,細節也就越少,也就越容易理解。而抽象層次越低,具體資訊越多,細節也越多。細節越多越容易陷入枝枝葉葉的泥潭而無法自拔。一旦超越人腦的處理極限,就很難去理解了。人們認識事物總是習慣從表面到本質,由表及裡的一步步去分析。剛認識一件事物時我們可以從外觀、整體較高的抽象層次去認識,然後逐步深入。比如對一個不瞭解汽車的人講汽車,我們可以從整體介紹汽車包括底盤、傳送機、變速箱、懸掛等。這時我們的抽象層次是很高的。當介紹清楚之後,我們可以深入到下一個層次,比如講發動機結構。在發動機結構講清楚以後,我們在從力學、熱學的角度講述發動機的工作原理。這樣逐步深入,結構清晰,聽的人也容易理解。逐步的深入中我們的抽象層次是逐漸降低的。反過來如果上來就講發動機工作原理,聽的人必定一頭霧水。上面這個由表面到機理的過程其實就是自頂向下方法。另一種方法是自底向上。先從內部、底層講起,逐步提高抽象層次。

這兩種方法都是分析、研究問題的方法。在軟體開發過程中,主體上應該採用自頂向下的方法,用少量的概念抽象、概括系統,再逐步降低抽象層次,直到程式碼編寫。同時輔以自底向上的方法,通過總結在較低抽象層次的實踐經驗,來改進較高層次的概念以提升軟體質量。

抽象層次高了,具體資訊越少,分析問題簡單了,但是隨之而來也會帶來另一個問題:抽象層次太高。抽象層次太高具體資訊太少,又會導致資訊量不足。所以在面向物件的分析過程中,在適當的時候選擇適當的抽象層次是十分重要的。

層次確定好了,接下來就是在該層次上進行面向物件的分析工作了。無論任何時候在同一個抽象層次上,都應當將物件看成一個不可分割的整體。無論物件的規模多麼大,大到一個國家、一座工廠,只要我們認為它是物件,它與其他物件互動時就是一個整體,不能分割。這就是說的物件的原子性,一旦破壞了原子性,就表示在同一抽象層次上 的物件不具備同一粒度,就將使得分析工作陷入混亂 。

在分析工作中,應該牢記物件有一個邊界,不應該打破邊界去窺探物件內部。形象一點來說,物件看上去就像是一個雞蛋,蛋殼就是雞蛋的邊界。在分析物件的過程中。對雞蛋的所有關係都是通過蛋殼發生。如果我們試圖瞭解物件內部的細節,就像打破蛋殼去窺探雞蛋內部,內部一團黏黏糊糊,無從下手。

下面內容主要關注以下四個方面:

  1. 面向物件為什麼那麼難?
  2. 類和物件是從石頭裡蹦出來的麼?
  3. 設計模式有那麼重要麼?
  4. UML和麵向物件什麼關係?

首先我們來看下為什麼面向物件那麼難。很多科班出身的程式猿,當然也包括我。第一門程式語言學習的是C語言。眾所周知,C語言是一門面向過程的語言,在編寫複雜的C程式時,用的最多的就是流程圖和虛擬碼。只要使用流程圖詳細描述出程式的每一步,就可以很容易的照貓畫虎將流程圖轉換成C程式碼。這也是C語言這類面相過程語言的特點,講究自頂向下逐步求精。任何系統,只要找到它的入口,從入口開始,詳細分析它的每一步以及影響這一步的所有因素,然後順藤摸瓜,直至分析完整個系統。

很多人的思維被面向過程先入為主,每次拿到一個需求時,都會強迫自己去分析所有的流程。小的系統還好,如果一個相對複雜的系統,流程眾多且複雜、參與者眾多,這個時候嘗試去分析其中的每一步,經常會遇到陷入業務細節的泥潭無法自拔的問題。而面向物件思想的出現就是為了解決這類複雜的問題。

面向過程存在的另一個問題是,整個系統的分析是順序的,下一步依賴上一步的分析結果。如果上一步不穩定或存在問題,以後就死翹翹了。我們經常說瀑布式軟體開發過程存在問題,大力提倡敏捷,一個很重要的原因是:瀑布式開發過程太過依賴上一步的結果,一旦上一步存在問題,後面將會全盤皆輸。這是不能令人接受的。

C++這門程式語言,既支援面向物件又支援面向過程。因此我們在實現一個東西時,既可以這樣做又可以那麼做。過多的選擇反而讓我們無所適從。有時候我們經常會想明明加一個else、case或者在一個方法裡實現的問題,為何要使用那麼多類來實現。這不是多此一舉嗎。有些時候確實是多此一舉。但面嚮物件語言存在的目的就為了構建可維護、可擴充套件、靈活性好的系統。可維護、可擴充套件和可維護聽起來很高大上,但是隻是飄在天上的遙遠關鍵詞,好像在我這裡無法落地。無法落地的原因就是你還沒有真正理解什麼是面向物件。

面向物件關注類、物件以及物件間的互動。再複雜的系統,都是由相互獨立的物件通過一定的互動和協作來完成。就像現實中大家協作完成一件事情一樣,每個人各司其職,既相互獨立又關係密切。而所謂的面向物件的系統,就是我們的系統有很多相互獨立的物件。每個物件具有一定的職責,物件之間相互互動或協作。整個軟體系統就是靠這些眾多物件之間的互動來運作。

類和物件是可以依據一定的規則推匯出來的。OOA(面向物件分析)和OOD(面向物件設計)就是叩開面向物件大門的金鑰匙。通過OOA、OOD我們發現和描述物件、定義物件的職責、描述物件間的互動等等。

很多初學者聽別人說到過設計模式很重要,但是卻不明白為什麼設計模式如此重要。設計模式是計算機大牛們在程式設計時,針對某些特定問題總結出來的一套經驗。經典設計模式有23種,後來又慢慢擴充套件越來越多。學會前人的這樣經驗固然重要,但是卻沒有想象中的重要。沿著前人的車轍,固然可以讓我們少走彎路,但更要的是學會前人分析解決問題的思路。大家可以看到每種設計模式在介紹時,都會有一個前提,即這個模式在XX情況下適用,可以解決什麼問題,有什麼樣的副作用。所以每種設計模式都有自己的適用背景,平時使用時如果不考慮這些背景以及導致的副作用,經常會出現得不償失的效果。很多人都很苦惱的是為何我看了那麼多的設計模式,卻仍然無法將設計模式應用到我的工作中去。對設計模式沒有那麼瞭如指掌是一方面的問題,但更重要的是經典的設計模式背景太過純粹,而我們的所面臨的背景相對複雜。有些時候這些設計模式是不能那麼輕而易舉原封不動的照搬過來。因此工作中經常遇到的就是我們使用的設計模式並不是純粹的XX設計模式,而是基於它的改進或變體或者是幾種設計模式的混用。設計模式是面向物件思想的很好的體現,應用了設計模式的系統,具備很好的靈活性。物件之間解耦合,內聚性強。很容易擴充套件和修改。應用設計模式的設計良好的系統,後面維護起來也很容易,不像我們的程式碼出現越維護越糟糕,這裡一句if那裡一句magic code,類、方法變得臃腫,職責越來越不清晰、分支越來越多,圈複雜度越來越高,四處有重複程式碼。讀起來都費勁,更別提基於此繼續修改了。

設計模式也是基於面向物件思想總結出來的,因此比掌握設計模式更重要的是學會面向物件的思想。當你達到一定的高度,你也可以創造屬於自己的設計模式。因此比掌握某個設計模式更重要的是學會面向物件的思想,哪怕沒有應用任何設計模式,也一樣可以構造出好的面向物件的程式碼。

UML (Unified Modeling Language)統一建模語言。 是一種視覺化的建模語言。用來描述需求、設計。方便參與軟體系統構建的各方交流溝通。

就像學會英語這門外語並不能保證你口若懸河出口成章字字珠璣一樣。學會UML只是讓你有了可以表達和描述你的設計的工具。UML只是和麵向物件更配哦。

現在軟體分工越來越細,需求分析、建模、設計、實現往往有很多人蔘與,UML的出現方便了各方的交流溝通。使用各種圖來描述系統,比文字更有清晰直觀,結合文字描述更容易理解。

UML包括九種圖:用例圖、類圖、物件圖、狀態圖、序列圖(順序圖)、協作圖(通訊圖)、活動圖、構件圖、部署圖。最常用到的圖是用例圖、類圖、序列圖

從上面大家可以看到,UML並不包括流程圖。流程圖這個東西是面向過程時代的產物。它有一個致命的缺陷就是隻描述了流程,卻無法給出有哪些物件參與以及物件間的協作。UML定義了活動圖用於替代流程圖,活動圖中引入了泳道的概念,泳道即代表每一個參與的物件。因此推薦大家在寫概要設計文件時避免使用流程圖,而應該使用活動圖。概要設計使用流程圖,只是描述了業務流程,並沒有進行任何設計。流程圖描述的客戶業務流程應該在更早一些的產品需求文件裡體現。

UML不僅僅可以在設計階段使用,還可以應用在需求階段。需求分析階段使用用例圖、用例文字描述整個系統的功能範圍。設計階段使用類圖說明類之間的靜態結構關係、使用序列圖說明類之間的互動順序、使用活動圖描述複雜業務流程。