# 為什麼軟體工廠會失敗：重新點亮燈光

> 📖 本站完整內容索引（documentation index）：[llms.txt](/llms.txt)

> 原作者：dex (@dexhorthy) · 策展與摘要：EasyVibeCoding · 平台：X (Twitter) · 熱度：🔥🔥 · 日期：2026-07-27

> 原始來源：https://x.com/dexhorthy/status/2081058573556306030

## 證據與延伸閱讀

- [這是軟體工廠失敗第二部分及YouTube連結](https://www.youtube.com/watch?v=Ib5GBkD555M)
- [產品審查階段的文件與HTML視覺稿](https://x.com/dexhorthy/status/2078592010852982977)

## 中文摘要

# 為什麼軟體工廠會失敗：重新點亮燈光

這是「為什麼軟體工廠會失敗」的第二部分。

這場演講的影片版本已在 YouTube 上線：https://www.youtube.com/watch?v=Ib5GBkD555M

## 重新點亮燈光

在第一部分中，我深入探討了為什麼隨著時間過去，我們無法信任模型來維護程式碼庫的品質。為什麼再多的 harness 工程或 tokenmaxxing（拼命塞 token）都無法解決模型訓練和基準測試的問題。為什麼程式品質的「model as judge（模型作為裁判）」機制不如某些人吹噓的那麼有效。

目前來說，裁判就是你——所以我們要將程式碼審查（code review）重新請回來。

![標題為「Optimizing the Lights-On Factory」的軟體工廠最佳化與 agent 工作流程架構圖。](https://pub-75d4fe1e4e80421b9ecb1245a7ae0d1a.r2.dev/curated/bd0ae71facb25af5.jpg)

<details class="chart-data"><summary>展開畫面重點</summary><div class="me-note">頂部中央標題：
Optimizing the Lights-On Factory

左側人員與來源區塊：
- CEO / Vision
- Product Managers
- Engineers
- 指向「stuff to do」的連線

頂部與中上方的使用者與回饋區塊：
- USERS
- 連線至「stuff to do」的標籤：complaints feature requests
- MONITORING
- PROD
- 連線標籤：incidents

任務追蹤與管理區塊（stuff to do）：
- stuff to do
- 包含項目：
  - linear
  - jira
  - state machine
  - issue tracker

Agent 建置與測試區塊：
- 標題：agent builds the thing
- 包含模組：
  - orchestration
  - harness
  - sandbox
  - model
- 虛線邊框模組：
  - automated testing
  - agentic testing e.g. browser / computer use

Pull request 與程式碼審查流程：
- Pull request
- 虛線邊框審查項目：
  - agentic code review
  - agent tests the change
  - human reviews the code（右側綠色區塊，帶有標題文字：put the code review back）

部署與監控迴圈：
- 虛線邊框部署項目：
  - rollout / deployment
- 檢查項目：
  - ci/cd checks
  - unit testing
  - static scanning
  - security checks
- 連線返回 USERS

左下角資訊與 QR code：
- Why Software Factories Fail
- hlyr.dev/wsff-gh
- QR code 影像</div></details>

我們要擁抱自 AI 出現以前就在做的事，也就是在前期做一點規劃，以降低後續漫長又痛苦的審查機率。

我們要尋找槓桿效益，並透過 AI 來協助達成，這會經歷以下 4 個階段：

- 產品需求（Product Requirements）

- 系統架構（System Architecture）

- 程式設計（Program Design）

- 垂直切片（Vertical Slices）

## 產品審查

一切都始於產品審查：一份簡短的文件，用來確定我們要打造什麼以及原因。我們的目標是將兩句話或是一段冗長的語音備忘錄，轉化為半結構化的內容。

首先，我們針對要解決的問題達成共識——也就是以使用者的角度出發，找出使用者真正的困擾。其次，明確定義成功長什麼樣子——也就是在功能上線後，我們能透過什麼指標來判斷這個東西值得打造。理想情況下，這會是一個使用者成效，例如「能夠在更短的時間內完成 XYZ 工作流程」或是「更早達到 ABC 引導里程碑」。有時候則是較低層級的指標，像是錯誤率或延遲數字，有時單純就是「關於 X 的客服單不再出現了」。

我們盡量讓這些討論根植於產品領域，而不是技術領域。身為一個一隻腳踩在產品世界、一隻腳踩在技術世界的人，我發現自己常常在這裡不知不覺陷入技術細節。每當這種情況發生，我就會把它們隨手記下來留到後續階段，然後把焦點拉回使用者實際體驗到的感受。如果技術決策阻礙了產品決策，我們就會先敲定現有的部分，然後進入架構階段，或是針對可行性進行更多原型研究。

既然這些大多與使用者看到的內容有關，我就不會用文字描述它——我會直接製作視覺稿。一個實際螢幕的粗略 HTML 視覺稿，比起用三段文字來辯論，更能有效解決爭議。

以下是一個正在進行中的真實範例——這份文件透過 JSON 大綱確定了功能，接著是兩個實際螢幕的粗略 HTML 視覺稿：

https://x.com/dexhorthy/status/2078592010852982977

當然，並不是所有東西都需要經過產品審查。像是調整文案、一次性執行的腳本、有明確重現步驟的臭蟲（bug）——這些我們依然直接用單次對話（oneshot）丟給 Agent。這個流程適用於那種「如果 Agent 誤解了我們的意圖會付出高昂代價」的變更。

對於這篇以及本系列所有文件，我們採用作者自願參與（opt-in）的審查機制。如果你想在審查過程中節省時間，你可以指定那個原本就會負責審查 PR 的人，然後和他們一起過一次產品／技術規格，可以透過文件註解進行非同步溝通（我們內部對此採用 dogfooding 方式使用 humanlayer，但你也可以很輕鬆地在 GitHub、Notion、plannotator 等工具中完成）。

## 系統架構

當產品審查敲定後，我們就會進入系統架構階段。這並不是什麼新穎的概念，甚至連 vibe coder（憑感覺寫程式的人）也開始對此深信不疑。

> 如果你想在審查過程中節省時間，你可以指定那個原本就會負責審查 PR 的人，然後在進入程式撰寫階段之前，先和他們一起過一次產品／技術規格。

在這個階段，我們會針對服務、端點（endpoint）、綱要（schema）、佇列（queue）以及資料儲存之間如何互相通訊達成共識，而不會深入探討程式設計的細節。為了最大化人類與 Agent 之間的溝通頻寬，我們在這裡大量使用視覺化工具——例如序列圖（sequence diagram）：

![顯示 UI、API、ResourceService 與 Store 之間互動的 sequence diagram 循序圖](https://pub-75d4fe1e4e80421b9ecb1245a7ae0d1a.r2.dev/curated/c5ecedb2b28f047e.jpg)

<details class="chart-data"><summary>展開畫面重點</summary><div class="me-note">畫面為一張深色背景的 sequence diagram 循序圖，包含四個參與者（Lifeline）：UI、API、ResourceService、Store。

互動流程如下：
1. UI 發送請求至 API，標示為 `PUT /resources/:slug`。
2. API 呼叫 ResourceService，傳遞 `create(input)`。
3. ResourceService 向 Store 執行 `insert resource`。
4. ResourceService 回傳 `201 resource` 給 UI。</div></details>

合約 / 端點形狀：

![REST API 端點的 PUT 請求格式與回應結構定義畫面](https://pub-75d4fe1e4e80421b9ecb1245a7ae0d1a.r2.dev/curated/97b6516f566aa945.jpg)

<details class="chart-data"><summary>展開畫面重點</summary><div class="me-note">畫面為深色背景的程式碼介面，左上角有紅、黃、綠三色圓點控制按鈕。內容顯示一個 API 端點的定義：
- `PUT /api/resources/:slug`
- `request: { destination: string }`
- `response: { resource: Resource }`</div></details>

資料模型與轉換：

![建立 `resource` 資料表的 SQL 程式碼片段。](https://pub-75d4fe1e4e80421b9ecb1245a7ae0d1a.r2.dev/curated/6ab938a802fb0355.jpg)

<details class="chart-data"><summary>展開畫面重點</summary><div class="me-note">畫面為一個深色介面的編輯器視窗，左上角依序有紅、黃、綠三顆圓點控制按鈕。視窗內顯示 SQL 程式碼內容如下：

-- new tables
CREATE TABLE resource (
    slug        TEXT PRIMARY KEY,
    destination TEXT NOT NULL,
    created_at  TIMESTAMPTZ NOT NULL DEFAULT now()
);

-- new query shapes
-- SELECT ... FROM ...</div></details>

Mermaid 在這裡很好用，但有時候會流於過度設計，甚至會讓你產生一種「雙方已經達成共識」的錯覺。架構階段具有相當高的槓桿效益，你可以在這個階段預防許多模型可能犯的壞習慣。然而，光靠這樣還不足以產出高品質的程式碼。為了達到這個目的，我們需要程式設計。

## 程式設計

在架構之後，我們要做一件我覺得在 Agentic 程式開發中被嚴重低估的事情：程式設計。

大多數人假設只要架構對了，模型就可以直接火力全開。你可以直接這麼做，但你可能不會喜歡產出的結果。

不過，我看到運作得很好的方式是：在任何人（人類或 Agent）開始撰寫實作之前，我們從架構再往下深入一個層級，去規劃程式碼的外貌：型別、方法簽章（method signature）、程式佈局以及呼叫堆疊（call stack）。

我們第一個版本的程式設計 skill 糟透了。它很難閱讀，令人心力交瘁。我們嘗試過 Mermaid，它有它的用武之地，但我們實際上更愛的是用虛擬碼（pseudocode）呈現的輕量視覺化：

呼叫堆疊樹狀圖（Call-stack trees），適用於任何編排或控制流程的變更。當重點在於「什麼地方正在改變」時，請使用 diff 語法：

![顯示程式碼呼叫流程與分支變更的 diff 介面](https://pub-75d4fe1e4e80421b9ecb1245a7ae0d1a.r2.dev/curated/74f2f245530b1a9f.jpg)

<details class="chart-data"><summary>展開畫面重點</summary><div class="me-note">畫面為深色背景的介面，上方有三個分別為紅、黃、綠的圓點控制按鈕。介面內顯示一段類似程式碼呼叫或執行流程（entrypoint）的文字，內容包含：
- entrypoint
- runCommand
- 以 `+` 標示新增的綠色程式碼行：
  - handleCreateResource
  - ResourceClient.create(input)
  - POST /resources
  - renderResult
- 以 `-` 標示刪除的紅色程式碼行：
  - legacyCreateFlow</div></details>

Dillon Mulroy 談到在他的規劃過程中會使用呼叫圖（call graph），我覺得這完全命中核心。

檔案樹 diff（File-tree diffs）——讓你能隨時掌握程式碼庫的佈局以及檔案的存放位置：

![呈現在 `src/resource` 目錄下的專案檔案變更清單與備註](https://pub-75d4fe1e4e80421b9ecb1245a7ae0d1a.r2.dev/curated/9a3a3c79caa57ae4.jpg)

<details class="chart-data"><summary>展開畫面重點</summary><div class="me-note">畫面顯示一個深色背景的終端機或程式碼編輯器視窗，展示 `src/resource` 目錄底下的檔案狀態與變更備註。

轉錄可見內容：
```
src
└── resource
+     resource-client.ts        # NEW - wraps API contract calls
+     resource-client.test.ts   # NEW - covers request/response mapping
~     resource-route.ts         # MODIFIED - wires create action into UI
```

詳細說明：
- `resource-client.ts` 標示為 `+ NEW`，備註說明為 `# NEW - wraps API contract calls`。
- `resource-client.test.ts` 標示為 `+ NEW`，備註說明為 `# NEW - covers request/response mapping`。
- `resource-route.ts` 標示為 `~ MODIFIED`，備註說明為 `# MODIFIED - wires create action into UI`。</div></details>

關鍵新函式的型別與方法簽章——這些東西對架構文件來說太過內部，但 Agent 卻依然很有可能會搞錯：

![TypeScript 程式碼介面，包含 `Item` 與 `Cursor` 型別定義以及 `resolveTarget` 函式宣告。](https://pub-75d4fe1e4e80421b9ecb1245a7ae0d1a.r2.dev/curated/05cdb8178a28fcab.jpg)

<details class="chart-data"><summary>展開畫面重點</summary><div class="me-note">畫面為一個深色背景的程式碼編輯器視窗，包含以下程式碼內容：

```typescript
interface Item {
    id: ItemId
    parentId: ItemId | null
    // ...
}

interface Cursor {
    position: ItemId
    direction: 'up' | 'down'
    // ...
}

resolveTarget(items: Item[], cursor: Cursor) -&gt; ItemId | null
```

這段程式碼定義了樹狀或階層式結構的資料模型：
- `Item` 包含節點識別碼 `id` 以及可為空值的父節點識別碼 `parentId`。
- `Cursor` 包含目前位置 `position` 與移動方向 `direction`（支援 `'up'` 或 `'down'`）。
- `resolveTarget` 函式接收 `Item` 陣列與 `Cursor` 物件，用以解析並回傳目標的 `ItemId` 或 `null`。</div></details>

這些都不用花太多時間產出（模型負責草擬，你負責跟它辯論），而其中的每一個項目，都是你在程式碼審查期間本來就得隱式做出的決策——而且那是你改變心意代價最高昂的時刻。

## 垂直切片

接下來，我們很喜歡做我稱之為「垂直切片（vertical slices）」的事情——Matt Pocock 和我曾在 2026 年 1 月的一場直播中，聊過垂直切片或是「曳光彈（tracer bullets）」。

模型很喜歡我稱之為「水平計畫（horizontal plans）」的東西——也就是按堆疊順序做事：

1. 資料庫遷移（Database Migrations）

1. 服務層（Service Layer）

1. API

1. 前端（Frontend）

在實務上，這意味著你在進行的過程中，沒有真正的方法去「動手接觸」這個解法。你可以用程式碼來測試，但我建造過的幾乎任何功能，閱讀測試只是一個開端，但在我工作的同時，在瀏覽器中拉起畫面，或是用 curl 呼叫它，始終是我工作流程中頻繁出現的一部分。

在 AI 出現之前，很少有人會在沒有沿途檢查某些東西的情況下，寫出超過 2000 行甚至 500 行的程式碼。

我花了一些時間才注意到我習慣的差異——在 AI 出現之前寫程式時，我總是從中間開始，然後向外擴展。大致上的流程是：

1. 建立 API 合約並提供模擬資料（mock data），用 curl 測試

1. 建立前端來消耗模擬資料，在瀏覽器中反覆迭代並打磨

1. 將 API 連接到服務層（服務層提供模擬資料／行為）

1. 新增資料庫遷移，將服務連接到資料庫

1. 新增一堆商業邏輯

1. 新增一堆錯誤處理

而且我在每個步驟中都會進行測試、迭代和打磨。

如果我很在意這段程式碼，或是對模型在這個程式碼庫區域的表現持懷疑態度，我也會在每個步驟中審查程式碼。檢查 100-200 行並隨時導正方向，在這裡會便宜很多。

大多數最先進的模型在沒有人類引導的情況下，設計不出這樣的計畫，而且要按程式碼庫甚至按任務來通用化是很困難的，所以我比較喜歡在這個環節保持參與（in the loop）。

30 分鐘的規劃可以省下數小時的審查時間

因此，有些步驟我認為人類必須親自參與其中，如果你想在不被堆積如山的爛程式碼（slop code）淹沒、事後試圖清理的前提下，維持接近人類水準的品質（亦即你真的想要跑得快的話）：

1. 產品設計

1. 系統架構

1. 程式設計

1. 垂直切片

很顯然地，我們並不會為我們發布的每一項東西都走完這個完整的流程（見下方的支線任務）。我猜測其分佈大致如下：

- 約 40% 的任務是一次搞定（oneshot），或是透過 1-2 輪的輕量回饋來完成一次搞定

- 對於中型任務，我們會將產品／系統設計全部整合在同一份計畫文件中，不費事將工作拆分到各個階段

- 對於大型任務，我們會走完所有步驟。像大型重構這種做產品階段沒有意義的工作，我們就會跳過產品階段。

在大多數情況下，我會指派模型一次做 1-3 個切片，並在進行的同時審查程式碼。比起在累積了 2000 多行程式碼、完全不知道哪裡壞掉的另一端才發現問題，在一開始就導正方向（無論是內部邏輯還是實際功能）要容易得多。

## 你可能覺得自己有太多 Pull Request 了

你不是有太多 PR，而是你有太多爛 PR。

早在 AI 出現之前，我們就已經審查過許多需要大幅重工的 PR。

但一個優秀的 PR 審查起來是一種享受。你瀏覽著每一個檔案，程式碼乾淨俐落，它遵循了你所有的決策、討論，以及對於軟體應該如何撰寫的堅定觀點。

另一方面，如果一個 Pull Request 甚至需要 20% 的重工（這已經很寬容了，我會說大多數 AI 一次搞定的 PR 接近 50%），這對提交者和審查者來說，都是一場智力與情感上的負擔。（即使提交者是 AI，也很可能有人啟動了這項工作、用 vibe 潤飾了 AI 的結果，或者至少，有人在乎這個結果）。

為了替你省下時間（我們快要結束了），我在一個支線任務中隨性聊了更多關於這點的內容：

「時間都去哪了」

## 約束理論（2026 年版）

對於這裡的核心論題，難免會讓人感到有些沮喪：「目前我們就是得乖乖讀程式碼」。

我原本對一個世界充滿期待：我們可以單純開口要求，然後讓模型火力全開，我們甚至不用讀程式碼，就能獲得漂亮的生產級軟體，它會隨著時間演進，而且不會變成一團爛泥。

但我盡我所能在這裡列出來的，全部都是約束。模型有些事情很擅長，有些事情則不太拿手。在這些約束之下，你該如何最佳化你的工作流程？

你可能正忙著試圖讓速度提升 10 到 100 倍，並試圖說服自己程式品質已經不再重要，然而此時此刻，你其實可以擁抱這些約束，安全地讓速度提升 2 到 3 倍。

我最後給予的建議基本上是：

1. 深入了解約束，透過頻繁與模型合作來培養直覺

1. 在這些約束的範圍內最佳化系統

1. 尋找槓桿效益

1. 好好讀一下該死的程式碼

就是這樣。如果你想留下來聽推銷，請繼續往下捲動吧。希望這能幫你避開災難，或者至少你在看著那些可愛的小動畫時覺得很有趣。

謝謝閱讀

  -dex

## 附註：我們對此著迷不已

我們正在打造 humanlayer.com，這是一個 Agentic IDE 與協作平台，目標是幫助你以 2 到 3 倍的速度前進，同時維持人類（或非常接近人類）水準的程式品質。

我們正朝著兩個核心理念邁進：「你軟體工廠的積木」以及「適用於軟體可維護性的更好驗證器」（或許還有更好的模型）。

對於不超過 3 人的小型團隊，HumanLayer 是免費的。如果你需要上手協助，歡迎來到我們的 Discord 聊聊，或是寄信至 founders@humanlayer.dev 與我們聯繫。

特別感謝 @calvinfo 提供靈感、我的共同創辦人 @0xBlacklight、@swyx 以及 @aiDotEngineer 的團隊為我提供了一個探索這些想法的舞台，同時也要感謝所有支持我們的優秀客戶、投資人、朋友和家人。

如果你想了解更多，我基本上對此喋喋不休，因此你可以在下方找到這篇文章的所有連結，以及這項素材在 Podcast、長篇白板討論等其他形式的延伸內容。

## 附註二：其他資源

Podcast 與文章：

- Dex 與 Gergely 在 The Pragmatic Engineer 上談論 context 工程與軟體工廠 - 2026 年 7 月

- Dex 與 Matt Pocock 談論常青的 AI 程式開發建議（以及 ralph loops）- 2026 年 1 月

AI That Works 系列單集：

- 基準測試證明不了什麼

- 用於 AI 程式開發的產品規格

- 透過學習測試來獲得更好的背壓（backpressure）

- 將 12-Factor Agents 原則應用於 AI 程式開發

本文相關連結：

- 為什麼軟體工廠會失敗主題演講 — AI Engineer World's Fair 2026

- StrongDM 的關燈軟體工廠（lights-off software factory）

- OpenAI：Harness Engineering（2026 年 2 月）

- Ryan Lopopolo 談論 Symphony（演講，2026 年 4 月）

- Mario 在 AI Engineer Europe：「在爛程式的世界裡打造 pi」

- FT（金融時報）：程式碼 Agent 出包導致亞馬遜服務中斷

- Matt Pocock：崩壞中的程式碼庫

- Faros AI：AI 加速陣痛報告

- 針對程式開發 Agent 的進階 context 工程（演講 8/25）

- 不允許 Vibes（No Vibes Allowed）（演講 11/25）

- 我們對 RPI 搞錯的一切（演講 3/26）

- Awesome-RLVR - 強化學習資源

- 針對程式開發 Agent 的進階 context 工程（文章）

- 12-Factor Agents

- Addy Osmani 談 vibe-coding 與維護

- 1968 年 NATO 軟體工程會議

- 美國國防部 DevSecOps 參考設計（PDF）

- Ramp 的程式開發 Agent 平台

- Stripe：Minions，一次搞定的端到端程式開發 Agent

- WorkOS：Project Horizon

- Brex（Latent Space）

- Dan Shapiro：軟體工廠的五個等級

- Simon Willison 談 StrongDM 的軟體工廠

- 「把海水煮沸」（Boil the ocean，比喻好高騖遠）

- 散彈槍式外科手術（Shotgun surgery，refactoring.guru）

- John Ousterhout — A Philosophy of Software Design

- Robert C. Martin — Clean Code

- Martin Fowler — Refactoring

- aider

- cline

- codebuff

- SWE-Agent 論文（2024）

- OpenAI Codex 演講（11 月）

- Calvin French-Owen — AI Council 演講

- SWE-bench Multilingual（資料集）

- AIE Worlds Fair 2026 - 偉大的迴圈辯論（「炒作超越了紀律」）

- SWE-Marathon (Abundant AI)

- DeepSWE (Datacurve)

- Frontier Code (Cognition)

- 突變測試（Mutation testing，維基百科）

- Dillon Mulroy 談規劃中的呼叫圖

- Dex × Matt Pocock：垂直切片／曳光彈（直播，2026 年 1 月）

- 「思考的苦工是無法外包的」（Jake Nations）

## 標籤

演講, 其他, HumanLayer
