我們該重用代碼還是復制粘貼?答案是“分情況”,那么這個邊界在哪呢?這也是我這篇博客所思考的問題。
今天在老德德的推薦下開始看了《架構之道》,這本書并不厚,但是干貨挺多。我用了一些瑣碎的時間看了幾章,每章長度也不長,每章都像一篇高手的博客,很有意思。
這本書的四分之一處開始介紹一些設計原則,首當其沖的就是單一職責原則,這個職責的學術范兒定義我不想贅述,因為并不好理解,我打算從書中的一個例子開始說起。
假設有這樣一種情況
假設有這么一個類Employee雇員類,這個類里面有3個方法:
class Employee {
caculatePay(); //這個方法用于計算當月工資
reportHours(); // 這個方法用于計算當月工時
save(); //這個方法用于將工資和工時存入數(shù)據(jù)庫
}
你看這三個方法:
- caculatePay(); 這個方法用于計算當月工資,財務部的軟件會調(diào)用這個方法來顯示工資。
- reportHours(); 這個方法用于計算工時,人事部的軟件會調(diào)用這個方法來顯示工時。
- save();這個方法用于將工資和工時存入數(shù)據(jù)庫
那么此時,程序員在實現(xiàn)這兩個方法的時候,都使用了一個公共函數(shù),regularHours(),如下圖:

有一個程序員不小心踩了雷
財務部的程序員需要對caculatePay這個方法進行更新,因為財務部的計算模型變了。于是這位程序員發(fā)現(xiàn)caculatePay這個方法其實是調(diào)用了一個regularHours方法,于是他就把regularHours給改動了一下。拜托,他可不知道這個方法正在被別人使用呢!理所當然的,人事部的數(shù)據(jù)就出現(xiàn)了問題。
單一職責的解決之道
單一職責的思路是:我們需要將Employee類拆分成兩個類。同樣的,這兩個類所共同依賴的regularHours方法當然也要被實現(xiàn)2次。沒錯,目前看來,我確實是在復制粘貼regularHours方法中的代碼,可是這樣一來,財務部的程序員就不會影響到其他部門的同事了。
內(nèi)心OS:如果這本書的作者不是大牛的話,可能這個復制粘貼的行為會被噴。但這個例子是可以說服我的。
缺點
在《設計模式之禪》這本書里也提到了,單一職責這種設計方法很容易導致代碼超級膨脹,本來一個類可以做的事情被拆成了多個類。那么什么時候該拆分,什么時候不該拆分呢?我需要講述另一個例子。
一個現(xiàn)實中的例子
我們當前的項目中,在訂票的流程頁面寫了一個卡片,類似于這樣:

過了很久后來了一個新需求,我們需要在管理頁面也實現(xiàn)這樣一個卡片的樣式。我有兩個選擇:
-
import scss from 'normalBookingFlow';這句話能看明白吧?哈哈,就是我在管理頁面直接導入之前的scss文件。 - 創(chuàng)建一個新的scss文件,并且將之前的scss樣式復制粘貼過來。
顯然,這是一個分水嶺,而我該怎么做呢?
我的個人見解是:根據(jù)team來決定是否選擇復制粘貼。說的直白點:
對于復制粘貼還是直接復用的邊界在于,兩段代碼當前是否處于同一個小團隊在開發(fā),或者是否處于同一個業(yè)務流程。
因為人事部和財務部不是同一批開發(fā)團隊,所以對于這兩個部門共用的代碼應該拆分成兩個部分。
因為普通的訂票流程和管理頁面的流程不是一個業(yè)務流程,所以也應該被拆分。
說來說去,其實結論一句話就說明白了。但是如果我在題頭直接寫這句話:對于復制粘貼還是直接復用的邊界在于,兩段代碼當前是否處于同一個小團隊在開發(fā),或者是否處于同一個業(yè)務流程。 不著頭不著尾的誰他媽看得懂???
結論:
1. 單一職責其實解決的是代碼復用與代碼復制的邊界問題。
2. 對于復制粘貼還是直接復用的邊界在于,兩段代碼當前是否處于同一個小團隊在開發(fā),或者是否處于同一個業(yè)務流程。
以上只是我結合自己的開發(fā)經(jīng)驗和書中所寫產(chǎn)生的聯(lián)想和理解,畢竟代碼開發(fā)因人而異,如果編程可以做到完全客觀呈現(xiàn)沒有個人風格,那么要我們還有什么用呢?找一幫編程的機器人就完事兒了。編程的藝術正在于,你可以從代碼看到一個人的成長和影子。