大家覺得在接手遺留代碼時,見到什麼東東是最讓人感到不耐煩的呢?複雜無比的UML ?我覺得不是。我的答案是,超過兩個else 的if ,或是超過兩個case 的switch 。可是在程式碼中大量使用if else和switch case是很正常的事吧?錯!絕大多數分支超過兩個的if else 和switch case 都不應該以硬編碼( hard-coded )的形式出現。
複雜分支從何而來
首先我們要討論的第一個問題是,為什麼遺留程式碼裡面往往有這麼多複雜分支。這些複雜分支在程式碼的首個版本中往往是不存在的,假設做設計的人還是有點經驗的話,他應該預見將來可能需要進行擴展的地方,並且預留抽象接口。
但是程式碼經過若干個版本的迭代以後,尤其是經過若干次需求細節的調整以後,複雜分支就會出現了。需求的細節調整,往往不會反映在UML 上,而會直接反映在程式碼上。例如說,原本訊息分為聊天訊息和系統訊息兩類,設計的時候自然會把這設計成訊息類的兩個子類。但接著有一天需求發生細節調整了,系統訊息裡面有一部分是重要的,它們的標題要顯示為紅色,這時候程式設計師往往會做以下修改:
在系統訊息類別上面加一個important 屬性
在對應的render 方法裡面加入一個關於important 屬性的分支,用來控制標題顏色程式設計師為什麼會做出這樣的修改?有可能因為他沒意識到應該要抽象化。因為需求說的是「系統訊息裡面有一部分是重要的」,對於接受命令式程式語言訓練比較多的程式設計師來說,他或許首先想到的是標誌位——一個標誌位就可以區分重要跟不重要。他沒想到這個需求可以用另一種方式來解讀,「系統訊息分為重要和不重要兩個類別」。這樣子解讀,他就知道應該對系統訊息進行抽象化了。
當然也有可能,程式設計師知道可以抽象,但基於某些原因,他選擇了不這麼做。很常見的一種情況就是有人逼著程式設計師,以犧牲程式碼品質來換取專案進度速度──加入一個屬性和一個分支,遠比抽象重構要簡單得多,如果要做10個這種形式的修改,是做10個分支快還是做10個抽象快?差異顯而易見。
當然, if else 多了,就有聰明人站出來說「不如我們改成switch case 」吧。在某些情況下,這確實能夠提升程式碼可讀性,假設每一個分支都是互斥的話。但是當switch case 的數量也多起來以後,程式碼一樣會變得不可讀。
複雜分支有何壞處
複雜分支有什麼壞處?讓我從百度Hi 網頁版的老程式碼裡面截取一段出來做個例子。
switch (json.result) {
case "ok":
switch (json.command) {
case "message":
case "systemmessage":
if (json.content.from == ""
&& json.content.content == "kicked") {
/* disconnect */
} else if (json.command == "systemmessage"
|| json.content.type == "sysmsg") {
/* render system message */
} else {
/* render chat message */
}
break;
}
break;
出處:百度泛用戶體驗