Clean Code: 技術筆記02 SOILD原則

Joyce Hsiao
Hsiao’s Blog
Published in
6 min readOct 28, 2022

#Clean Code #Code Architecture #Design Pattern

這次的讀書目標是希望可以增進程式架構設計能力,能夠寫出好的程式碼。會從線上課程中汲取心得筆記並記錄在此系列文章當中。

Photo by Kaleidico on Unsplash

在Clean Code一書中認為,正確的軟體系統是指建立和維護只需要一小部份的人力,而且修改時是簡單又迅速,花費精力最少,但功能和靈活性卻是最大的。

這就是具有高度維護姓與擴展性的系統,然而為了盡量達到這樣的境界,程式在設計上就有很多的概念和方法來建立,包含各種design pattern以及principle。

但是開發人員卻常常為求快速及短期的生產力,而直接寫出凌亂的程式碼,並認為自己未來具有清理的能力。

Clean Code:製造紊亂的開發速度總是比保持整潔的開發速度還要慢

Good software systems begin with clean code. This is where the SOLID principles come in.

SOILD Principle 設計原則

這個眾所皆知的SOILD原則在網路上有更多更清楚詳細的解釋和說明,因此這裡沒有嘗試要進行說明及解釋,而是重點放在我的錯誤認知和想法。

SRP: 單一職責原則

Robert開宗明義就說明了很多人誤解了這個名字,認為一個模組只能做一件事。

模組:簡單定義為source file,也可以說模組是由函示和資料結構聚集的集合。

我也以為所謂的SRP就是一個函式做一件事,但SRP的概念不僅於此。如果嘗試將想法提升到使用者角度,就可以想像成同一群使用者希望以同樣方式更改系統,那這群人稱為角色(Actor)。

而SRP的概念是 “一個模組應該只對唯一的一個角色負責”

簡而言之,當收到某個角色的需求要求更改某項功能,而改動後不該影響到其他的角色。如果開發一個學校內部系統,如果數學老師要求更改年度成績計算方式,但卻影響到英文老師的成績計算,那這就是違反了SRP原則,並增加了維護困難度。

在程式面(非完整語法),會造成上述問題的系統結構可能長這樣:

Class Teacher{  Dailywork w = new Dailywork ()  w.CheckStudentHomeWork  w.GenerateHomeWork()  w.PrepareCourse()}Class Dailywork{  Public CheckStudentHomeWork()  {
CalculateAttendance()
CalculateGrade()
...
} Public GenerateHomeWork() Public PrepareCourse() Private CalculateGrade()//開發人員更改了這裡的成績計算}

這個最簡單的例子說明每位老師都需要計算成績,雖然程式上嘗試做到function的reuse,但是這樣個架構並沒有對唯一角色負責,導致更改函式時可能會影響到其他角色的運作。

如果數學老師們決議更改計算成績的方式變成開根號乘以十,因此開發人員treac code後發現只要更動CheckStudentHomeWork()所呼叫的CalculateGrade(),卻因此造成其他科老師在計算成績時也呼叫了新的改動,造成錯誤的成績。

常見的解方是創Dailywork 的 Interface,並確定dailywork應該要有哪些function 這樣同樣function名稱在實作上互不影響(解耦):

Interface IDailywork (){  CheckStudentHomeWork()  GenerateHomeWork()  PrepareCourse()}

這個時候,在class teacher地方就可以根據不同科別的老師去建立object

例如:

IDailyWork dailyWork;Case Math:  dailyWork= new MathTeacherDailyWork();  Break;Case English:  dailyWork= new EnglishTeacherDailyWork();  Break;dailyWork.CheckStudentHomeWork()dailyWork.GenerateHomeWork()dailyWork.PrepareCourse()

如果認為DailyWork裡面的function還是有高度重複的話,可以用繼承的方式去撰寫Virtual method,繼承的子類別如果要更改功能就可以override.

以上是我對於SRP目前的理解,要參透靈活運用的話,我應該還需要多練練。

SOILD接下來還有OCP,LSP,ISP和DIP,閱讀後發現OCP,LSP,ISP的概念比較容易懂(甚至上述的繼承概念已經含括在內),其實也會發現過往寫的系統也已經應用了很多SOILD的觀念。而且Reference的連結中都有很清楚的解釋,因此下一篇的主題是甚麼,我還不確定。

這次的讀書計畫會從Design Pattern開始,研究各個pattern的使用情境,以及了解如何達到高維護高擴充。

--

--