本篇寫于讀<Code Complete>之后,面對實際設計中的問題時產生的一些感悟,在這里和大家一起分享。。
第一頁
設計是個“鬼”命題。為什么呢?它又鬼在哪呢?
A wicked problem as one that could be clearly defined only by solving it or by solving part of it.
---Horst Rittel and Melvin Webber
這里是大師的定義。只有你解決了或者部分解決這個問題的時候,你才能清楚的定義它。
用白話講,只有你做了,你才知道它是怎么回事,怎么才能做好這件事。
所以,我常常拿到一個開發功能而又無從下手時,除了尋找支援,詢問別人,唯一剩下的路就是嘗試著去做。雖然是膽顫心驚、如履薄冰,但是做著做著就明白了。
我想,大師告訴我們這是一個鬼命題,第一,是告訴我們第一次摸著石頭過河是人類的認知規律,開始時做錯了是正常的;第二,就是讓我們勇敢的去嘗試。
第二頁
設計是一個迭代的過程。
大家先看這幅圖。
這里典型的瀑布式設計“分析==>設計==>編碼==>測試”。這個過程每一個階段都有明確的輸入/輸出,每個階段都有一個交付件。這對我們的管理者是個福音,因為這樣子,項目的進展一目了然,項目就可控了。所以說,這個過程是為Mananger寫的。所以,有了這句話“Oh, I write specs to keep managers happy and then code the thing the way I want “
因為,事實上,我們程序員感覺到的設計過程不是這樣的。而是這樣的:
同樣,它也是基于瀑布模型的。只是增加了一個逆向過程,使得我們在下一階段發現問題時,可以回過頭來修正。
我們現在來想想這個問題,為什么大家會說 “設計文檔沒有用”?因為作為一個過程的輸出結果,設計文檔有個致命的問題:無法保證文檔與代碼同步。表現在兩個方法:
1.無法保證設計文檔的結果一定會反映在代碼中(除了人去看,無法證實)。
2.設計的成果,要通過重復勞動在代碼中來表現。
3.后期代碼結構的變化,很難表現在設計文檔中。
所以我說,設計階段的輸出應該是一份Rose文檔和一份簡要的設計補充說明。這樣,我們用Rose的逆向工程能力來表現現有代碼的實際結構/接口;用Rose的代碼生成能力來表現接口的修改。我們現在來試一下。
(Rose使用展示)
這樣,我們將模塊、類、類接口等都表現在Rose中,而將偽碼以注釋方式寫在代碼中。
我們少了多少事啊~~
這里附帶著強調一點,里程碑很重要。沒有了里程碑,迭代的設計很就成了死循環。不可控的項目也不會是好項目。
第三頁
分而治之
這是人類解決復雜問題的通用解決方法。
對應于我們軟件設計過程,就是“產品?模塊?類?方法”的逐層分解過程。
產品 |
0層 |
模塊與模塊/模塊與用戶的契約(public 方法) |
模塊 |
1層 |
類之間契約(friend 方法) |
類 |
2層 |
偽碼/私有方法 |
其中,模塊確定了與其它模塊之間、與用戶之間的契約(模塊間公共接口);類確定了類之間的契約(包內公共接口);方法確定了私有方法。下一層總是服務于上一次。
這個過程通過Rose完全能夠完成。所以,設計階段不等于寫設計文檔。設計文檔僅僅是輸出結果。
第四頁
自上而下和自下而上
這是兩種不同的思考過程。自上而上是由抽象到具體,自下而上則相反,由具體到抽象。上面提到的,分而治之,逐層分解就是一種自上而下的過程。
一般來講,自上而下比較容易點,也是軟件設計中比較提暢的一點。我們經常強調的“依賴反轉”,依賴于抽象,而不是依賴于具體。都是自上而下的抽象分解過程。
那么, 在設計中還有一個關注點“分離變化點”。是我們隔離變化,將變更的影響降低的一種方法。這里就有個問題,如果你不再往下看,找出具體是什么會變化,你怎么將變化隔離封裝?這個時候,要的就是“自下而上”的分析。
佛教有一句“法無定法”,意思是說做好一件事,不一定有一個固定的法則。當你用一種方法直不下去時,不妨試試其它方法。所以,自上而下與自下而上并不矛盾。
第五頁
原型。
設計的時候,經常有這樣一個問題。以前沒搞過,現在這么做行不行呢?心里沒底。那怎么辦?寫個原型。
就在代碼中寫。需要的時候,在進入編碼階段時,重復利用。
(比如這次我要開發個向導,我發現有個現成的框架。但是不知道該怎么用,不知道能不能滿足需要。所以,我按照現在規格,寫了一點原型代碼。發現可以用。)
但是這里有個分寸的問題,就是不要寫的太多。能夠證實你的想法就可以了。一是因為咱們還有里程碑計劃,有時間點的壓力。二是因為,這部分代碼只是試驗,并不可靠,寫的越多,隱藏的問題就會越多。
第六頁
設計到什么時候結束?
下列兩個條件中滿足任意一個結束:
-
你覺的再設計就成了寫代碼了;
-
你沒有時間了;
第一個結束點,對各個人不一樣,只要你感覺你能寫出代碼了就行。所以,對于經過多個版本的人可能會結束的早一些。
第二個結束點,沒有辦法的事,無論好壞,認命,趕快把文檔搞的貌似結束,在編碼階段再嘗試補救。
結束