第五章 軟體建構中的設計
Design in Construction
5.1 設計中的挑戰
Design Challenges
核心話題「設計是什麼?」
設計是個棘手的問題
Design is a Wicked Problem
設計是沒有固定設計的流程
Design is a Sloppy Process
設計就是確定取捨和調整優先順序
Design is About Trade-Offs and Priorities
設計環繞限制
Design Involves Restrictions
設計是不確定的
Design Is Non-deteministic
設計是啟發學習的過程
Design is a Heuristic Process
設計是演化產生的
Design is Emergent
5.2 關鍵的設計概念
Key Design Concepts
核心話題「設計+軟體 又是什麼?」
軟體的首要技術使命:管理複雜性
Software’s Primary Technical Imperative: Managing Complexity
(源自《人月神話-Brooks》的《沒有銀彈》)我的見解:
管理複雜性,可以看做「管理」+「複雜性」
「複雜性」是軟體的本質性,這是無法改變也沒有一個殺手級工具可以解決問題。
所以目前可以做的就是做好「管理」這件事。
附屬性問題和本質性問題 What?
Accidental and Essential Difficulties
管理複雜性的重要 Why?
Importance of Managing Complexity
如何對付複雜性 How?
How to Attack Complexity
理想的設計特性
Desirable Characteristics of a Design
也就是要邁向的方向(這樣做很好,但是不見得非得要這樣做不可。)
設計的層次
Levels of Design
(模組化設計的解析,看設計書《萬物》)軟體系統的的五個層次:
- 軟體系統
- 子系統或封裝
- 類別
- 常式
- 常式內部
在這個章節,最常見的一句話就是「這樣做,是好的,但是怎麼做,沒有對錯」在設計的角度來看,一直都是這樣沒錯!軟體是想法的產物,所以「概念整體性」完全支配了整個設計,第五章強調的是Brooks說過的概念整體性,在第六章繼承了這樣的想法,將它應用在建立類別上,而第六章討論時會遇到一些「哲學上的問題」在本書也有詳盡的討論。
5.3 設計積木:啓發學習法
Design Building Blocks: Heuristics
核心話題「什麼是『設計的過程』」
找尋真實世界中的物件 Who?
Find Real-World Objects
用程式語言訴說著什麼樣的角色?
制訂一致的抽象(概念)
Form Consistent Abstractions
這些被描述的程式行為,有沒有歸納過?共同的抽象特徵建立成Base Class
介面本身為概念表達核心,不代表函數內部的細節。
我的見解:
使用類別將專注於介面本身,函數內部是類別設計師的創意
(Design is not how it looksDesign is not just what it looks like and feels like. Design is how it works)
(使用類別的使用者-軟體工程師...管它怎麼做的,好用就對了)
封裝執行細節
Encapsulate Implementation Details(6.2節)
當繼承能簡化設計就用繼承Inherit When Inheritance Simplifies the Design(6.3節)
善用虛擬函數+動態連結的強大力量,除此之外,還是看看6.3節
隱藏秘密(資訊隱藏)
Hide Secrets (Information Hiding)
秘密和隱私權(class的作用)
Secrets and the Right to Privacy
- 某個可能變更的區域
- 某種檔案格式
- 資料型別的執行方式
- 某個需要隔離的區域
An Example of Information Hiding
第一版
int main()
{
int id;
id = ++g_maxId; //告訴別人,我是怎麼做的,容易找到破解方法或預測方式
return 0;
}
第二版
int NewId(){ return ++g_maxId; }
int main()
{
int id; //告訴別人,可以對ID做四則運算。
id = NewId();
return 0;
}
第三版
typedef IdType int;
IdType NewId()
{
return ++g_maxId;
}
int main()
{
IdType id;
id = NewId();
return 0;
}
需要被隱藏的兩種秘密Two Categories of Secrets
資訊要被隱藏起來「秘密」主要分為兩類:
- 隱藏複雜性
- 隱藏變更資料來源
資訊隱藏的障礙Barriers to Information Hiding
資訊過度分散循環相依性
類別資料誤認為全域資料
- 全域資料帶來難題(用在哪個函數?用了嗎?誰用過?)
- 類別資料降低風險
「架構層次」、「程式碼層次」的效能減損,做好資訊隱藏就可以避免掉這兩點。
時間過早擔心:「物件具現化」和「常式呼叫」等有隔外的層次,間接存取物件將導致執行階段的效能惡化。(想太多了,想要在維護程式痛苦?還是執行執式痛苦?)
資訊隱藏的價值 Why?
Value of Information Hiding
- 看見多少細節,就要考慮多少細節
- 有可能用到的Code較多
盡可能的減少看見的細節,保持程式順利執行。←花時間
減少辨別Code是否有用到的思緒。←花時間
減少花時間在不必要的地方,以達到管理複雜度的目標
確定在哪些領域可能改變
Identify Areas Likely to Change
Design Pattern的精神預測不同程度的變化
Anticipating Different Degrees of Change
步驟:
- 找
- 分離 包成類別
- 隔離 設計介面
保持鬆散的耦合
Keep Coupling Loose
耦合的準則
Coupling Criteria
- 規模
- 可視性
- 彈性
//耦合的彈性準則
LookupVacationBenefit ( Employee _E );
//otherClass 就不可以丟進去當參數了。
LookupVacationBenefit ( date _D, level _L );
Employee.GetDate();
Employee.GetLevel();
otherClass.GetDate();
otherClass.GetLevel(); //兩個類別都可以丟進去執行了。
耦合的種類Kinds of Coupling
- 簡單參數藕合:參數是基本型別
- 簡單物件藕合:類別裡面宣告物
- 物件參數藕合:物件3當作參數,從物件2傳給物件1(須要先知的藕合)
- 語意的藕合:(沒有邏輯,complier看不出來的藕合)(詳見內文繁中版p.104)
尋找常用的設計模式
Look for Common Design Patterns
設計模式有一個潛在的陷阱,就是強迫程式碼使用模式。不要使用「硬要用」的態度,使用設計模式。
其他啟發學習法
Other Heuristics
- 追求高內聚力
Aim for Strong Cohesion - 建置層次結構
Build Hierarchies - 嚴格描述類別契約
Formalize Class Contracts - 責任劃分
Assign Responsibilities - 為測試而設計
Design for Test - 避免失誤
Avoid Failure - 有意識地選擇綁定時間
Choose Binding Time Consciously - 集中控制
Make Central Points of Control - 考慮使用暴力法
Consider Using Brute Force - 繪製圖表
Draw a Diagram - 保持你的設計模組化
Keep Your Design Modula
使用啟發學習法的方針
Summary of Design Heuristics
設計啟發法最有效的方針之一:不要執著於單一的方法上。我的見解:
也許,在工業設計上,就是指「設計方法」這件事吧?!沒有一個方法吃遍天下,但是遇見什麼問題,使用什麼方法似乎是好用的方法,卻不是唯一能用的方法。
使用啟發學習法的原則
Guidelines for Using Heuristics
- 了解問題
- 設計一個計劃
- 執行計畫
- 檢查
5.4 設計的實踐
Design Practices
之前講「設計特性」的啓發學習法現在講「設計實踐」的啓發學習法
重覆(疊迭)
iterator
iterator : 承前經驗地重覆。
分而治之
Divide and Conquer
沒有人的頭腦能裝下一個複程式的全部細節《如何解題》-Polya,在解決數學問題中的建議
- 理解問題
- 設計計畫
- 執行計畫
- 回顧你的方法
「由上而下」和「由下而上」的設計方法
Top-Down and Bottom-Up Design Approaches
Top-Down & Botton-Up可以同時存在,而且是人類本能似的運作。
Top-Down : 找零件。
Botton-Up : 組積木。
實驗原型
Experimental Prototyping
寫出用於問答特定設計問題、量最少且能隨時捨棄的程式碼。(這時就可以不用考慮維護的問題,God Object的問題、架構的問題,而程式也不應該大到這種程度。除非是架構的Prototype)
協同設計
Collaborative Design
找伙伴交流- 聊天(隨便找人問想法)
- 討論(認真找人問想法)
- Code review(進行雙人設計)
- 客觀角色(讓不懂的人略懂)
- 依第21章的結構安排一次正式視察
- 自己當自己的伙伴(自己忘掉再來看)
- 社群
什麼樣的設計才算足夠?
How Much Design is Enough?
最大的設計錯誤,源自於「誤以為自己已做得很足夠」沒有什麼設計上的困難,是因為做了太多的設計。
80% 寫程式
20% 寫文件
記錄你的設計工作
Capturing Your Design Work
(各種寫文件的方法!來寫網誌吧!)5.5 對流行的方法評論
「應用設計方法時,你的方法愈教條化,能解決的現實問題就越少」- Plaugerd「設計所有的細節」和「完全不設計」的這兩種
看法極端的人所提倡的這兩種方法,,是唯一兩個永遠是錯的方法!
更多資源
Additional Resources
軟體設計的一般問題
Software Design, General
軟體設計理論
Software Design Theory
設計模式
Design Patterns
廣義的設計
Design in General
標準
Standards
我的見解:
也許現代工業可以給我們一些方向。
「Less is more」 - Ludwig Mies van der Rohe
「Form follows function」 - Horatio Greenough
「Good design is...」十誡 - Dieter Rams
- 好的設計是創新的 (Good design is innovative)
- 好的設計是實用的 (Good design makes a product useful)
- 好的設計是唯美的 (Good design is aesthetic)
- 好的設計讓產品說話 (Good design helps a product to be understood)
- 好的設計是謙虛的 (Good design is unobtrusive)
- 好的設計是誠實的 (Good design is honest)
- 好的設計堅固耐用 (Good design is durable)
- 好的設計是細緻的 (Good design is thorough to the last detail)
- 好的設計是環保的 (Good design is concerned with the environment)
- 好的設計是極簡的 (Good design is as little design as possible)
沒有留言:
張貼留言
(什麼是留言欄訊息?)