深模塊/淺模塊
作者使用深模塊和淺模塊的概念來形容模塊封裝的不同程度蓬戚。
深模塊:即暴露給用戶極少的必要接口福贞,其它的實現(xiàn)細(xì)節(jié)盡量封裝在模塊內(nèi)部/接口背后仁烹,這樣便于用戶使用和模塊對外接口的穩(wěn)定性厢塘。典型的深模塊有l(wèi)inux i/o接口郊闯,java垃圾回收等。
淺模塊:即暴露大量的接口給用戶贪庙,讓用戶自己選擇如何組合使用蜘犁,這樣設(shè)計接口的好處是增加了用戶使用的靈活度,但是止邮,大多數(shù)時候往往增加了用戶選擇的負(fù)擔(dān)这橙。例如鏈表的接口設(shè)計就是屬于淺模塊,另外java的FileInputStream和BufferInputStream大多數(shù)時候要同時使用的設(shè)計就屬于淺模塊的一個例子导披,其實可以將是否使用緩沖區(qū)的選擇封裝在通用接口后屈扎,因為大部分情況都是要使用緩存的,對于少部分不使用的情況撩匕,可以通過另一個接口或者通過增加參數(shù)來提供特例使用鹰晨。
因此作者推薦設(shè)計成深模塊從而減輕用戶使用的負(fù)擔(dān)。作者認(rèn)為應(yīng)該設(shè)計更少的通用接口,而不是帶有很多細(xì)節(jié)的專用接口模蜡。關(guān)于接口的通用性漠趁,qsort是一個不錯的例子。
異常處理
用戶面對異常時哩牍,很多情況下會不知如何處理棚潦。毫無節(jié)制地將異常拋給上層用戶是不負(fù)責(zé)任的表現(xiàn),異常應(yīng)該盡可能少膝昆。幾種處理異常的方法:
- 屏蔽異常:一些無關(guān)緊要丸边,不影響用戶感受的異常應(yīng)該在API內(nèi)部屏蔽處理,而不應(yīng)該拋給用戶荚孵。
- 匯聚異常:很多瑣碎的同類異常妹窖,應(yīng)該在內(nèi)部匯聚后拋到上層一處處理。
- 系統(tǒng)崩潰:一些致命的異常收叶,例如內(nèi)存耗盡而導(dǎo)致的內(nèi)存申請失敗骄呼,最好讓系統(tǒng)直接崩潰,而不是拋出異常判没。
總之異常處理是要仔細(xì)斟酌的蜓萄,仔細(xì)分辨哪些是不需要拋出內(nèi)部可以消化的,盡量多地在內(nèi)部消化異常澄峰,同時識別必須拋出的異常嫉沽,堅決拋出。
多次設(shè)計
以設(shè)計接口為例俏竞,同一個功能多設(shè)計幾個接口有助于你的思考绸硕,從而提煉出更好的接口,雖然有時候你一次就能設(shè)計出比較好的接口魂毁,但是玻佩,建議你還是要堅持這么做,因為習(xí)慣一旦養(yǎng)成席楚,力量不容小覷咬崔。
命名
- 糟糕的命名不僅是影響可讀性,有時候還會是引入bug的隱患烦秩。例如作者的例子刁赦,因為沒有在變量命名上區(qū)分fileblock和diskblock,導(dǎo)致錯用變量內(nèi)存被覆蓋的隱晦的bug闻镶,用了半年之久才定位出來。
- 一個變量的定義和使用之間的距離越遠(yuǎn)丸升,它的命名應(yīng)該相對越長铆农。模塊之間變量的定義,應(yīng)該加上模塊前綴,而一些簡單的循環(huán)變量只要使用i墩剖,j就可以了猴凹。
- 一個好的命名需要花些心思和時間,但這是一項值得的投資岭皂,因為它對代碼后期的可維護(hù)性帶來很大收益郊霎,并且隨著這項技能越來越熟練,它將會花的時間越來越少爷绘,那時它帶來的好處將是免費的书劝。
注釋
關(guān)于注釋這個頗具爭議的話題,作者傾向于先寫注釋土至,并且也提倡只寫必要的注釋购对。注釋其實是一種抽象工具,在你開始寫代碼實現(xiàn)之前陶因,將框架代碼寫出來骡苞,并且加好注釋,這其實是對思路的一次整理楷扬,同時解幽,由于當(dāng)前還沒有實現(xiàn)細(xì)節(jié)的干擾,注釋更多是在抽象層面描述烘苹,它將更加能夠體現(xiàn)設(shè)計思路躲株,也更加穩(wěn)定。一個難點在于修改代碼的同時要及時修改注釋螟加,作者的建議是通過一些紀(jì)律和規(guī)則來解決徘溢,注釋應(yīng)該離它所解釋的代碼盡可能近,這樣修改代碼的時候就容易看到這些注釋同時修改它們捆探。
重構(gòu)
重構(gòu)是一個永恒的話題然爆,需要把重構(gòu)看成一種投資。如果在增加一個需求/解決一個bug時黍图,可以在2小時簡單修補完成曾雕,也可能發(fā)現(xiàn)一個架構(gòu)調(diào)整點可以更好地實現(xiàn),同時具備更好地擴展性助被,但需要2周才能完成剖张,這種情況下,項目很難抵住快速實現(xiàn)的誘惑揩环,或者說時間上根本不允許2周才完成搔弄。但是一旦有了重構(gòu)的意識,就會去想有沒有2天能夠完成相同重構(gòu)效果的方案丰滑,如果確實沒有顾犹,可以使用快速實現(xiàn)方案,同時記錄下這個重構(gòu)點,在下個迭代周期要堅決預(yù)留時間進(jìn)行相關(guān)重構(gòu)炫刷。這是保持架構(gòu)持續(xù)演進(jìn)的必要工作擎宝,也是會產(chǎn)生持續(xù)收益的戰(zhàn)略投資。
敏捷軟件開發(fā)
關(guān)于敏捷軟件開發(fā)浑玛,作者將其一系列實踐歸納為戰(zhàn)術(shù)設(shè)計范疇绍申,很多人忽略了整體的戰(zhàn)略設(shè)計,這點也批判了在敏捷軟件實踐的一個誤區(qū)顾彰,那就是完全不要設(shè)計极阅。其實真實的敏捷踐行是需要有戰(zhàn)略設(shè)計,即軟件架構(gòu)設(shè)計的拘央。這點從Martin Fowler對DDD的贊譽中可見一斑涂屁。
性能優(yōu)化
關(guān)于性能優(yōu)化,作者的觀點是不需要時刻關(guān)注性能灰伟,而是對一些性能耗時的操作要了解拆又,對這些有限的點有所關(guān)注就行。例如栏账,對于內(nèi)核網(wǎng)絡(luò)報文轉(zhuǎn)發(fā)效率不高要有所了解帖族,那么在需要高速轉(zhuǎn)發(fā)的場景下,你需要專門的硬件來處理報文轉(zhuǎn)發(fā)挡爵,一開始的這個方向性的決策很重要竖般。但是,你不需要對每一行for語句的性能過分關(guān)注茶鹃,這些細(xì)節(jié)可能會由編譯器進(jìn)行優(yōu)化涣雕,程序員自己的優(yōu)化未必有效果,甚至?xí)鸬椒醋饔帽蒸妗W詈笳豕阅軆?yōu)化一定要通過工具進(jìn)行測量后,找到關(guān)鍵路徑進(jìn)行優(yōu)化疗韵,這樣是效果最好的兑障,也是最高效的。
簡潔的代碼往往是性能高效的蕉汪,除非有非常明顯的性能提升流译,否則不要以代碼復(fù)雜為代價來提升性能。