心智圖資源庫 軟體框架設計的藝術
軟體框架設計的藝術,想要將知識傳授給其他人的時候,就會因為他們沒有類似我們的經驗,也就很難說服他們接受我們的知識。
編輯於2024-04-10 17:25:12軟體框架設計的藝術
序言
“API一旦發布,便於我們永恆共存”
想要將知識傳授給其他人的時候,就會因為他們沒有類似我們的經驗,也很難說服他們接受我們的知識
理論與理由
”藝術“還是”工程“
API的重要獨特性:一致性
組內如何一致?
合作無間
共同的願景
公共術語
P2 一年後,我證明了當時的猜測。因為Netbeans是一個開源項目,有一個API吸引了一個外部的開發人員。開始的時候,這位外部程式碼貢獻者主要是做一些修復Bug的工作。隨後,他開始單獨負責一個子項目,並設計相關的API。原先負責設計這個API的人說他發現這個子專案的API變得越來越差,但他找不出原因,希望我幫一隻手。他說:非常不喜歡這些新的API,更不想把它們整合到他負責的專案中。但他也同樣說不清楚這些新的API到底有什麼問題。最後,他說這些新的API看起來和他原來的設想不一致。我曾經也對他說過類似的話。以我的標準來評估的話,他所寫的API與NetBeans的API的設想不一致!
方法論
理性主義
經驗主義
無緒
淺層理解
對某些事物的了解程度只限於掌握使用方法即可
深層理解
掌握某種事物背後的原則、規律
大多時候」淺層理解「已經夠
針對性無緒(selective cluelessness)
某些內如需要深入了解
應用程式開發的無緒原則
盡量讓最終負責整合的相關人員不需要深入了解系統也可以把整合工作做好
對象:人
評價API好壞的標準
Why?
我們希望能夠將大塊的構建模組”無緒“的集合成應用程序
what?
方法、類別、字段簽名
文件(unix管道)
環境變數和命令列選型
文字訊息(toString)
協定
行為
判斷相容性最重要的方式是”正常運行“,但這一點卻是由內部具體實現決定的
null回傳值
國際化
……
Quality
可理解性
設計人員和開發人員之間交流的途徑
範例的重要性
一致性
降低學習曲線
保持相容
可見性
提供”入口“,以便找到需要的解決方案
基於實際或預期的目標與任務
使用者不關心具體的類
簡單的任務應該要有簡單的方案
普通的使用者
擴充的使用者
保護投資
多為用戶考慮
不斷變化的目標
向後相容
原始碼相容
二進位相容
功能相容
容易被遺漏
態度,「好老闆」不會抱怨客戶
面向用例的重要性
用例
我該怎麼做
場景
你應該先做這件事,然後再做那件事就好了
API設計評審(優良API規則)
使用案例驅動的API設計
設計API時,要基於一些具體的場景和對API的認識進行抽象分析,最終給予設計
API設計的一致性
API往往是由多位設計者來完成的,但整個團隊中必須能夠保持「最佳實踐」的一些基本原則。一個介面設計得再好,只要它違反整個團隊的一致性,就寧願退而求其次
簡單明了的API
簡單而常見的任務應該更容易處理。如果基於用例驅動的方式進行設計,就可以很容易的透過那些可以簡單實現的場景來驗證這些API是否可以完成那些重要的用例
少即是多
一個API對外提供的功能應該只包括用例中說明的功能。這樣可以避免出現所需的功能與實際提供的功能兩者之間出現差異。
支援改進
必須能夠持續的維護該類別庫。即使出現新的需求,或是原作者離開,都不會放棄這個類庫
設計實戰
隻公開你要公開的內容
添加容易,移除困難
發布第一個版本時,移除不必要的內容
方法優於字段
除了static和final聲明的基本類型、string常數、枚舉和不變物件外,其他欄位都不應該被公開
工廠方法優於函數
工廠方法傳回值不一定是聲明型別的實例,可以是子類別的實例
每次返回的對像也不一定是新建的對象,可以將其緩存
同步控制,對創建物件前後的程式碼進行統一處理
讓所有內容不可更改
如不希望擁有子類,就應該讓其不可被繼承
避免濫用setter方法
如無必要,絕不要在正式的API中聲明setter方法
setEnable
可能上下文敏感
isEnable判斷,使setEnable失去意義
盡可能透過友元方法來公開功能
java預設的package存取方式,內部類
賦予物件創作者更多權利
存取權限
避免暴漏深層繼承
程式碼復用
功能復用
「繼承」不是用來改變具體的行為,而是用來增加一些額外的動作
如果去繼承一個類,只是為了切換某些方法的執行路徑,那麼這種做法應予以避免
建議:避免深層繼承,定義程式接口,並讓使用者來實現這些接口
面向介面而非實作進行程式設計
抽象定義(介面)與實作分離
合作
向API使用者講清楚:使用APi時,應遵循正確的原則。如果需要使用一個API就要遵守API的原則,不要破壞
清楚的說明API的需求,定義對應的用例,幫助API設計者實現這樣的API
protected方法無法移除,導致子類別修改
在介面中增加抽象方法,會強迫其非抽象子類別實作此方法
模組化架構
物件導向並不能避免義大利麵式的編程
模組化的目的:實現各組成部分的松耦合
模組化架構將規範與實作分離
在規範所在的模組中,至少會有一個小的“入口”
依賴注入
Spring
Netbean lookup
擴充
P111 2001年,我們給JavaOne大會提交了一份名為「組件定位與協作」的議題,該議題中的內容與本章多少有些關係,我們認為該議題涉及的內容對於所有的模組化程序都很重要。然而,當時的JavaOne會議的組委會可能僅僅因為覺得這個議題的名稱不夠酷,或者可能因為他們覺得組件這個詞用得太濫了,要知道「組件」這個詞幾乎包含了所有可以想像的內容,所以沒有接受該議題。直到2006年,我和同事Tim Boudreau又提交了一份類似的議題,名為「模組化架構中那些發現注入和依賴注入的模式」。果然,如我們所料,議題被組委會接受了。這說明一定要找到能夠貼近目標人群的術語才能打動他們。一旦聽到「依賴注入」這個詞,他們的心就被打動了。就像API這個字一樣,恰當的名稱有益交流。對使用者來說,他們越容易理解API這個詞,就越容易接受API的相關內容。
其實還有幾個詞:架構、模式
設計API時要區分其目標用戶群
API
可以新增但不能移除
供他人呼叫來完成某些功能
final類
內聚,自包含
SPI
Service Provider Interface
可以移除但不可增加
供其他人擴充API功能
介面
避免兩者混用
合理分解API
API
SPI
NetBeans的分類
核心API
支援API
核心SPI
支援SPI
根據使用者群體的不同需求來組織你的API結構
牢記可測試性
Mock對象
為API提供Mock對象
測試程式碼是規範的一部分
好工具讓API設計更簡單
嚮導
讓客戶盡快的上手
專案的第一目標快速推向市場
NetBeans中每一項重要的技術都有一個對應的嚮導來建立初始的基礎框架
相容性測試套件
面向SPI用戶和API實現者
與其他API協作
謹慎使用第三方API
包裝模式
只暴露抽象內容
曝光的越多,演進的餘地就越小
強化API一致性
代理和組合
避免API的誤用
所有的層次之間都需要保持一致性。
API具體運行時的一些內容
」臭名遠揚「—與其抱怨用戶,不如改變自己的態度
」保衛者「—自動化測試
同步與死鎖
正確且恰當的描述其線程模型
Java Monitors中的陷阱
繼承影響synchronized
對於公開的API,不能將對外方法申明為同步
處處陷阱的Java同步與死鎖
聲明式程式設計
基本想法:不是讓API使用者一步步告訴程式如何做,只需要告訴程式他們的結果,然後交給API去完成
NetBeans Lookup實現,只需要簡單XML描述,不需要使用者註冊、登出
自描述性
日常生活
現實生活充滿了變化因素,理論的東西不可能一成不變的用在生活中。不僅要知道哪些事情可行,哪些事情不可行,還要知道如何運作才能可行
極端意見有害無益
API必須
是漂亮的
是正確的
如果為了正確性而犧牲了易用性,那麼可能會引發更多的問題
Mercurial和SVN
盡量簡單
是高性能的
絕對相容
是對稱的
API設計中的矛盾
自相矛盾
Wiki定義:“同時相信兩個互相矛盾的觀點,而沒有意識到兩者是矛盾的”
安全部門
飛機安檢
開發人員抱怨的事項總是不斷,如評審、程式設計規範,等等。但API監護人需要時時保持警醒的狀態,否則可能會因為一個小小的疏忽而引發問題。另一方面,不是出個小問題,至少說明了你所做的工作確實很有用。
少數派報告
改進API
團隊協作
在提交代碼前進行程式碼評審
說服開發人員為他們的API提供文檔
倒推法
在寫程式碼之前
概述
FAQ
盡責的監控者
工具監控所有需要關注的變更狀況
沒有工具,需要一個」全知全能「的人
接收API的補丁
只接受正確的建議
制定要求
要求不能太複雜
利用競賽遊戲來改進API設計技巧
由 www.xmindchina.net 提供下載