iT邦幫忙

2026 iThome 鐵人賽

DAY 10
0
Software Development

當 AI 會寫 Code 之後:前端工程師的 30 天 SA/SD 學習筆記系列 第 16 篇

Day 16|焦點實戰:當 AI 寫出難維護的程式,如何用 SOLID 引導重構?

  • 分享至 

  • xImage
  •  

先記住:SOLID 用來解決具體變更風險,不是湊原則。
需要深入時:再做介面與依賴重構。

「遵守 SOLID」之後,怎麼多了十個檔案?

假設 AI 把購物車整理成一堆 class、factory 和 interface,結果改個優惠規則還是得讀完整個專案。
這時不該先問用了幾個設計原則,而是原本的變更困難到底有沒有減少。

今天先嘗試把 SOLID 當成幾個審查問題,就不當成一定要全部套上的模板。

  • SRP:這個模組是不是因為太多不同理由而一起改?
  • OCP:新增行為時,是否能把變動集中在擴充位置?
  • LSP:替換另一個實作後,原本的行為契約還成立嗎?
  • ISP:呼叫者是否被迫依賴不需要的方法?
  • DIP:高階流程是否直接依賴外部細節,還是依賴穩定的抽象?

對前端來說,SOLID 不一定要用 class 或繼承來實作。
它比較像一組幫助我們檢查責任、擴充、替換、介面與依賴的問題。
重要的是降低不必要的連動,而不是讓程式看起來符合某種教科書格式。

先指定這次真正要解的問題

教學情境:checkout 流程直接匯入 httpQuoteService,讀取它特有的巢狀欄位。
換測試替身或新服務時,流程也跟著改。

SRP > 把報價傳輸與結帳協調分開。
ISP > checkout 只需要取得報價,不必依賴同時包含登入、上傳圖片與分析事件的巨大服務。
DIP > 則要求高階流程依賴它需要的抽象能力,而不是外部實作的細節。
DIP > 可以先理解成「核心流程不要直接依賴外部細節」。

Adapter 是轉接頭,負責把後端格式翻譯成內部格式
DIP 則決定依賴方向:checkout 只認得自己需要的 QuotePort,HTTP Adapter 去遵守這個介面。

這樣後端欄位改名時,變動會集中在 Adapter,而不是一路擴散到畫面和流程。

DIP 反轉的是原始碼依賴方向

可以由流程附近定義 QuotePort:它接受購物車快照,回傳領域報價或約定錯誤。
HTTP Adapter 實作這個能力,組裝處再把它交給 checkout。

執行時仍然是 checkout 呼叫取得報價。
但原始碼不再要求 checkout 認識 HTTP Adapter;反而是 Adapter 遵守流程需要的介面。

僅僅加一個 handler,如果 handler 還把外部 DTO 原封不動交出去,就沒有真正隔離外部變動。
TS interface 也不是執行期驗證器,外部資料仍需在邊界檢查。

用很短的差異看重構方向

以下只是依賴關係示意,可別拿來執行:

import { httpQuoteService } from './httpQuoteService'
const quote = await httpQuoteService.fetch(cart)
// QuotePort 由使用它的流程定義,實作在組裝處注入
const quote = await quotePort.getQuote(cart)

重要的不是變數改名,而是 quotePort 的輸出已經是流程理解的報價,包含一致的版本與錯誤語意。測試替身也必須遵守相同約定。

依賴注入是把需要的物件或函式從外面傳入的手法;DIP 是依賴應朝向穩定抽象的原則。
兩者常一起使用,但不是同義詞。
依賴注入簡介:前端中文文章

另外兩個原則怎麼檢查

OCP 可以提醒我們把已知會替換的報價來源放在可擴充邊界,但不表示任何新需求都不能修改舊程式。
LSP 則要求替代實作維持呼叫者需要的契約。
若測試替身永遠同步成功,真實實作會非同步失敗,就容易掩蓋重要行為。
方法名稱相同,不等於行為可替換。

一眼對照

不要急著記名詞,只看「哪裡容易一起壞」:

原本的寫法 遇到什麼問題 改成白話
結帳流程直接呼叫某個 API API 改格式,結帳和畫面都要跟著改 中間放一個小轉接層(Adapter)
畫面自己讀後端的巢狀欄位 每個元件都知道後端細節 先翻成前端看得懂的報價資料
測試要模擬真正的網路服務 測試很難寫,也綁住傳輸方式 測試只提供一個符合規則的假服務

這裡的重點只有一句話:讓結帳流程只處理結帳,不要同時處理 API 格式。

可以交給 AI 的 Prompt

請先指出 checkout 直接依賴 HTTP 實作造成的具體變更風險。依 SRP、ISP、DIP 提出最小重構:由流程定義 QuotePort,HTTP Adapter 負責資料驗證與轉換,在組裝處注入。保持現有功能與錯誤語意;不加入容器或繼承框架。列出真實與測試實作共同遵守的契約,驗證成功、業務拒絕、逾時及版本不一致。

今日練習與筆記

問自己:明天換掉報價來源,哪些檔案應該不受影響?
如果說不出來,先畫依賴方向,再請 AI 重構。
今天的重點不是讓程式看起來像教科書,而是試著讓一個合理變動有可控制的影響範圍。
我覺得這篇連我自己都要反覆看好幾遍才要知道怎麼使用,但盡量先把名詞白話列出來該需要用什麼就用什麼。
明天會檢查拆開之後,是否仍然暗中耦合。


上一篇
Day 15|AI 程式像一團線?從單一職責與模組化開始~
下一篇
Day 17|高內聚、低耦合:先別把所有邏輯塞進 Vue SFC
系列文
當 AI 會寫 Code 之後:前端工程師的 30 天 SA/SD 學習筆記 共 17 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言