1. 好代碼必須是看起來很舒服,很干凈
象一篇好文章,不羅嗦,容易懂,有頭有尾
各個層次,模塊及函數(shù)分工明確,各司其職, 望文知義
接口即契約,要足夠簡單,易懂易用, 窄接口好過寬接口
其實只要符合代碼規(guī)范,命名簡單易懂,代碼就沒那么丑
看看重構(gòu)那本書中的臭味介紹, 可以提高品味
2. 好代碼要符合基本的編碼原則
首先我們先談?wù)剮讉€軟件開發(fā)的普適原則
KISS
KISS: Keep It Simple and Straight 保持簡單和直接, 適當隱藏復(fù)雜性
或者
KISS: Keep It Simple and Stupid 保持簡單, 象傻瓜一樣, 不要讓別人多加思考
軟件接口或 API 的設(shè)計要讓人一看就明白, 一看就知道作者的意圖和想法, 如何使用它, 有什么結(jié)果和可能的異常及副作用. 看過很多代碼, 踩過許多坑, 大多是作者或者我自己使用了出乎意料的實現(xiàn), 不做好必要的抽象和封裝, 復(fù)雜的判斷和算法到處都是
DRY – Don't Repeat Yourself
別重復(fù)你自己, 如有重復(fù)代碼, 請抽象或重用
SRP - Single Responsibility Principle
單一職責原則: 就一類而言, 應(yīng)該僅有一個引起它變化的原因
也有一個別稱 DOTADIW - Do One Thing and Do It Well 就做一件事并做好它
OCP - Open Close Principle
開放封閉原則: 軟件實體(類,模塊,函數(shù)等)應(yīng)該是可以擴展的, 但是不可修改
LSP
LSP替換基類原則: 子類型應(yīng)該可以替換掉它們的基類型
DIP
DIP依賴倒置原則: 抽象不應(yīng)該依賴于細節(jié), 細節(jié)應(yīng)該依賴于抽象
ISP
ISP接口隔離原則: 不應(yīng)該強迫客戶依賴于它們不用的方法, 接口屬于客戶, 不屬于它所在的類層次結(jié)構(gòu)
REP
REP重用發(fā)布等價原則: 重用的粒度就是發(fā)布的粒度
CCP
CCP共同封閉原則: 包中的所有類對于同一類性質(zhì)的變化應(yīng)該是共同封閉的. 一個變化若對一個包產(chǎn)生影響, 則將對包中所有的類產(chǎn)生影響, 而對于其他的包不造成任何影響
CRP
CRP共同重用原則: 一個包中的所有類應(yīng)該是共同重用的. 如果重用了包中的一個類, 那么就要重用包中的所有類
ADP
ADP無環(huán)依賴原則: 在包的依賴關(guān)系圖不允許存在環(huán)
SDP
SDP穩(wěn)定依賴原則: 朝著穩(wěn)定的方向進行依賴.
SAP
SAP穩(wěn)定抽象原則: 包的抽象程度應(yīng)該和其穩(wěn)定程度一致
設(shè)計模式和面向?qū)ο笤O(shè)計中講了很多,不再贅述
3. 好代碼要易于理解,測試和修改
封裝好復(fù)雜性,區(qū)分開經(jīng)常變化與基本不變的代碼, 適當抽取易變參數(shù)作為配置
還是書里那句話,高內(nèi)聚,低耦合,依賴倒置
例如最常用的 MVC 模式,為什么我們要分成模型,視圖和控制器三塊,原因之一就在于分開易變的與不易變的,分開不會在一起變化的部分,減小每次修改的范圍。
如果某個方面的功能需要修改,最好是改個配置, 其次是加幾行代碼或傳個不同參數(shù),最差的就是改多個地方,加多個判斷, 作霰彈式修改
4. 好代碼要考慮周到
各種邏輯流程和意外情況的處理要面面俱到, 單元和模塊測試要覆蓋異常邏輯和邊界
對于服務(wù)質(zhì)量 SLA 要考慮周全, 簡單說起來就是滿足用戶的以下基本需求
- 功能性
- 穩(wěn)定性
- 可靠性
- 性能
- 可維護性
- 可移植性
- 靈活性
5. 好代碼要與時俱進,自我蛻變
人會變老,代碼也會,新業(yè)務(wù),新技術(shù),新架構(gòu),新框架層出不窮,要大膽試驗,小心引入,逐步演進,不必抱殘守缺,也不要盲目沖動
一般來說,要封裝好業(yè)務(wù)邏輯,核心業(yè)務(wù)不會大變,即使推到重寫也要理解和參照老系統(tǒng)的業(yè)務(wù)流程
最后,引述一下,Python 之禪
Python 之禪
雖然說的是Python, 其實適用于多數(shù)編程語言
| 英文 | 中文 |
|---|---|
| Beautiful is better than ugly. | 美比丑好 |
| Explicit is better than implicit. | 明顯比隱晦好 |
| Simple is better than complex. | 簡單比復(fù)雜好 |
| Complex is better than complicated. | 復(fù)雜比難懂好 |
| Flat is better than nested. | 扁平比嵌套好 |
| Sparse is better than dense. | 稀疏比稠密好 |
| Readability counts. | 可讀性很重要 |
| Special cases aren't special enough to break the rules. | 特例也不要打破這個原則 |
| Although practicality beats purity. | 盡管實踐會破壞純潔性 |
| Errors should never pass silently. | 錯誤還是不能讓其悄然滑過 |
| Unless explicitly silenced. | 除非你明確聲明不用理會它 |
| In the face of ambiguity, refuse the temptation to guess. | 別讓人來猜測不確定的可能性 |
| There should be one-- and preferably only one --obvious way to do it. | 應(yīng)該有一個且只有一個比較好的明顯的方法來做事 |
| Although that way may not be obvious at first unless you're Dutch. | 盡管那個方法可能并非一開始就顯而易見 |
| Now is better than never. | 現(xiàn)在就做比永遠不做好 |
| Although never is often better than right now. | 盡管永遠不做經(jīng)常比馬上就動手做好 |
| If the implementation is hard to explain, it's a bad idea. | 如果實現(xiàn)很難解釋清楚, 那它不是一個好主意 |
| If the implementation is easy to explain, it may be a good idea. | 如果實現(xiàn)很容易說清楚, 那它是個好主意 |
| Namespaces are one honking great idea – let's do more of those! | 命名空間是個絕妙點子, 讓我們那樣做得更多 |
簡單總結(jié)一下
- 文學(xué)化編程,想清楚,整明白,胸有成竹,下手千行
- 測試驅(qū)動,不做額外的無用功,不追求覆蓋率,為的是增強自信心
- 度量驅(qū)動,代碼上線怎么辦,如何易于度量和調(diào)優(yōu)
- 為未來設(shè)計有限的靈活性,高聚低耦,無需多改容易擴展
- 考慮周全,足夠的健壯,不易出錯,不怕出錯
參考
- Agile Software Development, Principles, Patterns, and Practices by Robert C. Martin
- Clean code by Robert C. Martin
- Refactoring: Improving the Design of Existing Code Martin Fowler