iT邦幫忙

2026 iThome 鐵人賽

DAY 12
0
AI Engineering

AI 寫 Code 之後,我們還需要 Software Architecture 嗎?系列 第 12

Day 12:架構邊界 vs 過度設計——AI 容易把邊界當成「該加更多抽象層」

  • 分享至 

  • xImage
  •  

前言:邊界立好了,怎麼反而更難改了?

「我們已經把架構邊界講清楚了,AI 也照著寫,為什麼程式碼變得更難懂,不是更好維護?」

這是把架構邊界建立起來之後,很容易碰到的下一個問題。前面幾天講的都是「沒有邊界會怎樣」,但邊界本身也可能被誤用——AI 一旦知道「這裡有個邊界該遵守」,很容易把「遵守邊界」理解成「多包一層」,而不是「把改動範圍收斂到對的地方」。 結果邊界立起來了,程式碼卻多了三層它根本不需要的抽象。

今日目標

  • 理解「有邊界」跟「該包一層抽象」是兩件不同的事
  • 認識 AI 為什麼容易把架構規則解讀成「該加更多間接層」
  • 看一組「過度包裝」vs「恰如其分」的具體對照
  • 建立判斷「這裡真的需要抽象層嗎」的簡單標準

邊界的目的是收斂改動範圍,不是製造間接層

這系列從 Day 03 開始就在講一件事:架構的本質是約束「能改到哪裡」,不是規範「怎麼寫」。 Repository 分層收斂的是資料存取邏輯的改動範圍,介面切分收斂的是「呼叫端跟哪個實作綁死」,模組邊界收斂的是「一個改動能不能被限制在一個資料夾內」——這些機制的共同點是:它們解決的是「AI 下次改這裡時,需要查證的範圍有多大」這個問題。

但 AI 讀到「這裡有架構規則」的時候,容易產生一種過度反應:既然架構重要、邊界重要,那是不是應該在每個接觸點都包一層 interface,每個建立物件的地方都套一個 factory,每次呼叫外部服務都包一個 adapter?這種反應的問題在於,它把「架構規則存在」直接等同於「這裡需要更多間接層」,卻沒有先問一個更基本的問題:這一層間接性,實際上收斂了什麼改動範圍?

一組對照:包裝三層 vs 恰如其分

❌ 為了「看起來符合架構」包裝三層:
interface NotificationSenderInterface {
    public function send(string $to, string $message): void;
}

class NotificationSenderFactory {
    public static function create(): NotificationSenderInterface {
        return new EmailNotificationSender(new SmtpAdapter(config('mail')));
    }
}

class EmailNotificationSender implements NotificationSenderInterface {
    public function __construct(private SmtpAdapter $adapter) {}
    public function send(string $to, string $message): void {
        $this->adapter->deliver($to, $message);
    }
}

class SmtpAdapter {
    public function __construct(private array $config) {}
    public function deliver(string $to, string $message): void {
        // 實際寄信邏輯
    }
}
→ 四個類別、一個 factory,全專案目前只有一個地方會用到「寄通知信」,
  也沒有計畫支援第二種通知管道;這一層層間接性沒有收斂任何實際存在的改動範圍,
  只是讓「這裡寄了一封信」這件事,變成要跳四個檔案才看得完的迷宮

✅ 只在真正需要替換點的地方放邊界:
class NotificationSender {
    public function send(string $to, string $message): void {
        mail($to, 'System Notification', $message);
    }
}
→ 一個類別,一個方法,日後如果真的要支援簡訊或第三方通知服務,
  再抽出介面也不遲——現在的程式碼直接反映了現在的真實需求

間接層的價值不是「看起來更架構」,是「未來這裡真的會有替換點的時候,替換不用牽動呼叫端」。 如果一個系統目前確實只有一種通知方式、短期內也沒有計畫增加第二種,那一層介面加上一個 factory,不是架構嚴謹,是在還沒有問題的地方預先解一個不存在的問題。

AI 為什麼特別容易掉進這個陷阱

人類工程師在寫程式碼時,通常帶著「這個專案接下來半年會怎麼演進」的直覺——這種直覺來自對業務脈絡、團隊規劃的長期理解。AI 沒有這種脈絡,它看到的只有「這裡有架構規則」跟「眼前這段程式碼」,缺少「這個抽象層在可預見的未來會不會真的被用上」這個判斷依據。

於是 AI 容易退回一個安全但錯誤的策略:看到任何跟「架構」沾得上邊的規則,就往「加更多結構」的方向解讀,因為『加了總比沒加安全』。 但這個判斷邏輯忽略了一件事——多餘的抽象層不是零成本的,它增加了讀者理解程式碼需要跳的檔案數量、增加了未來要維護的介面契約,這些成本是真實存在的,不會因為「看起來比較架構」就消失。

架構邊界要解決的是「真實存在的改動範圍問題」,不是「看起來像架構的形式」——如果一層抽象拿掉了,程式碼行為完全不變、也沒有任何已知的未來需求會用到它提供的彈性,那這層抽象就是在製造間接性,不是在收斂邊界。

一個簡單的判斷標準:這一層拿掉了會怎樣?

面對「這裡該不該加一層介面/抽象」的判斷,一個實用的問題是:如果把這一層拿掉、直接呼叫具體實作,今天、下個月、可預見的未來,會不會有任何一個已知的理由需要替換掉這個具體實作? 如果答案是「不知道,但以防萬一」,那通常代表現在還不需要這層抽象——「以防萬一」不是一個具體的改動範圍問題,是一個假設出來的、還沒發生的未來。

這跟一條常見的重構紀律是同一個判斷邏輯——「沒有第二個消費者就不要先抽共用層」:抽象值不值得建立,看的是「現在有沒有真實存在的第二個場景」,不是「理論上可能會有」。架構邊界也一樣——邊界該立在哪裡,看的是「現在真實存在的改動範圍風險在哪裡」,不是「架構原則上哪裡都可以立一道邊界」。

今日思考題

回想你手上系統裡某個包了 interface + factory 的地方:如果拿掉這層包裝、直接呼叫具體實作,會不會有任何已知的、具體的理由需要替換掉它?如果想不出來,這層抽象可能從一開始就不是為了解決真實問題而存在的。

今日重點回顧

  • 架構邊界的目的是收斂「真實存在的改動範圍」,不是製造看起來更架構的間接層
  • AI 因為缺少對專案演進脈絡的直覺,容易把「這裡有架構規則」過度解讀成「該加更多抽象層」
  • 判斷一層抽象該不該存在,看的是「拿掉它會不會有已知的具體理由需要替換實作」,不是「以防萬一」
  • 這跟「沒有第二個消費者就不要先抽共用層」是同一個判斷邏輯,只是套用在架構層級

明日預告

明天用一個具體案例,把今天講的「過度抽象化」完整走一遍:AI 為了「遵守分層」,把一個一行程式碼就能解決的簡單功能,包成了四層架構。


上一篇
Day 11:CLAUDE.md/skill 跟架構文件的分工——規範跟決策紀錄的差異
下一篇
Day 13:案例——AI 為了「遵守分層」過度抽象化一個簡單功能
系列文
AI 寫 Code 之後,我們還需要 Software Architecture 嗎?15
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言