超越自我 從程序員到系統分析員

>>>  技術話題—商業文明的嶄新時代  >>> 簡體     傳統

(2005.04.21)  

大家應該對這兩個詞很熟悉了,但是對詞里包含的意義可能并不是特別清楚。首先必須說明的是,程序員和系統分析員不存在誰高級誰低級的分別,他們是兩種職業,對職業技能的要求完全不同。所以厲害的程序員就是系統分析員的說法是不對的。當然,系統分析員的技能要求他必須要懂得如何寫程序,但是他的重心在于如何把一個很大的項目切割成適合個人的小塊,然后將這些小塊組織起來。程序員的職責就是如何更好更快的實現這些小塊。 

  在正式開始之前,我們還是來看在Thinking In Java中作者對分析和設計的一段精辟見解:

  分析和設計

  面向對象的范式是思考程序設計時一種新的、而且全然不同的方式,許多人最開始都會在如何構造一個項目上皺起了眉頭。事實上,我們可以作出一個“好”的設計,它能充分利用OOP提供的所有優點。

  請原諒在這里突然出現了OOP這個詞,他的意思是面相對象,雖然在之前沒有提到,但是在現在OO概念滿天飛的軟件世界里,大家應該對他不會太陌生。這里我簡要的說明一下。在之前我介紹的實際上都是在很早以前程序寫作流傳下來的經驗(什么,教我們老古董,打他!),但是以前的非OO(就是基于過程)的軟件設計方法目前在國際上已經很少采用,所以我這里講軟件設計的時候所有的概念都是基于OO的。即使OO的概念很簡單的啦,大家思考一下,我們再學習C++的時候一開始使用的類不都是一些動物啦、正方形啦之類的,都是生活中的例子,對吧。其實OO就是我們看世界的一種方式。可是最早由于計算機技術的不發達,我們不得不用一些很奇怪的描述來表達我們的意思,只有這樣計算機才能理解,很笨不是嗎。比如我們必須使用參數、過程、函數。所以當時的軟件設計方法都是基于過程的。舉一個簡單的例子來顯示OO設計方法和基于過程的設計方法之間的差別:一句簡單的日常短語--“我吃飯”,用OO的方法來表述還是“我吃飯”,可是如果用基于過程的方法來描述的話就變成“我吃飯(飯)”,是不是很別扭呢。

  有關OOP分析與設計的書籍大多數都不盡如人意。其中的大多數書都充斥著莫名其妙的話語、笨拙的筆調以及許多聽起來似乎很重要的聲明。我認為這種書最好壓縮到一章左右的空間,至多寫成一本非常薄的書。具有諷剌意味的是,那些特別專注于復雜事物管理的人往往在寫一些淺顯、明白的書上面大費周章!如果不能說得簡單和直接,一定沒多少人喜歡看這方面的內容。畢竟,OOP的全部宗旨就是讓軟件開發的過程變得更加容易。盡管這可能影響了那些喜歡解決復雜問題的人的生計,但為什么不從一開始就把事情弄得簡單些呢?因此,希望我能從開始就為大家打下一個良好的基礎,盡可能用幾個段落來說清楚分析與設計的問題。

  不要迷失

  在整個開發過程中,最重要的事情就是:不要將自己迷失!但事實上這種事情很容易發生。大多數方法都設計用來解決最大范圍內的問題。當然,也存在一些特別困難的項目,需要作者付出更為艱辛的努力,或者付出更大的代價。但是,大多數項目都是比較“常規”的,所以一般都能作出成功的分析與設計,而且只需用到推薦的一小部分方法。但無論多么有限,某些形式的處理總是有益的,這可使整個項目的開發更加容易,總比直接了當開始編碼好! 也就是說,假如你正在考察一種特殊的方法,其中包含了大量細節,并推薦了許多步驟和文檔,那么仍然很難正確判斷自己該在何時停止。時刻提醒自己注意以下幾個問題:

  (1) 對象是什么?(怎樣將自己的項目分割成一系列單獨的組件?) 

  (2) 它們的接口是什么?(需要將什么消息發給每一個對象?)

  在確定了對象和它們的接口后,便可著手編寫一個程序。出于對多方面原因的考慮,可能還需要比這更多的說明及文檔,但要求掌握的資料絕對不能比這還少。

  整個過程可劃分為四個階段,階段0剛剛開始采用某些形式的結構。

  階段0:擬出一個計劃

  第一步是決定在后面的過程中采取哪些步驟。這聽起來似乎很簡單(事實上,我們這兒說的一切都似乎很簡單),但很常見的一種情況是:有些人甚至沒有進入階段1,便忙忙慌慌地開始編寫代碼。如果你的計劃本來就是“直接開始開始編碼”,那樣做當然也無可非議(若對自己要解決的問題已有很透徹的理解,便可考慮那樣做)。但最低程度也應同意自己該有個計劃。

  在這個階段,可能要決定一些必要的附加處理結構。但非常不幸,有些程序員寫程序時喜歡隨心所欲,他們認為“該完成的時候自然會完成”。這樣做剛開始可能不會有什么問題,但我覺得假如能在整個過程中設置幾個標志,或者“路標”,將更有益于你集中注意力。這恐怕比單純地為了“完成工作”而工作好得多。至少,在達到了一個又一個的目標,經過了一個接一個的路標以后,可對自己的進度有清晰的把握,干勁也會相應地提高,不會產生“路遙漫漫無期”的感覺。

  從我剛開始學習故事結構起(我想有一天能寫本小說出來),就一直堅持這種做法,感覺就象簡單地讓文字“流”到紙上。在我寫與計算機有關的東西時,發現結構要比小說簡單得多,所以不需要考慮太多這方面的問題。但我仍然制訂了整個寫作的結構,使自己對要寫什么做到心中有數。因此,即使你的計劃就是直接開始寫程序,仍然需要經歷以下的階段,同時向自己提出一些特定的問題。

  階段1:要制作什么?

  在上一代程序設計中(即“過程化或程序化設計”),這個階段稱為“建立需求分析和系統規格”。當然,那些操作今天已經不再需要了,或者至少改換了形式。大量令人頭痛的文檔資料已成為歷史。但當時的初衷是好的。需求分析的意思是“建立一系列規則,根據它判斷任務什么時候完成,以及客戶怎樣才能滿意”。系統規格則表示“這里是一些具體的說明,讓你知道程序需要做什么(而不是怎樣做)才能滿足要求”。

  需求分析實際就是你和客戶之間的一份合約(即使客戶就在本公司內部工作,或者是其他對象及系統)。系統規格是對所面臨問題的最高級別的一種揭示,我們依據它判斷任務是否完成,以及需要花多長的時間。由于這些都需要取得參與者的一致同意,所以我建議盡可能地簡化它們——最好采用列表和基本圖表的形式——以節省時間。可能還會面臨另一些限制,需要把它們擴充成為更大的文檔。 我們特別要注意將重點放在這一階段的核心問題上,不要糾纏于細枝末節。這個核心問題就是:決定采用什么系統。對這個問題,最有價值的工具就是一個名為“使用條件”的集合。對那些采用“假如……,系統該怎樣做?”形式的問題,這便是最有說服力的回答。例如,“假如客戶需要提取一張現金支票,但當時又沒有這么多的現金儲備,那么自動取款機該怎樣反應?”對這個問題,“使用條件”可以指示自動取款機在那種“條件”下的正確操作。

  應盡可能總結出自己系統的一套完整的“使用條件”或者“應用場合”。一旦完成這個工作,就相當于摸清了想讓系統完成的核心任務。由于將重點放在“使用條件”上,一個很好的效果就是它們總能讓你放精力放在最關鍵的東西上,并防止自己分心于對完成任務關系不大的其他事情上面。也就是說,只要掌握了一套完整的“使用條件”,就可以對自己的系統作出清晰的描述,并轉移到下一個階段。在這一階段,也有可能無法完全掌握系統日后的各種應用場合,但這也沒有關系。只要肯花時間,所有問題都會自然而然暴露出來。不要過份在意系統規格的“完美”,否則也容易產生挫敗感和焦燥情緒。 在這一階段,最好用幾個簡單的段落對自己的系統作出描述,然后圍繞它們再進行擴充,添加一些“名詞”和“動詞”。“名詞”自然成為對象,而“動詞”自然成為要整合到對象接口中的“方法”。只要親自試著做一做,就會發現這是多么有用的一個工具;有些時候,它能幫助你完成絕大多數的工作。

  盡管仍處在初級階段,但這時的一些日程安排也可能會非常管用。我們現在對自己要構建的東西應該有了一個較全面的認識,所以可能已經感覺到了它大概會花多長的時間來完成。此時要考慮多方面的因素:如果估計出一個較長的日程,那么公司也許決定不再繼續下去;或者一名主管已經估算出了這個項目要花多長的時間,并會試著影響你的估計。但無論如何,最好從一開始就草擬出一份“誠實”的時間表,以后再進行一些暫時難以作出的決策。目前有許多技術可幫助我們計算出準確的日程安排(就象那些預測股票市場起落的技術),但通常最好的方法還是依賴自己的經驗和直覺(不要忘記,直覺也要建立在經驗上)。感覺一下大概需要花多長的時間,然后將這個時間加倍,再加上10%。你的感覺可能是正確的;“也許”能在那個時間里完成。但“加倍”使那個時間更加充裕,“10%”的時間則用于進行最后的推敲和深化。但同時也要對此向上級主管作出適當的解釋,無論對方有什么抱怨和修改,只要明確地告訴他們:這樣的一個日程安排,只是我的一個估計!

  階段2:如何構建?

  在這一階段,必須拿出一套設計方案,并解釋其中包含的各類對象在外觀上是什么樣子,以及相互間是如何溝通的。此時可考慮采用一種特殊的圖表工具:“統一建模語言”(UML)。請到http://www.rational.com/去下載一份UML規格書。作為第1階段中的描述工具,UML也是很有幫助的。此外,還可用它在第2階段中處理一些圖表(如流程圖)。當然并非一定要使用UML,但它對你會很有幫助,特別是在希望描繪一張詳盡的圖表,讓許多人在一起研究的時候。除UML外,還可選擇對對象以及它們的接口進行文字化描述(《Thinking in C++》里說的那樣,但這種方法非常原始,發揮的作用亦較有限。

  我曾有一次非常成功的咨詢經歷,那時涉及到一小組人的初始設計。他們以前還沒有構建過OOP(面向對象程序設計)項目,將對象畫在白板上面。我們談到各對象相互間該如何溝通(通信),并刪除了其中的一部分,以及替換了另一部分對象。這個小組(他們知道這個項目的目的是什么)實際上已經制訂出了設計方案;他們自己“擁有”了設計,而不是讓設計自然而然地顯露出來。我在那里做的事情就是對設計進行指導,提出一些適當的問題,嘗試作出一些假設,并從小組中得到反饋,以便修改那些假設。這個過程中最美妙的事情就是整個小組并不是通過學習一些抽象的例子來進行面向對象的設計,而是通過實踐一個真正的設計來掌握OOP的竅門,而那個設計正是他們當時手上的工作!

  作出了對對象以及它們的接口的說明后,就完成了第2階段的工作。當然,這些工作可能并不完全。有些工作可能要等到進入階段3才能得知。但這已經足夠了。我們真正需要關心的是最終找出所有的對象。能早些發現當然好,但OOP提供了足夠完美的結構,以后再找出它們也不遲。

  階段3:開始創建

  讀這本書的可能是程序員,現在進入的正是你可能最感興趣的階段。由于手頭上有一個計劃——無論它有多么簡要,而且在正式編碼前掌握了正確的設計結構,所以會發現接下去的工作比一開始就埋頭寫程序要簡單得多。而這正是我們想達到的目的。讓代碼做到我們想做的事情,這是所有程序項目最終的目標。但切不要急功冒進,否則只有得不償失。根據我的經驗,最后先拿出一套較為全面的方案,使其盡可能設想周全,能滿足盡可能多的要求。給我的感覺,編程更象一門藝術,不能只是作為技術活來看待。所有付出最終都會得到回報。作為真正的程序員,這并非可有可無的一種素質。全面的思考、周密的準備、良好的構造不僅使程序更易構建與調試,也使其更易理解和維護,而那正是一套軟件贏利的必要條件。

  構建好系統,并令其運行起來后,必須進行實際檢驗,以前做的那些需求分析和系統規格便可派上用場了。全面地考察自己的程序,確定提出的所有要求均已滿足。現在一切似乎都該結束了?是嗎?

  階段4:校訂

  事實上,整個開發周期還沒有結束,現在進入的是傳統意義上稱為“維護”的一個階段。“維護”是一個比較曖昧的稱呼,可用它表示從“保持它按設想的軌道運行”、“加入客戶從前忘了聲明的功能”或者更傳統的“除掉暴露出來的一切臭蟲”等等意思。所以大家對“維護”這個詞產生了許多誤解,有的人認為:凡是需要“維護”的東西,必定不是好的,或者是有缺陷的!因為這個詞說明你實際構建的是一個非常“原始”的程序,以后需要頻繁地作出改動、添加新的代碼或者防止它的落后、退化等。因此,我們需要用一個更合理的詞語來稱呼以后需要繼續的工作。 這個詞便是“校訂”。換言之,“你第一次做的東西并不完善,所以需為自己留下一個深入學習、認知的空間,再回過頭去作一些改變”。對于要解決的問題,隨著對它的學習和了解愈加深入,可能需要作出大量改動。進行這些工作的一個動力是隨著不斷的改革優化,終于能夠從自己的努力中得到回報,無論這需要經歷一個較短還是較長的時期。

  什么時候才叫“達到理想的狀態”呢?這并不僅僅意味著程序必須按要求的那樣工作,并能適應各種指定的“使用條件”,它也意味著代碼的內部結構應當盡善盡美。至少,我們應能感覺出整個結構都能良好地協調運作。沒有笨拙的語法,沒有臃腫的對象,也沒有一些華而不實的東西。除此以外,必須保證程序結構有很強的生命力。由于多方面的原因,以后對程序的改動是必不可少。但必須確定改動能夠方便和清楚地進行。這里沒有花巧可言。不僅需要理解自己構建的是什么,也要理解程序如何不斷地進化。幸運的是,面向對象的程序設計語言特別適合進行這類連續作出的修改——由對象建立起來的邊界可有效保證結構的整體性,并能防范對無關對象進行的無謂干擾、破壞。也可以對自己的程序作一些看似激烈的大變動,同時不會破壞程序的整體性,不會波及到其他代碼。事實上,對“校訂”的支持是OOP非常重要的一個特點。

  通過校訂,可創建出至少接近自己設想的東西。然后從整體上觀察自己的作品,把它與自己的要求比較,看看還短缺什么。然后就可以從容地回過頭去,對程序中不恰當的部分進行重新設計和重新實現(注釋⑩)。在最終得到一套恰當的方案之前,可能需要解決一些不能回避的問題,或者至少解決問題的一個方面。而且一般要多“校訂”幾次才行。

  構建一套系統時,“校訂”幾乎是不可避免的。我們需要不斷地對比自己的需求,了解系統是否自己實際所需要的。有時只有實際看到系統,才能意識到自己需要解決一個不同的問題。若認為這種形式的校訂必然會發生,那么最好盡快拿出自己的第一個版本,檢查它是否自己希望的,使自己的思想不斷趨向成熟。

  反復的“校訂”同“遞增開發”有關密不可分的關系。遞增開發意味著先從系統的核心入手,將其作為一個框架實現,以后要在這個框架的基礎上逐漸建立起系統剩余的部分。隨后,將準備提供的各種功能(特性)一個接一個地加入其中。這里最考驗技巧的是架設起一個能方便擴充所有目標特性的一個框架(對這個問題,大家可參考第16章的論述)。這樣做的好處在于一旦令核心框架運作起來,要加入的每一項特性就象它自身內的一個小項目,而非大項目的一部分。此外,開發或維護階段合成的新特性可以更方便地加入。OOP之所以提供了對遞增開發的支持,是由于假如程序設計得好,每一次遞增都可以成為完善的對象或者對象組。

  這有點類似“快速造型”。此時應著眼于建立一個簡單、明了的版本,使自己能對系統有個清楚的把握。再把這個原型扔掉,并正式地構建一個。快速造型最麻煩的一種情況就是人們不將原型扔掉,而是直接在它的基礎上建造。如果再加上程序化設計中“結構”的缺乏,就會導致一個混亂的系統,致使維護成本增加。

