2026/11/02

12-Factor App

12-Factor App 是 Cloud Based 軟體開發的方法。它最初由 Heroku 的共同創辦人 Adam Wiggins 於 2011 年提出,總結當時在該平台上開發與部署應用程式後所獲得的寶貴經驗。2010 年代,系統正在從傳統伺服器,轉向 PaaS 與 SaaS。Heroku 的工程團隊整理出這套規範,讓開發者能建構出更具 Scalability 及 Portability 易於維護的應用程式。

方法的目標:

  • 標準化

    以宣告方式 declarative,建立自動配置,減輕新的開發人員初次參與專案的時間與成本

  • 可移植性

    有clean contract 明確的定義,確認作業系統,並能提供在不同執行環境運作的最大彈性

  • 可部署在 cloud platforms

    適合部署在先進的雲端系統,減少伺服器與系統的管理問題

  • 持續部署

    減少開發與正式環境的差異,能夠持續部署,以達成 agility 最大化

  • scale up

    不需要改變工具、架構、開發環境,就能快速因應大流量

1. Codebase

One codebase tracked in revision control, many deploys

一份在 vevision control 管理的程式碼,可部署在多個執行環境

2. Dependencies

Explicitly declare and isolate dependencies

明確地宣告及隔離相依性

3. Config

Store config in the environment

在執行環境中儲存設定配置,不要寫在程式裡面

4. Backing services

Treat backing services as attached resources

把DB,Cache, MQ,SMTP 等等外部資源,透過 URI 的方式存取

5. Build, release, run

Strictly separate build and run stages

嚴格分離 Build, Release, Run 階段

  • build 是編譯成服務元件

  • release 是將元件發佈到 registry,提供給外部執行環境下載

  • run 是在執行環境取得元件,搭配部署設定執行該元件

6. Processes

Execute the app as one or more stateless processes

以一到多個無狀態程序執行app

7. Port binding

Export services via port binding

透過 service port binding 對外提供服務

8. Concurrency

Scale out via the process model

透過 process model 水平擴充

  • 每一個 service app 都是獨立的 process,可啟動多個 thread 分散 process 性能壓力

  • 同一個 service app 也可以啟動多個 instances

9. Disposability

Maximize robustness with fast startup and graceful shutdown

快速啟動/優雅終止 app,最大化系統穩定度

10. Dev/prod parity

Keep development, staging, and production as similar as possible

盡可能保持dev、pre-release、prod環境相同

11. Logs

Treat logs as event streams

將 logs 視為事件串流

  • 微服務應該建立統一的服務來管理日誌(ELK、Graylog、Cloudwatch...)

  • 每個運行的微服務都直接透過Stdout和Stderr來輸出日誌。開發時期透過console來查看時間排序下的Event log。正式環境,則是透過 log 管理服務,來收集、聚合、索引、分析這些Log

12. Admin processes

Run admin/management tasks as one-off processes

把維護/管理任務當作一次性process執行

  • 例如 db migration, db snapshot, schema/table更動,定期renew憑證等等

  • 把這些一次性作業寫成腳本或是Shell,當成一般程式來執行,也進到Git做版控

References

The Twelve-Factor App

[12 Factor原則簡介

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。主要用在簡短的教學及範例程式。如果是大型正式的專案,還是不適合使用。