S.O.L.I.D 物件導向設計原則 - SRP (Single Responsibility Principle)

Posted by Ryan Tseng on 2017-10-05

我很不會說話,但是我很實在

前言

第一次寫到這個物件導向設計原則的主題,我想到的是上面那一句廣告的台詞,因為 S.O.L.I.D 原則本身光看字面你可能還無法了解他代表的意義,最好的方式應該是將這幾個原則實務的應用到專案上面,你就能夠感覺到 SOLID 原則 實在 的地方。

首先我們討論到單一職責原則,以下會使用比較貼近生活的例子來讓大家有一點感覺。

SRP (Single Responsibility Principle)

a class should have only a single responsibility

一個類別只能擁有單一個職責

在現實生活當中,常常會遇到有同事一個類別寫了好幾千行,裡面的操作包羅萬象,就好像hen久以前很喜歡把一些方便的操作方法包裝成一個 Utility 類別,可是打開這個類別的程式碼你又會發現,裡面又做了一些 Parser,一些寄信的功能,一些資料庫的操作,一些邏輯的計算,就好像你什麼東西都摻了一點,但是什麼都沒有辦法做到位,你的類別一天一天的越來越肥,但是工程師卻越來越瘦。

以實例來做比喻,比如說我們在系統上有定義一個 UserService,它可以用來幫我們處理一些與 User 有關的操作,如下

修改前

1
2
3
4
5
6
7
8
9
10
11
12
public class UserService
{
public bool IsUserValid(string account, password)
{
// ...
}

public void SendEmail(string address, string title, string content)
{
// ...
}
}

這個例子其實比較極端一點,稍微的觀察一下 UserService 當中的 Method SendEmail 這個方法和 User 一點關係都沒有,所以它違反了 SRP ,我們可以對它稍作修改。

修改後

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class UserService
{
private readonly EmailService _emailService;
public UserService()
{
_emailService = new EmailService();
}

public bool IsUserValid(string account, password)
{
// ...
}
}

public class EmailService
{
public void SendEmail(string address, string title, string content)
{
// ...
}
}

經過重構之後,我們將 SendEmail 方法移至獨立的一個 EmailService 來寄送郵件,然後在原本的 UserService 建構式當中將這個 EmailService 建立一個新的實體,看起來似乎是有這麼一點 SRP 的樣子了。