計劃的回報

  如果沒有仔細擬定的設計圖,當然不可能建起一所房子。如建立的是一所狗舍,盡管設計圖可以不必那么詳盡,但仍然需要一些草圖,以做到心中有數。軟件開發則完全不同,它的“設計圖”(計劃)必須詳盡而完備。在很長的一段時間里,人們在他們的開發過程中并沒有太多的結構,但那些大型項目很容易就會遭致失敗。通過不斷的摸索,人們掌握了數量眾多的結構和詳細資料。但它們的使用卻使人提心吊膽在意——似乎需要把自己的大多數時間花在編寫文檔上,而沒有多少時間來編程(經常如此)。我希望這里為大家講述的一切能提供一條折衷的道路。需要采取一種最適合自己需要(以及習慣)的方法。不管制訂出的計劃有多么小,但與完全沒有計劃相比,一些形式的計劃會極大改善你的項目。請記住:根據估計,沒有計劃的50%以上的項目都會失敗!

  非常佩服作者對軟件構建過程的精辟見解,軟件工程是一門內容非常繁雜的學科,但是作者能夠用淺顯易懂的句子把它描述出來,真的是非常不簡單。軟件工程最早的提出者并不是計算機的專業人士,而是一位建筑設計師,所以軟件工程的很多思想來自于建筑學。經過了幾十年的發展,軟件工程經歷了很多次的蛻變。形成了今天的世界上以一些大公司提出的架構為主的形式:比如微軟提出的COM及COM+以及基于其上的DNA體系,SUN提出的EJB,CORBA,還有BEA、WebLogic、IBM等公司的架構。雖然架構有不同,但是他們的思想都是相通的,架構的作用都是起到輔助開發者實現規范的、科學的軟件開發過程。至于談軟件項目的管理和開發,那么Rational公司就是這方面的鼻祖。綜合來說,目前世界范圍內的軟件工程提倡的就是以漸進的、螺旋式的開發方法構建基于組件的軟件產品。現在說這些東西可能有些畫餅的嫌疑,隨著我們專題討論的繼續深入,這些概念就會很清晰的展現在面前。

  雖然很希望能夠繼續的討論軟件工程方面的東東,但是我們的這個專題畢竟是討論如何編寫優美的程序的,離題還是不要太過分的好,至于軟件工程的詳細討論,我會在接下去的專題中繼續。在接下去的篇幅中,我們會繼續討論程序員和系統分析員之間的差別。

  四個階段

  這里我不想舉一大堆的數字和實例來描述軟件危機和論證軟件工程的重要性,這方面的資料有很多,如果一一列舉的話,會被懷疑別有用心。事實上,建造狗舍和寫一個小的軟件沒有很大的區別。雖然你認為你的能力可以很輕松的完成小型的軟件系統,根本不需要任何的計劃。好!我來問問你,你在寫程序代碼的時候,有沒有過漏這漏那,程序快接近完成的時候卻發現少了一個很重要的模塊;有沒有過在書寫了大量的代碼之后覺得自己寫出來的東西不堪入目,恨不得重頭開始;有沒有過寫程序花了兩天的時間,但是Debug卻花了一個星期的時間;有沒有過聽到軟件的使用者說要改需求,你就恨不得狠狠揍他一頓。如果都沒有,那么只有兩種可能:你是個超級天才,所有人類能夠想到的美好品質你都具有,另一種可能:你根本沒有開發過軟件。

  即便是個人開發的軟件,軟件工程科學中也有相應的方法來指導軟件的開發過程,這種方法叫做PSP(個人軟件開發過程),與此相對的,還有TSP(小組軟件開發過程)。這些被事實證明行之有效的方法包括了一整套的規范,幫助你開發你的軟件,不讓你的程序變得無法控制。可以說,對于任何一個軟件系統來說,只要你花一些時間去設計,即便你的設計僅僅只是在草稿紙上隨便的涂抹,在軟件開發完成后,你就會驚喜的發現,你在軟件開發早期的小小投入,已經為你帶來了額外的好處。

  路標和RUP

  在階段0中,我想最重要的思想就是就是“路標”的概念了,和這個概念相類似的概念還有“周期”和“里程碑”的概念,這些概念在Rational公司的RUP(Rational Unified Process 軟件統一過程)中有詳細的論述。不論這些概念叫做什么,他們體現出來的是一種迭代開發的思想。面對當今的復雜的軟件系統,使用連續的開發方法:如首先定義整個問題,設計完整的解決方案,編制軟件并最終測試產品,是不可能的。需要一種能夠通過一系列細化,若干個漸進的反復過程而生成有效解決方案的迭代方法。

  Rational Unified Process支持專注于處理生命周期中每個階段中最高風險的迭代開發方法,極大地減少了項目的風險性。迭代方法通過可驗證的方法來幫助減少風險--經常性的,可執行版本使最終用戶不斷的介入和反饋。因為每個迭代過程以可執行版本告終,開發隊伍停留在產生結果上,頻繁的狀態檢查幫助確保項目能按時進行。迭代化方法同樣使得需求、特色、日程上戰略性的變化更為容易。(出自《Rational Unified Process白皮書》)

  上面這段好像很復雜,但是他所要說明的思想卻是很簡單的,就拿搭建狗舍來說,你的第一個“路標”可能是要搭一個框架,這個框架是由幾根結實的木頭組成,等到框架完成之后,你會把你的小白叫來,讓他試一下,糟糕的是,這個框架對于小白來說小了一些,這時候你噓了一口氣,因為你原來是打算把整個狗舍搭好以后再叫小白來試一下的,如果你那樣做的話,你剩下的木頭可能就不夠再蓋一間狗舍了。好吧,既然有了些問題,我們就把框架調整一下,可能這個過程也花了你一些木頭,不過所幸木頭還夠。在修整完畢后,你覺得第一步的計劃雖然有些挫折,不過仍可以算是成功的,接下來你就要建立第二個“路標”了:第二個的“路標”是為狗舍釘上墻板和做出一個底座,你可能花了一些時間來思考以及和你的小白商量是否要在墻壁上開一個窗戶和給底座加上輪子,在決定之后,你很快的達成了第二個“路標”。而且在經過了小白的測試后,你發現完全沒有問題,你自己都覺得有些佩服自己了,很快的,你又完成刷油漆等“路標”。整個過程進展的非常順利,而你在做狗舍方面很有天賦的名聲也在你的街坊四鄰間不脛而走。

  很簡單是吧,其實本來就是簡單的,軟件工程的目的就是要把復雜的軟件開發過程條理化,簡單化。記住,在你使用迭代開發方法的時候,它在每個周期后的產品是一份可執行代碼,是一份可以讓你的用戶品頭論足的東西。而這份可執行代碼不僅包括了程序本身,可能還有其他的產成品,例如:文檔等。

  問題和場景

  在階段1中,非常重要的一點是問題描述,在多數情況下,問題描述來自于你的軟件的使用者,就是用戶。用戶的需求決定了問題描述,糟糕的是,用戶多半不懂計算機,對他們來說,他們只能夠用日常的語言來表達自己的需要。而你的任務就是要把他們的語言翻譯成計算機語言,不過并不是指象C那樣的高級語言,而是便于你構造系統的需求描述語言。這同樣很簡單:你只需要問自己幾個問題就可以:在什么場合?有什么條件?做些什么事?回答好這三個問題,你就完成了一個完整的問題描述了。

  舉一個簡單的例子:一個銀行的信貸系統有這樣的問題描述:

  “若顧客采取信用貸款方式,銷售員就請求信用部門的審核人員查核顧客的信用,此時審核人員會向銷售員取得顧客信用編號和銷貨總金額。”

  在某種條件下應該做什么事情,這就是這個問題描述的表現形式,很簡單是吧。

  實際上,這里可以引申出兩個概念:場景(context)和問題(problem),場景指的是一種特定的情況,會導致某種問題的發生;而問題是在某個場景之中,但它也有可能產生出新的場景。

  過程和對象

  有必要說明一下以前基于過程的軟件開發和目前基于對象的軟件開發的不同。在沒有OO的年代里,DFD(Data Flow Diagram 數據流程圖)是一份軟件設計中的非常重要的文檔,注意力的關鍵也是集中在數據如何在各個系統之間傳遞。可是在現在的OO概念中,數據大有為消息(message)所替代的趨勢。比如你到麥當勞快餐店,要花10塊錢買一份漢堡。在DFD的時代,就是這樣表示的:

  如果你用消息表示法來表示話,就是另一種方式:

  怎么樣,你覺得那一種方式更自然呢。(如果你敢回答第一種的話我就...)。再比如上一段話中關于問題描述的例子,如果用傳統的數據描述的方法的話,就會是這樣子的:

  “若采取信用貸款方式,銷售員就將顧客信用編號及總金額交給信用部門的信用審核人員。”

  請比較其中的兩句話:

  “若采取信用貸款方式,銷售員就將顧客信用編號及總金額交給信用部門的信用審核人員。”

  “若顧客采取信用貸款方式,銷售員就請求信用部門的審核人員查核顧客的信用,此時審核人員會向銷售員取得顧客信用編號和銷貨總金額。”

  了解其中的不同之處了嗎,用自然的語言去描述你的問題,這是寫出好的軟件的第一步。

