物品我們都知道要按照其功能或用途分類和整理,來確保每個物品都處於適當的位置,整理後的物品更容易被找到,因為被分類得很清楚。
在架構上,該怎麼去做設計和切分,才能讓下面一位接手的人心情不至於太差呢?
回顧一下之前的例子,專案假設今天總共用五個階段五個角色,每個角色在不同階段需要填的欄位並不相同,可以想像一個班級有不同的幹部,而班級學期報告需要大家按照各自的職掌在不同階段逐漸把內容完善。
程式會被修改的原因,通常是使用者需求的改變
假設一個類別只做一件事,但這件事剛好被兩個角色使用到,當其中一個角色提出新的需求,調整時就影響到另外一個,這就是把元件做成瑞士刀給不同角色去使用的壞處。
這時候該怎麼做比較好,接著就讓我們來看看 Single Responsibility Principle (SRP) 的概念吧。
Single Responsibility Principle (SRP) 是指每個類別或模組只負責一個功能或職責。
一個類別或模組應該只有一個理由會使其改變
這個說明應該更往回推,因為程式會被修改的原因,通常是使用者需求的改變。
一個類別或模組應該只對唯一的一個角色負責
單一職責原則,是希望我們依據不同角色的使用者來進行分類,只有當這個特定群體的需求改變,程式碼才會改變。
讓我們看看前後端的例子:
# frontend
src
└── features
├── typeOne
│ ├── TypeOne.js
│ ├── TypeOne.styles.scss
│ └── typeOneSlice.js
├── typeTwo
│ ├── TypeTwo.js
│ ├── TypeTwo.styles.scss
│ └── typeTwoSlice.js
└── typeThree
├── TypeThree.js
├── TypeThree.styles.scss
└── typeThreeSlice.js
# backend
src/
├── entities/ # 按照資料表去區分
│ └── user/ # 使用者表
│ ├── model.js # Schema 定義
│ ├── controller.js # 資料庫 CRUD
│ └── route.js # API 設定
└── index.js # 入口
這樣的程式碼會更容易理解,因為
這樣的作法雖然會導致程式碼重複,但因為模組會針對不同群的使用者分開,複製貼上的成本比起每次更動都可能影響一大群使用者來說,其代價會是相對小的。
這讓我想起了大學時期曾經到恆春夏日小學當課輔老師,當時社工老師希望我們和孩子傳遞的價值觀
一次做一件事,念
單一功能原則的目的是減少同個區塊中不相關的邏輯。
當被開發者找到程式碼後,可以更快確認在哪一行產生目前的行為,更容易去判斷在這一階層 (頁面) 的操作只要正確就可以不用煩惱其他階層的任何操作,進而更容易且安全的去修改程式碼。
以撥放器的 App 來說,撥放的頁面和設定的頁面是分開的,設定的時候並不用管撥放的時候做了什麼操作,對程式碼來說開發者就要知道這段程式碼是在做什麼,有沒有耦合或是在不明顯的地方又多做其他的事情,以 React 的開發來說比較好的方式就是將顯示邏輯和資料邏輯分開。
import React, { useState } from "react";
// 資料和顯示寫在一起
function SendButton() {
const [data, setData] = useState(null);
const strButtonDisplay = "送出";
const url = "http://example.com/movies.json";
// 送出的邏輯
function handleSend() {
fetch(url)
.then((response) => {
return response.json();
})
.then((myJson) => {
setData(myJson);
});
}
return (
<button type="button" onClick={handleSend}>
{strButtonDisplay}
</button>
);
}
// 將資料和顯示邏輯分開
// 資料邏輯
function useSubmit({ strButtonDisplay, url }) {
const [data, setData] = useState(null);
function onClick() {
// 送出的邏輯
fetch(url)
.then((response) => {
return response.json();
})
.then((myJson) => {
setData(myJson);
});
}
return {
strButtonDisplay,
data,
onClick,
};
}
// 顯示邏輯
function ThemeButton() {
const { strButtonDisplay, data, onClick } = useSubmit({
strButtonDisplay: "送出",
url: "http://example.com/movies.json",
});
return (
<button type="button" onClick={onClick}>
{strButtonDisplay}
</button>
);
}
設計系統的架構受制於產生這些設計的組織的溝通結構。
M. Conway
系統設計本質上其實反映了企業的組織結構,軟體的架構與團隊的組織結構是互相影響的。
系統各個模組間的介面也反應了企業各個部門之間的訊息流動和合作方式,如果組織在資源和合作上沒有真的共用某些資源,那麼在程式設計上我們就不應該共用模組。