2019-05-18 代碼重構(gòu)

代碼優(yōu)化基本原則
易讀性?xún)?yōu)先
如果不是性能瓶頸,就不要為了性能而改寫(xiě)代碼
復(fù)雜性守恒原則:無(wú)論你怎么寫(xiě)代碼,復(fù)雜性都是不會(huì)消失的
推論:如果邏輯很復(fù)雜,那么代碼看起來(lái)就應(yīng)該是復(fù)雜的。如果邏輯很簡(jiǎn)單,代碼看起來(lái)就應(yīng)該是簡(jiǎn)單的。

命名
程序員三大難題
變量命名
緩存失效
循環(huán)邊界
可見(jiàn)變量命名的重要性

1、注意詞性
普通變量/屬性用「名詞」
var person = {
name: 'Frank'
}
var student = {
grade: 3,
class: 2
}
bool變量/屬性用「形容詞」或者「be動(dòng)詞」或者「情態(tài)動(dòng)詞」或者「hasX」
var person = {
dead: false, // 如果是形容詞,前面就沒(méi)必要加 is,比如isDead 就很廢話
canSpeak: true, //情態(tài)動(dòng)詞有 can、should、will、need 等,情態(tài)動(dòng)詞后面接動(dòng)詞
isVip: true, // be 動(dòng)詞有 is、was 等,后面一般接名詞
hasChildren: true, // has 加名詞
}
普通函數(shù)/方法用「動(dòng)詞」開(kāi)頭
var person = {
run(){}, // 不及物動(dòng)詞
drinkWater(){}, // 及物動(dòng)詞
eat(foo){}, // 及物動(dòng)詞加參數(shù)(參數(shù)是名詞)
}
回調(diào)、鉤子函數(shù)用「介詞」開(kāi)頭,或用「動(dòng)詞的現(xiàn)在完成時(shí)態(tài)」
var person = {
beforeDie(){},
afterDie(){},
// 或者
willDie(){}
dead(){} // 這里跟 bool 沖突,你只要不同時(shí)暴露 bool dead 和函數(shù) dead 就行,怕沖突就用上面的 afterDie
}
button.addEventListener('click', onButtonClick)
var component = {
beforeCreate(){},
created(){},
beforeMount(){},
mounted(){},
beforeUpdate(){},
updated(){},
activated(){},
deactivated(){},
beforeDestroy(){},
destroyed(){},
errorCaptured(){}
}
容易混淆的地方加前綴
div1.classList.add('active') // DOM 對(duì)象
div2.addClass('active') // jQuery 對(duì)象
不如改成
domDiv1 或 elDiv1.classList.add('active')
div2.addClass('active') 屬性訪問(wèn)器函數(shù)可以用名詞div.text() // 其實(shí)是 div.getText()div.text('hi') // 其實(shí)是 $div.setText('hi')
爛代碼示例
https://coolshell.cn/articles/4758.html

2、注意一致性

介詞一致性
如果你使用了 before + after,那么就在代碼的所有地方都堅(jiān)持使用
如果你使用了 before + 完成時(shí),那么就堅(jiān)持使用
如果你改來(lái)改去,就「不一致」了,不一致將導(dǎo)致「不可預(yù)測(cè)」
順序一致性
比如 updateContainerWidth 和 updateHeightOfContainer 的順序就令人很別扭,同樣會(huì)引發(fā)「不可預(yù)測(cè)」
表里一致性
函數(shù)名必須完美體現(xiàn)函數(shù)的功能,既不能多也不能少。
比如

function getSongs(){
return $.get('/songs).then((response){
div.innerText = response.songs
})
}
就違背了表里一致性,getSongs 表示獲取歌曲,并沒(méi)有暗示這個(gè)函數(shù)會(huì)更新頁(yè)面,但是實(shí)際上函數(shù)更新了 div,這就是表里不一,正確的寫(xiě)法是

要么糾正函數(shù)名

function getSongsAndUpdateDiv(){
return $.get('/songs).then((response){
div.innerText = response.songs
})
}
要么寫(xiě)成兩個(gè)函數(shù)

function getSongs(){
return $.get('/songs)
}
function updateDiv(songs){
div.innerText = response.songs
}
getSongs().then((response)=>{
updateDiv(response.songs)
})
時(shí)間一致性
有可能隨著代碼的變遷,一個(gè)變量的含義已經(jīng)不同于它一開(kāi)始的含義了,這個(gè)時(shí)候你需要及時(shí)改掉這個(gè)變量的名字。
這一條是最難做到的,因?yàn)閷?xiě)代碼容易,改代碼難。如果這個(gè)代碼組織得不好,很可能會(huì)出現(xiàn)牽一發(fā)而動(dòng)全身的情況(如全局變量就很難改)

改代碼
如果你的代碼有單元測(cè)試,那么改起來(lái)就很放心。如果沒(méi)有單元測(cè)試,就需要用「小步快跑」的策略來(lái)修改。
小步快跑的意思是說(shuō),每次只修改一點(diǎn)點(diǎn),測(cè)試通過(guò)后,再修改一點(diǎn)點(diǎn),再測(cè)試,再修改一點(diǎn)點(diǎn)……如此反復(fù)。
那么如何修改一點(diǎn)點(diǎn)呢?《重構(gòu)》這本書(shū)介紹了很多方法,但是講得挺啰嗦的,如果你有時(shí)間可以看看。
兩個(gè)經(jīng)久不衰的方法。

一、使用函數(shù)來(lái)改代碼
步驟:

將一坨代碼放到一個(gè)函數(shù)里
將代碼依賴(lài)的外部變量作為參數(shù)
將代碼的輸出作為函數(shù)的返回值
給函數(shù)取一個(gè)合適的名字
調(diào)用這個(gè)函數(shù)并傳入?yún)?shù)
這個(gè)函數(shù)里的代碼如果超過(guò) 5 行,則依然有優(yōu)化的空間,請(qǐng)回到第 1 步

二、使用對(duì)象來(lái)改代碼
如果使用了函數(shù)改造法改造后,發(fā)現(xiàn)有太多的小函數(shù),則可以使用對(duì)象講這個(gè)函數(shù)串起來(lái)。
「this 是函數(shù)和對(duì)象的橋梁」,用 this 來(lái)串聯(lián)這個(gè)對(duì)象和所有函數(shù)。


image.png

一些固定的套路
表驅(qū)動(dòng)編程(《代碼大全》里說(shuō)的)
所有一一對(duì)應(yīng)的關(guān)系都可以用表來(lái)做
自說(shuō)明代碼(以 API 參數(shù)為例)
把別人關(guān)心的東西放在顯眼的位置


image.png

表驅(qū)動(dòng)示例(表驅(qū)動(dòng)容易減少if else)
優(yōu)化前(一個(gè)月有多少天)


image.png

優(yōu)化后
image.png

image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。