從程序員到系統區分員(轉)
發表時間:2024-01-20 來源:明輝站整理相關軟件相關文章人氣:
[摘要]大家應該對這兩個詞很熟悉了,但是對詞里包含的意義可能并不是特別清楚。首先必須說明的是,程序員和系統分析員不存在誰高級誰低級的分別,他們是兩種職業,對職業技能的要求完全不同。所以厲害的程序員就是系統分析員的說法是不對的。當然,系統分析員的技能要求他必須要懂得如何寫程序,但是他的重心在于如何把一個很大...
大家應該對這兩個詞很熟悉了,但是對詞里包含的意義可能并不是特別清楚。首先必須說明的是,程序員和系統分析員不存在誰高級誰低級的分別,他們是兩種職業,對職業技能的要求完全不同。所以厲害的程序員就是系統分析員的說法是不對的。當然,系統分析員的技能要求他必須要懂得如何寫程序,但是他的重心在于如何把一個很大的項目切割成適合個人的小塊,然后將這些小塊組織起來。程序員的職責就是如何更好更快的實現這些小塊。
在這章之前,我們討論的都是一個合格的程序員應當具備的技能,當然不止那一些內容。之所以在這里插進來討論系統分析員的事情,是因為我們的欄目叫做軟件工程而不是程序員從入門到精通之類的。
在正式開始之前,我們還是來看在Thinking In Java中作者對分析和設計的一段精辟見解:
分析和設計
面向對象的范式是思考程序設計時一種新的、而且全然不同的方式,許多人最開始都會在如何構造一個項目上皺起了眉頭。事實上,我們可以作出一個“好”的設計,它能充分利用OOP提供的所有優點。
請原諒在這里突然出現了OOP這個詞,他的意思是面相對象,雖然在之前沒有提到,但是在現在OO概念滿天飛的軟件世界里,大家應該對他不會太陌生。這里我簡要的說明一下。在之前我介紹的實際上都是在很早以前程序寫作流傳下來的經驗(什么,教我們老古董,打他!),但是以前的非OO(就是基于過程)的軟件設計方法目前在國際上已經很少采用,所以我這里講軟件設計的時候所有的概念都是基于OO的。即使OO的概念很簡單的啦,大家思考一下,我們再學習C++的時候一開始使用的類不都是一些動物啦、正方形啦之類的,都是生活中的例子,對吧。其實OO就是我們看世界的一種方式。可是最早由于計算機技術的不發達,我們不得不用一些很奇怪的描述來表達我們的意思,只有這樣計算機才能理解,很笨不是嗎。比如我們必須使用參數、過程、函數。所以當時的軟件設計方法都是基于過程的。舉一個簡單的例子來顯示OO設計方法和基于過程的設計方法之間的差別:一句簡單的日常短語--“我吃飯”,用OO的方法來表述還是“我吃飯”,可是如果用基于過程的方法來描述的話就變成“我吃飯(飯)”,是不是很別扭呢。如果大家覺得對于OO的方法還有什么問題的話,可以去看一下軟件工程專欄下的另一篇專題:《Thinking In Java賞析》
有關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公司就是這方面的鼻祖。綜合來說,目前世界范圍內的軟件工程提倡的就是以漸進的、螺旋式的開發方法構建基于組件的軟件產品。現在說這些東西可能有些畫餅的嫌疑,隨著我們專題討論的繼續深入,這些概念就會很清晰的展現在面前。
雖然很希望能夠繼續的討論軟件工程方面的東東,但是我們的這個專題畢竟是討論如何編寫優美的程序的,離題還是不要太過分的好,至于軟件工程的詳細討論,我會在接下去的專題中繼續。在接下去的篇幅中,我們會繼續討論程序員和系統分析員之間的差別。