在匯道科技辦公室,總有那么一段時間會看到產(chǎn)品經(jīng)理和某個程序員因為代碼的問題展開“聲情并茂”(激烈)的討論,程序員抱怨產(chǎn)品經(jīng)理看不懂代碼,產(chǎn)品經(jīng)理指責(zé)程序員寫的代碼沒有表現(xiàn)力。隨著軟件行業(yè)的不斷發(fā)展,歷史遺留的程序越來越多,代碼的維護(hù)成本越來越大,甚至大于開發(fā)成本。而新功能的開發(fā)又常常依賴于舊代碼,閱讀舊代碼所花費的時間幾乎要大于寫新功能的代碼。
“復(fù)雜的代碼往往都是新手所寫,只有經(jīng)驗老道的高手才能寫出簡單,富有表現(xiàn)力的代碼”此話雖然說的有點夸張,可是也說明了經(jīng)驗的重要性。我們所寫的代碼除了讓機(jī)器執(zhí)行外,還需要別人來閱讀。所以我們要:寫讓別人能讀懂的代碼、寫可擴(kuò)展的代碼。
寫可測試的代碼(代碼應(yīng)該具備可測試性,對沒有可測試性的代碼寫測試,是浪費生命的表現(xiàn))我們來看看如何寫出讓人看得懂的代碼?需要注意些什么?
基于兩個指導(dǎo)原則:
一.DRY(Don’trepeat yourself)
此原則如此重要,代碼越少,Bug也越少,沒有重復(fù)邏輯的代碼更易于維護(hù),當(dāng)你修復(fù)了一個bug,如果相同的邏輯還出現(xiàn)在另外一個地方,而你沒意識到,你有沒有覺得自己很冤?
二.TED原則
簡潔(Terse)
具有表達(dá)力(Expressive)
只做一件事(Do one thing)
三.舉例說明
1.拒絕注釋,用代碼來闡述注釋
反例:
///
///!@#$%^&^&*((!@#$%^&^&*((!@#$%^&^&*((!@#$%^&^&*((
///
//!@#$%^&^&*((!@#$%^&^&*((
var a = new List{ 2m, 3m, 10m };
var b = 2;
var c = 0m;
//!@#$%^&^&*((!@#$%^&^&*((!@#$%^&^&*((
foreach (var p in a)
{
c += p*b;
}
return c;
}
重構(gòu)后:
public decimal CalculateTotalCash
{
var prices=new List{2m,3m,10m};
var itemCount = 2;
return prices.Sum(p => p*itemCount);
}
良好的代碼命名完全可以替代注釋的作用,如果你正在試圖寫一段注釋,從某種角度來看,你正在試圖寫一段別人無法理解的代碼。
當(dāng)你無法為你的方法起一個準(zhǔn)確的名稱時,很可能你的方法不止做了一件事,違反了(Do one thing)。特別是你想在方法名中加入:And,Or,If等詞時
2. 為布爾變量賦值
反例:
public bool IsAdult(int age)
{
bool isAdult;
if (age > 18)
{
isAdult = true;
}
else
{
isAdult = false;
}
return isAdult;
}
重構(gòu)后:
public bool IsAdult(int age)
{
var isAdult = age > 18;
return isAdult;
}
4.拒絕HardCode,拒絕挖坑
反例:
if (carName == "Nissan")
{
}
重構(gòu)后:
if (car == Car.Nissan)
{
}
四.關(guān)于DRY
平時大家重構(gòu)代碼,一個重要的思想就是DRY,項目在架構(gòu)過程中會有各種各樣的MODEL層,例如:DomainModel,ViewModel,DTO。很多時候這幾個Model里的字段大部分是相同的,于是有人就會想到DRY原則,干脆直接用一種類型,省得粘貼復(fù)制,來回轉(zhuǎn)換。
五.利用先進(jìn)的生產(chǎn)工具
以vs插件中的Reshaper為例,本文列舉的大部分反例,Reshaprer均能給予不同程度的提示。經(jīng)過一段時間的練習(xí),當(dāng)你的代碼Reshaper給予不了任何提示的時候,你的代碼會有一個明顯的提高。
真希望我們某位程序員也看看這篇內(nèi)容,平時寫代碼的時候多注意一下,因為小編實在是不想再看安靜的辦公室,突如其來幾聲吼啊!