iT邦幫忙

2021 iThome 鐵人賽

DAY 11
0
Software Development

幫自己搞懂物件導向和設計模式系列 第 11

單一功能原則 Single Responsibility Principle

關於物件導向程式設計的五個設計原則,大家可能會依據不同的順序來解釋,不過我想「單一功能原則」一定會被擺在首位。

這個原則由 "Uncle Bob" (Robert C. Martin) 於 2003 年在他的著作 Principles of Object Oriented Design 當中所提出,其描述相當簡短:

A class should have only one reason to change

每一個類別只會因為一種原因被修改。從另外一個角度來說,就是每一個類別只會有一種功能,只有當依賴這個功能的需求變動的時,才需要修改這個類別。

如果回想設計原則存在的原因:面對需求快速變動的世界,那麼這個原則所要告訴我們的就是,盡可能將功能與職責拆分,一種類別就單純處理一種功能、需求,因此當未來需求變動的時候,我們只要修改負責的類別就行,降低大規模修改程式碼、甚至影響到其他功能的狀況。

關於單一功能

那好吧,我們就開始拆分各種功能,拆分到每一個類別裡面只有一種屬性或方法,那這樣就非常「單一」了!

然而這樣反而就違背了物件導向程式設計本身的意義:透過物件來模擬真實世界。

舉例來說,如果今天我們希望透過物件來描述一位棒球選手,不過因為單一功能原則,所以我們需要「大量」的繼承各種類別、實作各種介面,才能好好描述一位棒球選手,似乎就本末倒置,無法容易的描述真實世界的事物。

另一方面,這個棒球選手類別,其實就高度依賴其他類別與介面,如果其他類別或介面因為其他需求變動而修改,反而棒球選手類別也就會跟著受到影響。

所以,到底什麼是「單一功能」呢?其實 Uncle Bob 後來有補充了一句話:

This principle is about people.

回過頭來,這個原則是「關於人們」,但這是什麼意思呢?

關於人們

當我們在設計任何程式的時候,最終目的都是要來解決人們在真實世界當中遇到的問題,所以「單一功能」的角度,並不是指程式本身功能的角度,而是人們的需求功能(或業務功能)的角度。

也就是說,我們會希望一個類別不是只處理一種程式功能,而是能夠處理某一種人們(業務)需求,而當這個需求變動的時候,我們只要回頭修改這個類別就行,不影響到其他類別。

但這時候又有另外一個問題,要怎麼定義或規範業務需求的範圍呢?譬如以一間咖啡店來說,一開始我們可以建立一個超大類別,涵蓋經營咖啡店所需要的各種屬性和方法,接著,我們可以開始拆分業務,建立吧台人員、櫃台人員、後勤物流人員 ... 等類別,來分別處理各種需求。

但是如果咖啡店的經營規模持續擴大,吧台人員可能又可以繼續拆分成負責飲料的吧台人員、負責甜點的吧台人員、負責熱食的吧台人員 ... 等。

最後會發現,現實世界當中的業務,也可以像程式碼的功能一樣,不斷的拆分下去。那麼這樣,要怎麼決定「單一功能」所需要面對的業務範圍呢?

關於範圍

再次回到設計原則存在的原因:面對需求快速變動的世界,以剛剛的咖啡店例子來說,如果吧台人員所面對的需求並不會變動,那麼其實我們就不需要將吧台人員這個類別拆分的更細,因為原本的這個類別就能夠很好的處理業務。

如果這家咖啡店的強項是甜點,每週都會有新品上市,因此需要訓練員工準備、介紹新的甜點。所以每當有新甜點出來之後,我們就需要去修改「吧台人員這個類別當中關於甜點的部分」,但每次修改可能就會影響到其他部分(飲料、熱食)等,所以這時候我們就可以把「吧台人員這個類別當中關於甜點的部分」給拆分出來,成為獨立的類別,專門面對某個快速變動的需求。

小結

所以如果要實現「單一功能原則」,其實背後在做的是拆分真實世界的業務,特別是針對會快速變動的需求,將其拆分出來並建立專門的類別來處理。某個角度來說就是「隔離變化」。

真實世界的業務是不斷的在變動,因此實作「單一功能原則」時的細節也會不斷的跟著變動。


上一篇
中場回顧
下一篇
開放封閉原則 Open-Closed Principle
系列文
幫自己搞懂物件導向和設計模式30

尚未有邦友留言

立即登入留言