我為簡短的回答向龐大的問題致歉镜沽。
真理啊,不要太留意我巫橄。
引言
模式和重構(gòu)之間聯(lián)系緊密,在一定程度上來說湘换,設(shè)計(jì)模式的目的就是為許多重構(gòu)行為提供目標(biāo)。
在實(shí)際的項(xiàng)目開發(fā)中统阿,一次到位是非常少見的事彩倚,無論時(shí)間是否充裕,第一版的代碼往往單純的以實(shí)現(xiàn)功能為目標(biāo)扶平。后續(xù)帆离,如果有時(shí)間或者要求較高,可能會有一次结澄,兩次重構(gòu)哥谷。如果是小企業(yè)興許就會這么交差。然而對于我們開發(fā)者而言麻献,長時(shí)間大量編寫低質(zhì)量代碼假以時(shí)日就會變得只會寫這種類型的代碼们妥,這對職業(yè)發(fā)展是不利的。
即使只以提升自身為目標(biāo)勉吻,適當(dāng)?shù)牧私庥嘘P(guān)代碼重構(gòu)的知識將對日后的開發(fā)工作大有脾益监婶。
作為一個初級前端,本筆記旨在簡單介紹一些重構(gòu)的原則齿桃,目標(biāo)惑惶,手段。會比較偏頗短纵,只具備一定的參考價(jià)值带污。
這里重構(gòu)主要針對JavaScript。
代碼重構(gòu)
提煉函數(shù)
函數(shù)是JavaScript的一等公民香到,平日的開發(fā)不是在和函數(shù)打交道就是在和對象打交道鱼冀。
當(dāng)然我知道函數(shù)也是一個對象,把它當(dāng)對象來使用是毫無問題的养渴,可以玩出很多花樣雷绢。
針對函數(shù)有這么幾點(diǎn)重構(gòu)建議。
- 假如一個函數(shù)名本身就很長理卑,包含了很多功能它就應(yīng)該被重構(gòu)翘紊。
- 可以獨(dú)立出來的代碼最好獨(dú)立出來成為一個單獨(dú)的函數(shù),所謂拆分藐唠。
- 獨(dú)立出來的函數(shù)需要良好的命名帆疟,它可以起到注釋的作用鹉究。
舉例來說
function getInfo(){
...//一段業(yè)務(wù)邏輯,也許是數(shù)據(jù)處理
$.ajax({
url:'xx',
data:'xx',
type:'post',
success:function(data){
...//一段業(yè)務(wù)邏輯踪宠,也許是數(shù)據(jù)處理和展示
}
})
}
//這是一個很常見的函數(shù)自赔,如果有必要,它可以拆分成
function getInfo(){
handleData(data)
$.ajax({
url:'xx',
data:'xx',
type:'post',
success:showData
})
}
function handleData(data){
...//一段業(yè)務(wù)邏輯柳琢,也許是數(shù)據(jù)處理
}
function showData(data){
...//一段業(yè)務(wù)邏輯绍妨,也許是數(shù)據(jù)處理和展示
}
//就像我說的如果有必要..如果不需要考慮復(fù)用我會考慮把拆分出來的兩個函數(shù)寫到主函數(shù)里面去。
拆分出功能對于了解一個復(fù)雜函數(shù)內(nèi)部在干什么很重要柬脸,同時(shí)維護(hù)分別的小函數(shù)他去,比維護(hù)一個大而復(fù)雜的函數(shù)要容易的多。
合并重復(fù)的條件片段
假如一個函數(shù)中有一些條件分支語句倒堕,而這些分支語句中有一些重復(fù)的語句灾测,這樣,我們就可以進(jìn)行去重把這些重復(fù)語句提取出來垦巴。
這個沒什么太多好說的很常見比如一個分頁跳轉(zhuǎn)媳搪。
function paging(currPage){
var jumpPage= 1;
if(currPage <=0){
jumpPage= 0;
jump(jumpPage)
}else if(currPage>totalpage){
jumpPage= 10
jump(jumpPage)
}else{
jumpPage=currPage
jump(jumpPage)
}
}
//雖然我個人認(rèn)為不會有人寫這么累贅的函數(shù),這里只是為了舉例可以把jump(jumpPage)提出來
function paging(currPage){
var jumpPage= 0;
if(currPage <=0){
jumpPage= 0;
}else if(currPage>totalpage){
jumpPage= 10
}else{
jumpPage=currPage
}
jump(jumpPage)
}
//類似這種感覺骤宣,只要是做數(shù)據(jù)前處理的秦爆,基本都以提出來
//如果有必要你可以把這里的重構(gòu)成多態(tài)的形式,只是在這個例子里沒有必要涯雅。
把條件分支語句提煉成函數(shù)
巨大而復(fù)雜的條件往往會使函數(shù)變得很難懂鲜结,簡單來說就是把各種簡單的小判斷單獨(dú)拉出來當(dāng)作一個函數(shù)。
返回一個布爾值活逆,通過這個布爾值來做判斷精刷。
例子:
function getInof(){
if(一串長而復(fù)雜的判斷條件){
...//一串獨(dú)立的處理代碼
return result;
}
return result;
}
//這里就可以把那串判斷條件提出來
function getInfo(){
if( judgeInfo()){
...//一串獨(dú)立的處理代碼
return result;
}
function judgeInfo(){
return //一串長而復(fù)雜的判斷條件。
}
}
這樣會使代碼更好懂蔗候,當(dāng)然不絕對怒允,需要分情況討論,在此不再展開锈遥。
合理使用循環(huán)
在一個龐大而復(fù)雜的函數(shù)體內(nèi)其實(shí)有很多代碼是負(fù)責(zé)的重復(fù)的工作纫事,比如最常見的通過js直接對Dom元素進(jìn)行賦值和取值這樣的操作.
很多人會寫出...
function setValue(){
document.getElementById('a').innerHTML='1';
document.getElementById('b').innerHTML='2';
document.getElementById('c').innerHTML='3';
.........
}
//這里只是舉例它們有的時(shí)候可以有20~30行長,這是讓人崩潰的所灸。為什么不寫一個簡單的for in循環(huán)呢丽惶?
function setValue(){
var list={
a:1,
b:2,
c:3
}
for(i in list){
document.getElementById(i).innerHTML=list[i];
}
}
不僅減少了編碼量,看起來更加優(yōu)雅爬立,還比較好懂钾唬,循環(huán),你值得擁有。
合理的傳參&&合理的退出&&合理的三目運(yùn)算符
JavaScript函數(shù)的出口不一定非得限定為一個抡秆,雖然通常我喜歡讓它只有一個出口使得結(jié)果更為可控奕巍。
但不一定每次都這樣,比如進(jìn)來一個判斷儒士,滿足才需要往下執(zhí)行的情況的止,我們就可以一進(jìn)來不滿足直接退出。這里需要靈活掌控着撩。
關(guān)于參數(shù)诅福,如果一個函數(shù)要接受很多參數(shù),而你全部寫上了睹酌,這無論是對擴(kuò)展還是調(diào)用都很不利权谁。
所以可以把它們寫到一個對象中去。
一個簡單的判斷通潮镅兀可以用三目來替代,比如給參數(shù)賦上默認(rèn)值但是沪猴,如果復(fù)雜的If else也使用三目來替代代碼會變得很不好懂辐啄,所以合理使用。
這里我無意舉一個壞例子运嗜,只擺一個我認(rèn)為合適的例子在這壶辜。
var param={
isExist:true,
age:12,
name:'tom',
vip:false
}
function setUserInof(param){
if(!param.isExist){
return 'notExist'
}
var vipState= param.vip || false
....//大量的業(yè)務(wù)邏輯,比如賦值什么的
return result;
}
大概就是這種感覺..壞的列子完全可以通過閱讀上面的文字來反推担租。
關(guān)于合理的退出砸民,假如內(nèi)部有一堆循環(huán),且需要判斷到某個條件break的話奋救,直接return效果更好岭参,通常可以節(jié)約一些判斷尝艘,且增加代碼可讀性演侯。
合理使用鏈?zhǔn)秸{(diào)用
鏈?zhǔn)秸{(diào)用,使用過jQuery的話背亥,對此不會陌生秒际,每個操作之后可以直接跟下一個操作。
//就像這樣
$('#user').text('tom').attr('display','block').css('font-size','28px')....
我在使用jQuery的時(shí)候聽說這是被建議的狡汉,我見過一整個頁面都是鏈?zhǔn)秸{(diào)用的代碼娄徊,一個代碼塊可能有30~50行,每個鏈條隔了幾百米遠(yuǎn).....看起來似乎很高端盾戴?然而實(shí)際閱讀起來寄锐,非常的不方便,而且沒有必要,在這種情況下使用鏈?zhǔn)秸{(diào)用節(jié)省下來的字符數(shù)似乎相對原本的長度而言顯得非常微不足道锐峭,我不知道為什么它要這么寫中鼠。但這種代碼修改起來非常的不友好,可以說是高度耦合的沿癞。
所以通常來說援雇,如果結(jié)構(gòu)穩(wěn)定,使用鏈?zhǔn)秸{(diào)用似乎并沒什么不妥椎扬。
但是如果這個代碼很有可能需要擴(kuò)展和修改惫搏,鏈?zhǔn)秸{(diào)用只會徒增修改的不便罷了。
結(jié)語
今天蚕涤,稍微對代碼重構(gòu)進(jìn)行了一些探討筐赔,算是管中窺豹..
畢竟這一塊展開來說可以出本書了。
實(shí)際上揖铜,這篇筆記讓我來寫有些空洞茴丰,因?yàn)榛旧衔覜]有對我寫的模塊進(jìn)行大規(guī)模重構(gòu)過。
充其量就是在項(xiàng)目時(shí)間充裕的時(shí)候精煉下寫法罷了天吓,然而通常項(xiàng)目時(shí)間并不充裕贿肩。
重構(gòu)別人寫的模塊倒是有過幾次,只是那些時(shí)候通常來說搞清楚它在干嘛然后自己寫一遍會更快龄寞。
然而汰规,并不是說這篇筆記就沒有意義,雖然是現(xiàn)學(xué)現(xiàn)賣物邑,但是這上面提到的重構(gòu)原則溜哮,我在實(shí)踐中通常會在編寫時(shí)就考慮好,它們很基礎(chǔ)色解,基礎(chǔ)而有用茂嗓。
這兩天有點(diǎn)累,這篇筆記就到這里吧冒签,相對之前的筆記篇幅可能略微有些短在抛,這是為了便于補(bǔ)充。
于是在此暫時(shí)的萧恕,我放下了鍵盤刚梭。