2026/10/19

Harness Vibe Coding

Harness 這個詞,當作名詞時,最核心的意思是「束縛帶」、「馬具」或「控制、利用的工具」;當作動詞則是「駕馭」、「利用」。搭配了 Harness Engineering 以及 Harness Vibe Coding。就是透過 harness 這個單字的意思,描述一個 AI 工程的工具,需要在使用時,透過約束、引導、監控的方法,來完成工作。

AI 模型的程式生成能力非常強大、速度極快且不知疲倦,但如果放任不管,它可能會朝錯誤的方向亂跑、產生幻覺或寫出無法維護的程式碼。Harness 就是一套用來約束、引導、監控 AI 的機制與工具系統(例如:架構約束、自動化測試、型別檢查、CI/CD 迴圈、特定的 Context 規範)

Vibe Coding 最初是指人們只靠著跟 AI 對話、憑感覺指揮 AI 生成程式碼,不管底層細節。但這種方法如果要做大型、長久維護的專案,就會遇到瓶頸。這時就會需要 Harness。

實踐 Harness Engineering 可以從以下四個層面著手:

1. 上下文與邊界工程(Context & Boundary Engineering)

AI 之所以會寫出不符合架構的程式碼,通常是因為它「看不全」或「看錯了」全貌。Harness 的第一步是為 AI 提供絕對清晰的地圖與邊界:

  • 專用導航文件(如 AGENTS.md 或 .cursorrules):在專案根目錄建立專門給 AI 閱讀的說明書,明確規定專案採用的架構(例如:嚴禁直接在 Controller 呼叫資料庫等)。

  • 限制修改範圍(File-level Scoping):在執行 AI Agent 時,明確限制它只能修改特定的目錄或檔案,防止它不小心覆蓋了核心安全性或基礎設定。

2. 高頻自動化回饋迴圈(High-Frequency Feedback Loops)

AI 生成程式碼後,最怕的是「靜默失敗」或引入隱含的邏輯錯誤。Harness 必須建立一套能讓 AI 「自我修正」的閉環系統:

  • 嚴格的型別系統與編譯檢查:採用強型別語言或完整的 TypeScript/JSDoc/Java 泛型約束。當 AI 寫出型別不符的程式碼時,編譯器錯誤訊息(Error Traceback)會立刻被擷取並丟回給 AI,讓它在下一輪對話中自我修復。

  • 單元測試與整合測試防線:在 AI 介入前,確保專案具備高覆蓋率的測試。當 AI 完成修改後,自動執行測試。如果測試失敗,測試報告就是回饋給 AI 的精確導引。

  • Linter 與 Static Analysis 門神:Linter(代碼檢查工具)是一個在軟體開發中用來自動分析原始碼的工具。它不需要實際執行程式,就能掃描程式碼並標記出潛在的錯誤、語法問題、安全漏洞以及不符合規範的風格寫法。透過 ESLint、Checkstyle、SonarQube 等靜態檢查工具,在程式碼落地前就攔截掉潛在的效能陷阱或語法不規範。

3. 沙盒與執行權限隔離(Sandboxing & Least Privilege)

當你使用更具自主性的 AI Agent(能自己執行 terminal 指令、安裝套件)時,Harness 的角色就變成了「安全沙盒」:

  • 容器化執行環境:將 AI 執行的終端機指令關在 Docker 容器或虛擬機中,避免 AI 誤下一行 rm -rf / 或修改到主機的敏感設定。

  • 最小權限原則:限制 AI Agent 的 API Key 或工具權限(例如:唯讀存取生產環境資料庫、禁止直接推送到主分支 main/master)。

4. 人類閘道與語意審查(Human-in-the-Loop & Semantic Gatekeeping)

