什么是好代碼

在我心目中,好代碼必須要符合以下四條標準

  1. 正確
  2. 易懂
  3. 易改
  4. 高效

而糟糕的代碼,只有一個衡量標準,那就是你在閱讀或修改代碼時罵的臟話的程度與次數(shù)

1. 正確

這是最基本的要求,代碼當然是滿足需求,運行起來正確無誤,這一點并不那么容易做到,尤其是運行環(huán)境比較復(fù)雜,各種異常情況較多的時候。

好代碼要考慮周到,各種邏輯流程和意外情況的處理要面面俱到, 單元和模塊測試要覆蓋異常邏輯和邊界

對于服務(wù)質(zhì)量 SLA 要考慮周全, 簡單說起來就是滿足用戶的七大基本需求

  1. 功能性
  2. 穩(wěn)定性
  3. 可靠性
  4. 性能
  5. 可維護性
  6. 可移植性
  7. 靈活性

我們的代碼既要防錯,也要容錯,足夠的健壯,不易出錯,不怕出錯,網(wǎng)絡(luò)崩了,電源斷了,磁盤滿了等異常情況,都要有相應(yīng)的應(yīng)對措施。

2. 易懂

  • 好代碼必須是看起來很舒服,很干凈,容易理解

象一篇好文章,不羅嗦,容易懂,有頭有尾。

各個層次,模塊及函數(shù)分工明確,各司其職, 望文知義,代碼無需注釋即可自我描述。

接口即契約,要足夠簡單,易懂易用, 窄接口好過寬接口。

其實只要符合代碼規(guī)范,命名簡單易懂,代碼就沒那么丑。

參見 Google 的代碼風格指南

有空翻翻“重構(gòu)”那本書中的臭味介紹, 可以提高品味。

有一些基本軟件開發(fā)的普適原則,能遵守盡量遵守。

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ù)代碼, 請抽象或重用,切勿將重復(fù)的代碼散落在多處,否則修改代碼時就知道有多痛苦了

SRP: Single Responsibility Principle

單一職責原則: 就一類而言, 應(yīng)該僅有一個引起它變化的原因,就一個函數(shù)來說,它應(yīng)該只做好一件事,貪多嚼不爛。

也有一個別稱 DOTADIW - Do One Thing and Do It Well 就做一件事并做好它

OCP: Open Close Principle

"software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification

一個軟件實體如類、模塊和函數(shù)應(yīng)當對擴展開放,對修改關(guān)閉。即軟件實體應(yīng)盡量在不修改原有代碼的情況下進行擴展。

我們可以在原有的類中添加字段或方法進行擴展,或者給函數(shù)添加新的參數(shù)(C++可賦予一個默認值, Java 干脆重載一個新函數(shù)),以及擴展出一個新的子類。

而對于已經(jīng)暴露出去的API 以及接口, 類及公有函數(shù),盡量不要修改它們,因為你需要說服你的客戶(其他使用這塊代碼的模塊)做相應(yīng)的修改,而你往往并不清楚有多少客戶在使用它。

LSP: Liskov Substitution Principle

LSP替換基類原則: 子類型應(yīng)該可以替換掉它們的基類型,或者說父類型擁有子類型的全部共性,子類型擁有父類型的全部特征。

ISP: Interface Segregation Principle

ISP接口隔離原則: 不應(yīng)該強迫客戶依賴于它們不用的方法, 接口屬于客戶, 不屬于它所在的類層次結(jié)構(gòu),接口是生產(chǎn)者與消費者之間的契約,應(yīng)該精煉簡約,生產(chǎn)者只通過接口提供服務(wù),而消費者也只通過接口來調(diào)用服務(wù)。

DIP: Dependency Inversion Principle

DIP依賴倒置原則: 抽象不應(yīng)該依賴于細節(jié), 細節(jié)應(yīng)該依賴于抽象。

我們要依賴于高層接口,而不是依賴于底層實現(xiàn),接口是不會輕易改變的,而實現(xiàn)可以修改和替換
時下常用的插件機制,依賴注入方法都遵循這一原則

-- 上述 5 個原則常被統(tǒng)稱為 SOLID 原則

3. 易改

好代碼要易于測試和修改, 適當?shù)某橄?,封裝和模塊化有利于后期的修改和重構(gòu)。

封裝好復(fù)雜性,區(qū)分開經(jīng)常變化與基本不變的代碼, 適當抽取易變參數(shù)作為配置。
為未來的變化設(shè)計有限的靈活性,無需多改就能很容易的擴展新功能。

還是書里那句話,高內(nèi)聚,低耦合。將依賴倒置,做好抽象,封裝和模塊化,代碼就不難改。

例如最常用的 MVC 模式,為什么我們要分成模型,視圖和控制器三塊,原因之一就在于分開易變的與不易變的,分開不會在一起變化的部分,減小每次修改的范圍。

如果某個方面的功能需要修改,最好是改個配置, 其次是擴展個類或函數(shù), 或者傳個不同參數(shù),最差的就是改多個地方,要做多個判斷, 還要做霰彈式的修改。

好代碼要易于觀測和調(diào)試,也就是說日志和度量數(shù)據(jù)要完備,可以分級,分模塊進行日志和度量數(shù)據(jù)的調(diào)整與分析,自帶度量 API, 調(diào)試 API 及控制臺為佳

好代碼還要與時俱進,自我蛻變,寫代碼時要將不變的與易變的分開,技術(shù)再怎么變,人性不會變,掙錢的業(yè)務(wù)變化也不會太大。一般來說,要封裝好業(yè)務(wù)邏輯,核心業(yè)務(wù)不會大變,即使推到重寫也要理解和參照老系統(tǒng)的業(yè)務(wù)流程。

人會變老,代碼也會,新業(yè)務(wù),新技術(shù),新架構(gòu),新框架層出不窮,要大膽試驗,小心引入,逐步演進,不必抱殘守缺,也不要盲目沖動,把握住變與不變的平衡,經(jīng)常變的地方應(yīng)該盡量少,且盡量方便修改。

引述一下,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! 命名空間是個絕妙點子, 讓我們那樣做得更多

4. 高效

好的代碼應(yīng)該充分利用可用的資源,性能達標,沒有無謂的浪費和等待。
使用合適的算法和數(shù)據(jù)結(jié)構(gòu),對 CPU, 內(nèi)存,網(wǎng)絡(luò)等資源的使用有節(jié)制。

在關(guān)鍵算法,關(guān)鍵路徑上要做算法復(fù)雜度分析,應(yīng)用大 O 分析法以及Amdahl加速定律等進行定性和定量分析,再結(jié)合性能度量數(shù)據(jù)進行調(diào)優(yōu)。

我們不但要給業(yè)務(wù)數(shù)據(jù)制定 KPI, 也要給性能數(shù)據(jù)制定 KPI, 例如通常用的到 UPS - Usage, Performance 和 Saturation, 通過觀測,度量和分析這些 KPI 再做有的放矢的調(diào)優(yōu)。

壓力測試(stress testing)和性能分析(performance profiling)是必不可少的方法。
一般來說,高效率要在設(shè)計,實現(xiàn)和測試多方面都要做有針對性的考慮,通過度量驅(qū)動,想清楚代碼上線怎么生成和收集度量數(shù)據(jù),如何通過度量進行調(diào)優(yōu)。

參考

  • 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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. 好代碼必須是看起來很舒服,很干凈 象一篇好文章,不羅嗦,容易懂,有頭有尾 各個層次,模塊及函數(shù)分工明確,各司...
    老瓦在霸都閱讀 603評論 0 1
  • 前言 最近在團隊推行Code Review,遇到一個頭痛的問題。當向伙伴的代碼提一個comment時,他們不解為什...
    CatchZeng閱讀 5,300評論 1 19
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,525評論 19 139
  • 本文出自《Android源碼設(shè)計模式解析與實戰(zhàn)》中的第一章。 1、優(yōu)化代碼的第一步——單一職責原則 單一職責原則的...
    MrSimp1e0閱讀 1,911評論 1 13
  • 今天周六我的生日,女兒送了一份生日禮物!給我畫了一副生日畫!謝謝女兒的用心,你的好意媽媽收到了! 上午奶奶發(fā)的面準...
    瑤媽1閱讀 605評論 0 0

友情鏈接更多精彩內(nèi)容