系統分析員的語言

  場景描述是一個很不錯的方法,可是隨著你對系統的分析的深入,參與開發的人員的增加,你漸漸的感覺這種方法不夠用了。原因有很多:文字的描述不夠直觀,不可能到達一種很細致的程度。這時候就需要一種能夠描述問題、描述解決方案、起溝通作用的語言。這就是UML。

  UML(Unified Modeling Language 統一建模語言)是由Rational公司發明,目前由OMG(標準化對象管理機構)維護。作為一種建模語言,UML的定義包括UML語義和UML表示法兩個部分:

  UML語義 

  描述基于UML的精確元模型定義。元模型為UML的所有元素在語法和語義上提供了簡單、一致、通用的定義性說明,使開發者能在語義上取得一致,消除了因人而異的最佳表達方法所造成的影響。此外UML還支持對元模型的擴展定義。

  UML表示法 

  定義UML符號的表示法,為開發者或開發工具使用這些圖形符號和文本語法為系統建模提供了標準。這些圖形符號和文字所表達的是應用級的模型,在語義上它是UML元模型的實例。標準建模語言UML的重要內容可以由下列五類圖(共9種圖形)來定義:用例圖、靜態圖、行為圖、交互圖、實現圖。

  從應用的角度看,當采用面向對象技術設計系統時,首先是描述需求;其次根據需求建立系統的靜態模型,以構造系統的結構;第三步是描述系統的行為。其中在第一步與第二步中所建立的模型都是靜態的,包括用例圖、類圖(包含包)、對象圖、組件圖和配置圖等五個圖形,是標準建模語言UML的靜態建模機制。其中第三步中所建立的模型或者可以執行,或者表示執行時的時序狀態或交互關系。它包括狀態圖、活動圖、順序圖和合作圖等四個圖形,是標準建模語言UML的動態建模機制。因此,標準建模語言UML的主要內容也可以歸納為靜態建模機制和動態建模機制兩大類。

  這樣說,你可能還是不了解UML到底是什么,不過UML并不是我們討論的重點,你只需要知道UML是一種建模語言,他的目的就是在開發團隊之間提供一種通用的、簡單的溝通機制,并且UML是面相對象的。

  上面所說的這些就是階段2的重點所在。使用UML語言對階段1中提出的問題描述進行深化,從各方各面看待問題:順序、流程、數據、狀態、接口等。最終你得到的是一套完整的文檔,做為詳細的程序設計的參考和標準。

  不要累壞自己

  上面說了這么多在編程之前要做的工作,但是要注意的是,不是所有的開發工作都必須做這么多的工作的。對于你來說,抓住最重要的內容,不要涉及到太多的細節。對你寫出來問題描述,必須要仔細的分析,而這里的分析呢,并不是要你用程序來實現你的問題描述,而是你必須從問題描述中分析出對象(object)、事件(event)和消息(message)。例如上面所提到的例子:

  “若采取信用貸款方式,銷售員就將顧客信用編號及總金額交給信用部門的信用審核人員。”

  你可能看到這句話以后就會在想做一個審核信用的函數,參數部分有信用編號和總金額,然后開始設計程序的細節。如果你是這樣干的話,這說明你還沒有真正了解OO的思想,你的開發方式仍然停留在以前基于過程的開發方式中。那么面相對象的分析是怎樣進行的呢。我們還是來看這段話,撇開你的程序,你的語言,你從這句話中獲得了什么信息?是的,你知道說這個企業中有銷售員、有信用審核人員;要求審核顧客信用是他們的工作之一;顧客的信用編號和總金額是審核顧客信用的時候的重要信息。這是任何一個普通的人看到這段話后的感覺,這就是OO的分析(在OO中這種的分析方法稱為OOAD)。其實是很簡單的,和你采用什么樣的程序一點關系都沒有。

  軟件重用(Reuse)是軟件工程中最重要的思想之一,只有軟件重用,才能降低軟件成本,提高軟件的質量。你在對一個軟件進行分析的時候,找出可以重用的對象,有助于你開發高效的軟件系統。正如前面所說的,你不必把軟件分析的過分細致,你只需從中找出關鍵性的、能夠重用的對象就足夠了。剩下的事情,就是對這些對象分配屬性和方法,并充分的使用這些對象就好了。

  還是那個例子:我們已經從中看到了一些對象:銷售員、信用審核人員。但是他們在系統中不具備重用性,至少是重用性不強。信用部門這個對象也存在這個問題。所以不能夠把他們作為底層的對象,我們用一個術語Entity Objects 來稱呼底層對象。那什么是軟件系統中的Entity Objects呢?毛主席教導我們要透過現象看本質。上面的描述中有很多隱含的信息:

  顧客請求信用貸款:這里就包括兩個Entity Objects:顧客、信用貸款。

  銷售員、信用審核人員都是員工,所以員工也是一個Entity Objects。

  觀察一個Entity Objects,你會發現,Entity Objects已經是最小的單位,是使用軟件的用戶(這里是銀行)最小的單位。當然不但是這個軟件有Entity Objects,比如我們最常用的Word,我們可以想象一下它的Entity Objects有什么,可能是一種叫做圖元的Entity Objects,一個圖元包括了文字、圖象以及其他的對象。

  用OO的方法分析你的軟件,從設計到實現都是非常的自然,可能你學習面向對象時是從C++開始的,被其中的虛函數、多態性、多基類繼承搞得一頭霧水。但是實際上OO的方法要比以前的方法簡單的多,不相信?試一試,你就知道了。

  校訂、校訂再校訂

  第3個階段稱為校訂,這個稱呼真是太貼切了,既不是測試,也不是返工。任何事物從誕生起都必須經歷不斷的改進才有可能成熟。(呵呵,說出這么有哲理的話,我都很佩服自己啊。)軟件同樣不例外。事實上,在階段0中,我們就討論了“路標”的概念,當你的第一個路標達成之后,剩下的應該都是屬于校訂的事了。通過和用戶的交互,確定新的“路標”,不斷的改進系統功能,優化系統結構,修正系統Bug。

  正如作者所說的那樣,真正OO的軟件是經得起修改的,由于采用了多層的結構以及面向對象的思想,以前軟件的致命傷(修改)在新的開發方法面前不會是個大問題。(注意,這并不是說你可以無規劃構建你的軟件)

  由于以前的系統大多會將GUI、事務處理、數據存儲都做在一起,當你需要修改一個地方的時候,你就會發現問題的嚴重性:一個小小的需求變動都意味著你的系統將面臨傷筋動骨般的修改。在OO的時代里,所有的對象的訪問都是通過接口(Interface)進行的,對象中方法的改變并不會接口產生影響,也就是說,調用該接口的模塊不用做任何的修改。另外,如果你打算把你的系統的界面從C/S方式向B/S方式改變,同樣不會有問題,你可以很容易的把GUI部分從原有的系統中剝離出來。軟件的修改對你來說不再是一個惡夢。


網載 2011-02-22 02:19:36

[新一篇] 跨進微軟技術世界的第一步------Microsoft隨筆

[舊一篇] 程序創業:創業者的十大“必殺技”
回頂部
寫評論


評論集


暫無評論。

稱謂:

内容:

驗證:


返回列表