# 六角鼠年鐵人賽 Week 37 - Design Pattern - Single Responsibility Principle ==大家好,我是 "為了拿到金角獎盃而努力著" 的文毅青年 - Kai== ## 半澤直樹 (日劇:半澤直樹) :::info 重要的不是在哪工作,而是如何去工作 ::: ## 前引 寫程式的時候常會有人說:「要把功能模組化拆開」、「東西不要都放在一個 class」、「同個功能不同對象就不能寫進同一個程式中」。 這些話時常聽到,但其背後所需要具備的知識含量絕對不是三言兩語的可以蔽之,甚至很多時候負責教導的工程師都會用 **經驗** 兩字帶過 (Kai 也這樣對後輩的教學偷懶過...)。 但其實這些基本的道理全部都已經被寫成理論、邏輯被構思成精巧的字句寫進書裡、教學文章中,只要用心學,除了經驗累積以外,也可以迅速上手這些看似模糊卻又必須具備的硬知識。 ## 主題 今天要介紹的 **Single Responsibility Principle** 中文常見名稱 **單一職責原則** 由 **Robert C. Martin** 在 2002 年的 Agile Software Development, Principles, Patterns, and Practices. 一書中提到: **There should never be more than one reason for a class to change**. 意思即為: 單個類只能存在一種變更其功能種類的理由或需求,若超過一個,則該類必須再做更細部的劃分,視情況應進行拆分解耦合,或透過多型的方式,作成兩個或以上只具備單個變更其功能種類的理由或需求。 落落長一大串,言簡意賅就是該類只負責單一需求的功能處理,這樣子做的好處就是當物件內容有變化時,並不會超出原本預計物件必須處理的範疇。 就像汽車並不能當火車開、遙控飛機跟真實飛機的可比性也是差了一大截。 ## 幫助 Single Responsibility Principle 實行後,對於專案、對於維護上的幫助如下: - 降低類別內容的複雜程度 - 降低多型引發的錯誤風險 - 增加類別內容的可讀性 - 增加類別內容的可維護性 Single Responsibility Principle 的道理簡單,但在實作上的難度卻比下了先前提及的幾大原則,原因無他 -- 極高度依賴開發人員的經驗。 配合先前提及的幾大原則之下,Single Responsibility Principle 才可以發揮他最棒的長處,而這完全取決於開發人員對於系統、業務需求與邏輯有一定程度的了解,才能夠將其面面俱到的設計到位。 單一功能的類別或多或少可能都需要納入一些特殊處理,而如何將一整個系統的類別都設計到位,並且具備擴充的彈性、系統的胖瘦控制,都是許多開發人員常常要面對的課題。 ## 新實例 我們以一個團體來說,每一位員工有各自需要負責的事情。 好比主管的工作項目通常是: 1. 向上呈報 2. 向下管理 3. 規劃工作進度 員工的工作項目為: 1. 向上呈報 2. 規劃工作進度 3. 執行工作 我們可以分別在主管和員工的類別中設定這幾個方法,但若每個月都有例行會議報告,我們就得分別使用主管和員工的類別,並呼叫他們的方法實作。 :::warning **情境問題** 在某一支負責會議的類別中,有著與主管、員工等類別高偶合的狀況 ::: 也許我們可以用一個職員的 Interface 來界定這些方法,然後各自讓主管和員工去針對需要的部分進行實作。 如下圖:  :::warning 情境問題 主管和員工,各有沒在使用的方法實作,不是一個高效的作法 ::: 切分更多的 Interface 來強化結構 如下圖:  :::warning 情境問題 同樣是主管,行銷主管和人力資源主管的 **規劃工作進度()** 內容完全不同,同樣在員工的部分,業務和工程師在 **執行工作()** 的內容差異也是極大 ::: 因為我們都聚焦在人! 而單一職責原則則是聚焦在功能的本身,所以上述這些如果透過不斷長出的 Interface 則在最後的部分會不好掌控,且是 By 角色的切分方式,當我們再次聚焦回工作項目本身後,雖然不同角色在同一個工作項目上可能有不同的做法,反之相同的角色在同一個工作項目上是沒有差異的。因此縱使透過繼承的方式處理擁有相同工作項目的角色,也會因為過多的層級而讓整個架構非常卡。 角色跟工作項目無法區分開來就是上述想法持續擴展的後果,最差最差就是會變得比第二張圖還多層級,且每多出一個新角色,可能就會對原有的層級架構又產生一次影響。 那麼我們要如何切分開呢? 我們可以針對工作項目建置獨立的類別架構,並把其分類,在各自製作適合的實體類,這種作法甚至可以細分到職階差異,例如下圖中管理類**最高層級管理**和**部門管理**的不同。 這樣的好處是: 角色與工作項目的架構解耦合、每個類別都能夠達到單一職責原則的期望、更易維護、更易擴充。 未來只需要專注在於拼湊每個角色應該擁有的工作項目,即可達到預期目標。 如下圖:  而在原先要求的會議部分,我們只需要在會議中新增一個送入角色的方法,該方法會去判讀該角色所挾帶的工作項目是否有報告類的實作可以呼叫,則我們就不需要在會議類裡面去作高偶爾的角色類建立,從而達到會議類的單一職責。 ## 舊實例  :::warning 舊的舉例,尚未切分仔細,僅講述了應把角色從團體中切分的部分而已,參考看看就好 ::: 以一個樂團當作實例來說,樂團的表演需要有人聲和伴奏 (假設非自彈自唱情況),人生和伴奏是個別的人合湊成一個樂團。 對伴奏來說,有其需要負責的項目。 對歌手來說,也有需要負責的項目。 兩者負責的項目不會一樣,但樂團如果要表演,無論是清唱 (純人聲)、純音樂 (純伴奏),或是一首有人聲的歌曲,都需要借用個別的物件的功能來達到目的。 不管是單獨還是混搭,都不影響原先兩物件的功能面相,因為兩者並沒有重複的地方或性質存在。 這也是 Single Responsibility Principle 的所提供的最好幫助。 :::danger 又過了一週,又學習到一個新的 Principle,希望大家都能與 Kai 一起慢慢把基本功紮實起來吧! ::: 首頁 [Kai 個人技術 Hackmd](/2G-RoB0QTrKzkftH2uLueA) ###### tags: `Design Pattern`,`w3HexSchool`
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up