何為整潔
5S哲學(xué)
- 整理 seiri 或謂組織
- 整頓 seiton 或謂整齊
- 清楚 seiso 或謂清潔
- 清潔 seiketsu 或謂標準化
- 身美 shitsuke 或謂紀律(自律)
名言警句
- 整潔近乎虔誠 Cleanliness is next to godliness
- Test Obsessed 沉迷測試
整潔的代碼怎么產(chǎn)生的
定義
- 整潔即優(yōu)雅
- 整潔的代碼是由某位特別在意它的人寫的,幾乎無任何改進的余地
- 能通過所有測試
- 沒有任何重復(fù)代碼 =最重要=
- 體現(xiàn)系統(tǒng)中的全部設(shè)計理念
- 包括盡可能少的實體,比如類、方法、函數(shù)等
自我總結(jié)
- 1.消除重復(fù)
- 2.提高代碼自我表達能力(一定程度少依賴注釋)
任何門派都絕非正確。不過,身處某一門派,我們須全身心善技,排斥其他門派,學(xué)有所成后再轉(zhuǎn)投其他門派,擴展自己的知識和技能
童子軍軍規(guī)
- 讓營地比你來的時候更干凈
最好你經(jīng)受過的代碼都比你剛接手的時候更整潔
命名與函數(shù)
命名
- 名副其實
- 如果名稱需要注釋來補充,那就不算名副其實
- 避免誤導(dǎo)
- 做有意義的區(qū)分
- 使用讀的出來的名稱
- 使用可搜索的名稱
- 更改變量時,一鍵搜索就可以找到所有
- 避免使用編碼
- 避免思維映射
- 別扮可愛
- 言到意到, 意到言到
- 每個概念對應(yīng)一個詞
- 別用雙關(guān)語
- 避免將同一個詞用于不同目的。同一術(shù)語不同概念即雙關(guān)語
- 使用解決方案領(lǐng)域名稱
- 使用源自問題領(lǐng)域的名稱
- 添加有意義的語境
- 不要添加沒用的語境
函數(shù)
- 短小
- 函數(shù)的第一規(guī)則是短小,第二規(guī)則是更短小
- 20行封頂最佳
- 只做一件事
- 函數(shù)應(yīng)該做一件事。做好這件事。只做這件事
- 檢測是否做一件事:看其能否繼續(xù)拆分
- 每個函數(shù)一個抽象層級?
- switch語句?
- 使用描述性的名稱
- 函數(shù)參數(shù)
- 最理想的參數(shù)數(shù)量是0,其次是1,再次是2
- 無副作用
- 分割指令與詢問
- 函數(shù)要么做什么事,要么回答什么事,二者不可兼得
- 函數(shù)應(yīng)修改某對象的狀態(tài)或是返回改對象的有關(guān)信息
- 使用異常替代返回錯誤碼
- 抽取try/catch代碼塊
- 最好把try/catch代碼塊抽取出來,另外形成函數(shù)
- 將處理整體,try,catch三部分放在一個函數(shù)內(nèi),形成三個子函數(shù)部分
- 錯誤處理就是一件事
- error錯誤碼統(tǒng)一處理
- 抽取try/catch代碼塊
- 別重復(fù)自己
- 結(jié)構(gòu)化編程
- 如何寫出這樣的函數(shù)
- 先寫后打磨
“我寫函數(shù)時,一開始都冗長而復(fù)雜。有太多縮進和嵌套循環(huán)。有過長的參數(shù)列表。名稱是隨意取的,也會有重復(fù)代碼。不過我會配上一些單元測試,覆蓋每行丑陋的代碼。然后我會打磨這些代碼,分解函數(shù)、修改名稱、消除重復(fù)。我縮短和重新安置方法。有時我還拆散類。同時保持測試通過”
“我并不從一開始就按照規(guī)則寫函數(shù)。我想沒人做得到”
函數(shù)是語言的動詞,類是名詞
注釋與格式
注釋
- 別給糟糕的代碼加注釋,重新寫吧
- 注釋是一種必須的惡,是彌補代碼表達意圖時遭遇的失敗
- 注釋不能美化糟糕的代碼
- 用代碼來闡述
- 語義化簡單判斷函數(shù)
- 好注釋
- 法律信息
- 提供信息的注釋
- 對意圖的解釋
- 闡釋
- 警示
- ToDo注釋:解釋為何無所作為,將來會產(chǎn)生什么影響
- 放大:放大某種看來不合理之物的重要性
- 公共API中的解釋性語句
- 壞注釋
- 喃喃自語
- 多余的注釋
- 誤導(dǎo)性注釋
- 循規(guī)式注釋:比如自帶的函數(shù)注釋,要寫函數(shù)名、作用、值...
- 日志式注釋
- 廢話注釋
- 可怕的廢話
- 能用函數(shù)或變量時就別用注釋
- 位置標記 長長的/////和****
- 括號后面的注釋:破壞代碼可讀性,注釋應(yīng)獨立成行
- 歸屬與署名:寫上日期和姓名看起來很純。版本控制器會說明一切
- 注釋掉的代碼:就像沒丟掉的垃圾
- html格式的注釋
- 非本地信息:文不對碼
- 信息過多+廢話過多
- 不明顯的聯(lián)系:注釋和代碼聯(lián)系不緊密
- 函數(shù)頭:短函數(shù)好名字比注釋強多了
- 非公共API中的解釋性語句
格式
- 我大多數(shù)小于200多行,沒有一個超過500行的單個文件完全可以構(gòu)造一個出色的系統(tǒng)
垂直格式
- 向報紙學(xué)習(xí)
- 大綱:入口
- 頭部:必用部分
- 主題:核心邏輯
- 尾部:可能用部分
- 概念間垂直方向的間隔
- 適當(dāng)?shù)睦每崭耖g隔不同函數(shù),不同類
- 垂直方向上的靠近
- 緊密相關(guān)的代碼、變量定義應(yīng)該相互靠近
- 垂直距離
- 變量生命應(yīng)盡可能靠近其使用位置,本地變量應(yīng)在函數(shù)頂部
- 實體變量應(yīng)在類的頂部
- 概念相關(guān)的代碼應(yīng)該放在一起
- 垂直順序
- 自上而下:被調(diào)用者放在執(zhí)行調(diào)用的函數(shù)下面,建立自頂向下貫穿源碼代碼模塊的良好信息流
把最重要的概念先出來,并包含最少的細節(jié)來描述他,底層細節(jié)最后出來,讓旁觀者從最初的幾個函數(shù)獲知要旨,而不至于沉溺細節(jié)
橫向格式
- 正常代碼程度應(yīng)在80字符以內(nèi),上限120個字符
- 利用空格將相關(guān)性較弱的事物分開(如運算符的左右部分,for循環(huán)中的語句)
- 保持一定程度的水平對齊(上下)
- 必要的縮進
- 空范圍(while中無語句也要加大括號)
- 制定統(tǒng)一團隊風(fēng)格
對象和數(shù)據(jù)結(jié)構(gòu)
將對象設(shè)置為私有有一個理由:我們不想其他人依賴這些變量。我們還想在心血來潮時能自由修改其類型或?qū)崿F(xiàn)
前端暫時我沒有用到類,現(xiàn)在看這部分還很迷
- 數(shù)據(jù)抽象
- 數(shù)據(jù)、對象的反對稱性
- .....
錯誤處理
錯誤處理的存在在于,前端不準用戶看到報錯;有些錯誤可能導(dǎo)致程序崩潰、影響下一步運行
錯誤處理很重要,但如果它搞亂了代碼邏輯,就是錯誤的做法
- 使用異常而非返回碼=沒搞懂=
- 先寫Try-Catch-Finally語句
- 所有try的范圍,只在可能出錯的最小集合集中使用
- 別讓用戶察覺異樣
- 使用不可控異常
- 可控異常的代價就是違反開放/閉合原則。如果你在方法中拋出可控異常,而catch語句在三個層級之上,你就得在catch語句和拋出異常處之間的每個方法簽名中聲明該異常。這意味著對軟件中低層級的修改,都將波及較高層級的簽名。修改好的模塊必須重新構(gòu)建、發(fā)布,即便它們自身所關(guān)注的任何東西都沒改動過。
- 你應(yīng)該創(chuàng)建信息充分的錯誤信息,并和異常一起傳遞出去,在消息中,包括失敗的操作和失敗類型。
- 給出異常發(fā)生的環(huán)境說明
- 如果你的應(yīng)用程序有日志系統(tǒng),傳遞足夠的信息給catch塊,并記錄下來
- 依調(diào)用者需要定義異常類
- 定義常規(guī)流程
- 針對常規(guī)異常:創(chuàng)建一個類或配置一個對象,用來處理特例。將異常行為封裝到特例對象中。
- 別返回null值
- js如何防止接口返回空值,或不存在字段
如果將錯誤處理隔離看待,獨立于主要邏輯之處,就能寫出強固而整潔的代碼
如何整理混亂的代碼
說完如何保持整潔的代碼,如果遇到了一團混亂的代碼,我們要如何將它整理的井井有條呢?首先我們要能夠明確的找到混亂地方,我們就要像剝洋蔥一樣一點一點的拆解代碼,小幅的進行改動。每次改動,都有前邊提到的測試來保證我們并沒有破壞現(xiàn)有的功能。
當(dāng)我們要整理一大坨代碼的時候,個人經(jīng)驗,如果不知道如何改動的時候,可以先從最基本的入手,看懂一段代碼并且明確這是做了一件事之后,提取出來,取一個具有描述意義的名字。當(dāng)將代碼這樣拆解成一個一個的方法之后,結(jié)構(gòu)就清晰了很多。之后我們就會聞到很多的code smell,發(fā)現(xiàn)很多的重復(fù)。關(guān)于如何發(fā)現(xiàn)和解決code smell,可以參考《重構(gòu)》這本書,這本書列舉了很多的code smell,并且給出了很好的解決方案。