Harness 不僅是自動化工具,還包含人類工程師的防禦策略:

  • 原子化 PR 審查(Atomic Pull Requests):強迫 AI 一次只做一件小事(例如「只修復這個登入驗證 Bug」或「只實作這個特定的 DTO 轉換」),不要讓 AI 一次修改幾十個檔案,這會大幅增加人類審查(Code Review)的盲點。

  • 關注語意而非語法:人類工程師在審查 AI 產出的程式碼時,可以完全不用檢查語法(因為 Harness 已經過編譯與測試把關),而是專注於業務邏輯是否正確、邊界條件(Edge Cases)是否考慮周全。

傳統的軟體工程是「人寫程式、機器執行」;而在導入 AI 後的軟體工程,人類的職責正在轉變為 Harness Architect,不需要手動敲每一行程式碼,而是透過建立嚴密的測試、型別、規範與回饋迴圈,讓 AI 在這條高速公路上狂飆的同時,永遠不會翻車。

2026/10/12

JEP 512 Compact Source Files and Instance Main Methods

java 的第一個範例程式 HelloWorld 必須要這樣寫,但初學者不能理解,為什麼一定要寫 class,main method 一定要宣告 public static void,也必須要加上字串陣列參數。

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, world!");
    }
}

自 JDK 21 開始,就有幾個簡化入門程式的 preview 功能 JEP,然後到了 JDK 25,正式 final 了 JEP 512。

主要的改動是,可以不寫 class,可以簡寫 main 為 instance method,也就是不需要宣告 public static void

JEP 512 核心功能

Compact Source Files

可以不寫 class

public static void main(String[] args) {
    System.out.println("Hello, world!");
}

Instance Main Methods

可以去掉 main method 的宣告

void main() {
    System.out.println("Hello, world!");
}

支援直接執行

傳統的 java 程式,必須要先編譯 javac HelloWorld.java 為 HelloWorld.class,然後才能執行 java HelloWorld

現在可以直接執行 HelloWorld.java

java HelloWorld.java

Summary

這些功能,並不是 Java 的常態。而僅只是為了讓初學者用類似 python 的腳本式語言的方式,學習並入門 Java。主要用在簡短的教學及範例程式。如果是大型正式的專案,還是不適合使用。

2026/09/14

JEP 467 Markdown Documentation Comments

自 JDK 23 開始,javadoc 支援在每一行 javadoc 中,以 /// 開頭的方式,標記為markdown 格式的 javadoc,這種方式取代舊的 /** **/ ,並支援 markdown 語法。

markdown 是簡化的 html,以往在 javadoc,需要用大量的 html tag,標記為

,

    , ,現在支援 markdown 語法的 標題、列表、代碼塊、連結、粗體/斜體,讓 javadoc 的內容更精簡。

    新舊兩種註解寫法是同時支援的。新的 markdown,除了比較簡潔以外,解決了傳統的 javadoc 使用 html,太難寫,需要寫很多 html tag 的問題,在查看 code 裡面的註解時,markdown 的可讀性明顯比 html 高。

    支援的 markdown 語法

    • 粗體,斜體文字

    • 段落與換行

    • 有序及無序的列表 list

    • 程式碼

    • 標題

    • 連結

    • 表格

    markdown javadoc 範例

        /// 這是使用 Markdown 格式的註釋。
        ///
        /// # 範例功能
        /// * 使用 **Highlight** 語法。
        ///
        /// # 程式區塊:
        /// ```java
        /// test("param");
        /// ```
        ///
        /// # 列表
        /// 1. 項目1
        /// 2. 項目2
        /// 3. 項目3
        ///
        /// # 連結 [google]("https://www.google.com")
        /// * 連結
        /// - 模組 [java.base/]
        /// - 套件 [java.util]
        /// - 類別 [String]
        /// - 欄位 [String#CASE_INSENSITIVE_ORDER]
        /// - 方法 [String#chars()]
        /// - 同一類別其他方法: [equals][#equals(Object)]
        ///
        /// # 表格
        ///
        /// | Latin | Greek |
        /// |-------|-------|
        /// | a     | alpha |
        /// | b     | beta  |
        /// | c     | gamma |
        ///
        /// @param param1 參數
        /// @return 回傳值