代碼之丑(五)——不受歡迎的大心臟
不知道為什么,初見它時,我想起了郭芙蓉的排山倒海:
newRule->SetOID(oldRule->GetOID());
newRule->SetRegion(oldRule->GetRegion());
newRule->SetRebateRuleID(oldRule->GetRebateRuleID());
newRule->SetBeginCycle(oldRule->GetBeginCycle() + 1);
newRule->SetEndCycle(oldRule->GetEndCycle());
newRule->SetMainAcctAmount(oldRule->GetMainAcctAmount());
newRule->SetGiftAcctAmount(oldRule->GetGiftAcctAmoun t());
newRule->SetValidDays(0);
newRule->SetGiftAcct(oldRule->GetGiftAcct());
rules->Add(newRule);
就在我以為這一片代碼就是完成給一個變量設值的時候,突然,在那個不起眼的角落里,這個變量得到了應用:它被加到了rules里面。什么叫峰回路轉,這就是。
既然它給了我們這么有趣的體驗,必然先殺后快。下面重構了這個函數:
ColdRule *newRule = new ColdRule();
newRule->SetOID(oldRule.GetOID());
newRule->SetRegion(oldRule.GetRegion());
newRule->SetRebateRuleID(oldRule.GetRebateRuleID());
newRule->SetBeginCycle(oldRule.GetBeginCycle() + 1);
newRule->SetEndCycle(oldRule.GetEndCycle());
newRule->SetMainAcctAmount(oldRule.GetMainAcctAmount());
newRule->SetGiftAcctAmount(oldRule.GetGiftAcctAmount());
newRule->SetValidDays(0);
newRule->SetGiftAcct(oldRule.GetGiftAcct());
return newRule;
}
rules->Add(CreateNewRule(*oldRule));
把這一堆設值操作提取了出來,整個函數看上去一下子就清爽了。不是因為代碼變少了,而是因為代碼按照它職責進行了劃分:創建的歸創建,加入的歸加入。之前的代碼之所以讓我不安,多重職責是罪魁禍首。一旦把這個函數提取出來,做完這步操作,我們就不難發現這個函數應該成為CodeRule類的一部分。篇幅所限,就不再繼續了。
談論干凈代碼時,我們總會說,函數應該只做一件事。函數做的事越多,就會越冗長,也就越難發現不同函數內存在的相似之處。為了一個問題,要在不同的地方改來改去也就難以避免了。但面對長長的函數,還是有人無動于衷,繼續往里塞著“新”代碼。
即便大家都認同了函數應該只做一件事,但多大的一件事算是一件事呢!不同的人心里有不同的標準。有人甚至認為一個功能就是一件事。于是,代碼會越來越刺激。想寫干凈代碼,就別怕事小。哪怕一個函數只有一行,只要它能完整的表達一件事。在干凈代碼的世界里,大心臟是不受喜歡的。
接下來,我需要用歷經滄桑的口吻告訴你,這么跌宕起伏的代碼也只不過是一個更大函數的一個部分。此刻,浮現在我腦海里的是層巒疊嶂的山峰。
作者簡介:
鄭曄,ThoughtWorks公司咨詢師,擁有多年企業級軟件開發經驗,熱衷于探索各種程序設計語言在真實軟件開發中所能發揮的威力,致力于探尋合理的軟件開發方式,加入ThoughtWorks公司后,投入到敏捷開發方法的實踐之中,為其他公司提供敏捷開發方法方面的咨詢服務。他的blog是夢想風暴。
查看原文:代碼之丑(五)