SRP(單一職責)——沒有一隻能飛能走的鳥

單一職責原則(SRP:Single responsibility principle)又稱單一功能原則。它規定一個類應該只有一個發生變化的原因。

一、起因

編碼中,需要創建一隻小鳥,既能飛,用能走。
我寫的時候,我會定義兩個接口,IFly,IWalk,然後實現他們。
image
然後,外部模塊需要用到我的「鳥」,進行操作。這個時候,有同事過來了,說「按照SRP,你這個鳥有問題」
難道我要提供兩隻鳥:一隻FlyBird,一隻WalkBird?

二、問題

「一個類應該只有一個發生變化的原因」
在《敏捷軟件開發:原則、模式與實踐》90頁,清晰的寫着「我們把兩個職責都耦合進了ModemImplementation類中,這不是所希望的,但或許是必要的,常常由於一些和硬件或者操作系統的細節有關的原因,迫使我們這樣去處理。我們可以把它看做一個有缺陷的類,所有的依賴關係都是從它出發,誰也不需要依賴它。除了Main以為,誰也不需要知道它的存在。因此我們已經把醜陋的部分隱藏起來。」
image

三、思考

比如當前外部有一個大的舞台場景,裏面有「鳥」,「雲」,「天空」,
偽代碼:

class Scene{
bird:Brid;
cloud:Cloud;
sky:Sky;
}

按照 「標準srp」,我提供的是一個「飛,走,職責揉進bird」的類,是「醜陋的鳥」。
那怎樣寫出一隻「不醜陋的鳥」呢?
答案是,沒有這樣的一隻鳥。因為你的鳥需要「飛,走」。

在書中提到的「main」,是我們現在用到的場景么?個人覺得,不是!!!
「main」應該是指最外層的調用者,而不是中間層的調用者。最外層只能是 文檔類(入口類)。
對於外界來說,我的鳥,能飛,能走,已經是一個獨立的組件了,不能將兩者分離。
如果我創建兩隻鳥,FlyB,WalkB,那麼,這鳥如果再中間層被使用,每次都要在兩隻鳥中艱難選擇。

當然,調用者想用 ISP,這個要看他的需求了。

四、結論

個人覺得,我最開始的設計沒有問題。SRP對於最底層的組件,可以適用;但是對於中間各層的組件,就會出現結構過於分散,職責過於細緻,適用過於繁雜。

Tags: