7 Coding Patterns I Stole From Senior Engineers

原始來源與檔名:2026-06-16T094218+0800-7 Coding Patterns I Stole From Senior Engineers.md


NAPKIN | 餐巾纸

餐巾纸公式

高手程式碼 = (提早返回 + 業務命名 + 邊界隔離 + 嚴謹狀態 + 分離決策) × 易讀性

好程式碼不是炫技,而是為了讓下一個接手的人減少猜測。

一句话

資深工程師的程式碼之所以無聊,是因為他們把複雜性鎖在清晰的邊界內,而不是讓它蔓延到別人的大腦裡。

餐巾纸草图

[複雜的外部世界 / API]
       |
  (3. 邊界隔離)
       V
[清晰的內部領域模型]
   |--- (4. 嚴謹的狀態設計)
   |--- (2. 具備業務意義的命名)
       V
[業務決策邏輯] <--- (5. 分離決策與行動) ---> [副作用/執行行動]
       |
  (1. 提早返回,過濾無效狀態)
       V
[清晰且有用的錯誤日誌] (6. 錯誤對下一個人有用)

ROUND 1: SKELETON | 骨架掃描

“這本書在說什麼”

章節骨架

  1. 提早返回 (Return Early): 移除無效路徑,讓核心邏輯浮現。
  2. 業務命名 (Business Meaning): 用業務意義命名,而非技術載體。
  3. 邊界隔離 (Boundaries): 不讓外部系統定義內部資料形狀。
  4. 嚴謹狀態 (Invalid States): 用型別讓無效狀態難以存在。
  5. 分離決策與行動 (Separate Decisions): 抽離決策邏輯,使其易於單元測試。
  6. 有用的錯誤 (Useful Errors): 錯誤訊息是寫給除錯者和系統看的。
  7. 優化審查 (Optimize for Diff): 專注於 PR 的易讀性與可回溯性。

ROUND 2: DISSECTION | 血肉解剖

“憑什麼這麼說”

論證鏈

程式碼主要成本在於閱讀與除錯 --> 複雜且模糊的結構會增加認知負擔 --> 資深工程師透過一系列模式 (提早返回、業務命名、防禦型狀態等) 降低認知負擔 --> 因此程式碼更穩定且易於維護

關鍵證據

  1. 巢狀條件災難:多層 if 判斷隱藏了真實的業務邏輯,提早返回可立即曝露錯誤路徑。
  2. 外部依賴蔓延:如果直接使用第三方 API 的欄位名稱(如 response.data.user_name),一旦 API 改變,整個程式碼庫都會崩潰;而映射層能控制爆炸半徑。
  3. 狀態不一致:將所有欄位設為 Optional 只是掩耳盜鈴,建立如 DraftUserSavedUser 的嚴謹型別,能在編譯期就攔截邏輯漏洞。

隱形假設與邊界

ROUND 3: SOUL | 靈魂提取

“還能怎麼用”

跨域映射


7 Coding Patterns I Stole From Senior Engineers (Architectural Deep Dive)

前言/背景

這篇文章探討了資深工程師與初階開發者在撰寫程式碼時的根本差異。作者指出,資深工程師之所以優秀,並非因為他們掌握了更多酷炫的語法或框架技巧,而是因為他們專注於「減少驚嚇 (Reduce surprise)」。他們透過七種實用的程式碼設計模式,將系統的複雜度封裝在可控的範圍內,使程式碼在面臨需求變更或生產環境事故時,依然具備極高的可維讀性與可維護性。

章節詳細總結

1. 提早返回 (Return Early) 替代巢狀條件迷宮

初階開發者經常習慣將業務邏輯寫在層層遞進的 if 條件中,導致核心邏輯深陷在巢狀結構內,這被稱為「條件迷宮 (Conditional Mazes)」。資深工程師則採用「Guard Clauses (守衛子句)」,優先排除無效或錯誤的執行路徑,讓正常的業務邏輯 (Happy Path) 能夠在最外層清晰展開。

技術細節與程式碼展示: 與其撰寫層層嵌套的結構,不如提早拋出錯誤:

async function updateUserProfile(userId: string, input: ProfileInput) {
  const user = await getUser(userId);

  // 提早返回:過濾無效狀態
  if (!user) throw new NotFoundError("User not found");
  if (!input.email) throw new ValidationError("Email is required");
  if (!user.canEditProfile) throw new ForbiddenError("User cannot edit profile");
  
  // 核心業務邏輯直接浮現
  return saveProfile(user.id, input);
}

架構意義:這符合「Fail Fast」原則。在處理生產環境事故時,工程師能依序且直觀地理解「什麼情況會阻止程式執行」,而不需要在腦海中維持複雜的條件狀態樹。

2. 基於業務意義命名 (Name the Business Meaning)

許多開發者習慣使用 dataresultpayloaditem 這些反映技術載體的詞彙來命名變數。然而,當系統變大時,這些詞彙會失去上下文,導致語義不清(例如 activeUsers 可能包含被停權但未刪除的用戶)。

技術細節與程式碼展示:

// 菜鳥寫法:只表達了這是一個結果與狀態
const result = await getData(id);
if (result.status === "active") {
  await process(result);
}

// 資深寫法:表達了領域模型與業務意圖
const subscription = await getSubscription(subscriptionId);
if (subscription.isBillable) {
  await chargeSubscription(subscription);
}

架構意義:良好的命名本身就是一種防禦性設計,它創造了「誤用的摩擦力」。在微服務架構或領域驅動設計中,使用 Ubiquitous Language (通用語言) 能夠確保技術實作與業務邏輯的緊密對齊。

3. 建立外部混亂的隔離邊界 (Boundaries Around External Chaos)

第三方 API、Webhook 或是外部資料庫的結構是不穩定的。如果讓外部系統的資料結構(如 response.data.user_name)直接滲透到核心業務邏輯或 UI 層,那麼第三方系統的任何變更都會引發全域性的重構。

技術細節與程式碼展示: 資深工程師會在系統邊界建立映射層 (Mapping Layer) 或防腐層 (Anti-corruption Layer):

// 建立邊界,將外部的蛇形命名與不穩定結構,轉換為內部控制的領域模型
function mapBillingCustomer(response: BillingCustomerResponse): Customer {
  return {
    id: response.id,
    name: response.user_name,
    isBillable: response.status === "ACTIVE",
    planName: response.subscription?.plan_name ?? "Free"
  };
}

架構意義:「永遠不要讓你無法控制的系統,來定義你能控制的系統的形狀」。這有效控制了爆炸半徑 (Blast Radius),當第三方 API 升級或欄位變更時,只需要修改這個轉接器 (Adapter/Mapper) 即可。

4. 讓無效狀態難以存在 (Make Invalid States Hard)

為了讓編譯器 (如 TypeScript) 不報錯,開發者常將所有屬性設為可選 (?),這導致整個系統充滿了對 null 或 undefined 的猜忌與防禦性檢查。

技術細節與程式碼展示: 與其使用一個充滿 Optional 的泛用型別,不如誠實地建模不同的業務狀態:

// 定義不同生命週期的精確狀態
type DraftUser = { email: string; role: "admin" | "member"; };
type SavedUser = { id: string; email: string; role: "admin" | "member"; status: "active" | "disabled"; };

// 使用 Discriminated Unions 處理複雜狀態
type Payment =
  | { state: "pending"; id: string }
  | { state: "authorized"; id: string; authorizationId: string }
  | { state: "captured"; id: string; receiptId: string }
  | { state: "failed"; id: string; reason: string };

// 函數簽名直接要求特定的安全狀態
function sendReceipt(payment: Extract<Payment, { state: "captured" }>) {
  return emailReceipt(payment.receiptId);
}

架構意義:這是「Parse, don’t validate」理念的延伸。在型別系統層面消滅不合法的狀態組合,可以大幅減少執行期的 Bug (如對尚未授權的付款進行退款)。

5. 分離決策與行動 (Separate Decisions From Actions)

將「判斷邏輯」與「副作用 (如資料庫寫入、發送 API、寄送 Email)」混在一起,會使得單元測試變得極其困難,因為你必須 Mock 大量的外部依賴。

技術細節與程式碼展示: 將決策抽離成純函數 (Pure Function):

// 決策層:純函數,極易進行單元測試
function getRefundEligibility(invoice: Invoice): RefundEligibility {
  if (invoice.status !== "paid") return { allowed: false, reason: "Invoice is not paid" };
  if (invoice.refundedAt) return { allowed: false, reason: "Invoice is already refunded" };
  if (invoice.amount <= 0) return { allowed: false, reason: "Invalid refund amount" };
  return { allowed: true };
}

// 行動層:只負責執行決策與副作用
async function refundInvoice(invoiceId: string) {
  const invoice = await getInvoice(invoiceId);
  const eligibility = getRefundEligibility(invoice); // 調用決策

  if (!eligibility.allowed) throw new ValidationError(eligibility.reason);

  await paymentProvider.refund(invoice.paymentId);
  await markInvoiceRefunded(invoice.id);
}

架構意義:這是命令與查詢職責分離 (CQRS) 和六角架構的核心精神。將核心業務規則與副作用隔離,不僅提高了可測試性,也讓規則更具可重用性。

6. 提供有用的錯誤訊息 (Make Errors Useful)

拋出 { "message": "Something went wrong" } 是一種災難,因為它對後端除錯、前端狀態展示和維運監控都毫無幫助。文字訊息是給人類看的,系統應該依賴結構化的代碼 (Codes)。

技術細節與程式碼展示: 優秀的錯誤響應應該包含結構化的錯誤碼與上下文:

{
  "code": "USER_EMAIL_ALREADY_EXISTS",
  "message": "A user with this email already exists.",
  "details": { "field": "email" },
  "requestId": "req_8f91a2"
}

在後端日誌中:

// 記錄充分的上下文,但絕不記錄敏感資訊 (如密碼、信用卡號)
logger.warn("Refund rejected", {
  invoiceId,
  customerId,
  reason: eligibility.reason,
  requestId
});

架構意義:這增強了系統的可觀測性 (Observability)。透過RequestId 串聯分散式追蹤 (Distributed Tracing),讓排查生產環境問題從「通靈猜測」變成「精準定位」。

7. 針對差異優化,而非演示 (Optimize for the Diff, Not the Demo)

初階工程師追求在本地端把功能跑通就好,經常提交包含重構、新功能、修正 Bug 以及格式調整的「巨大 PR (Pull Request)」。資深工程師知道程式碼審查 (Code Review) 和回滾 (Rollback) 的成本,因此他們優化的是「Diff 的可讀性」。

技術細節與程式碼展示: 將巨大的變更拆分為微小且獨立的 PR 序列:

架構意義:這不僅是 Git 工作流的最佳實踐,更是維持高頻率部署與降低回滾風險的核心。將基礎設施重構與業務邏輯變更分開提交,能保證 CI/CD 流程的順暢與安全。

總結與結論