Service Sequences as Code — GoコメントDSLからサービスコードを生成する。

サービスロジックは一連の決定だ:どのモデルをクエリするか、何を防御するか、いつ拒否するか、何を返すか。これらの決定はビジネスを理解する人のものだ——しかしボイラープレートに埋もれ、レイヤーに散らばり、リライトで失われる。

SSaCはこれらの決定を宣言的な仕様として保存する。何が起こりどの順序かを宣言すれば、ツールが実装を生成する。

specs/service/*.go  →  ssac validate  →  ssac gen  →  artifacts/service/*.go

GitHub

核心アイデア

すべてのサービス関数はステップのシーケンスだ。各ステップはバイナリ契約に従う:成功 → 次の行、失敗 → return。これは我々が発明した抽象ではない——サービスロジックがすでに動いている方法だ。SSaCはこれを明示的にする。

10の固定シーケンスタイプがこの契約に従うすべてのサービス層操作をカバーする。合わないものはcallに委譲する。集合は設計上閉じている。

LLMなし、推論なし——テンプレートからの純粋なシンボリックコード生成。仕様が単一の真実の情報源だ。

// @sequence get
// @model Project.FindByID
// @param ProjectID request
// @result project Project

// @sequence guard nil project
// @message "project not found"

// @sequence post
// @model Session.Create
// @param ProjectID request
// @param Command request
// @result session Session

// @sequence response json
// @var session
func CreateSession(w http.ResponseWriter, r *http.Request) {}

この10行の宣言が以下のコードを生成する:

func CreateSession(w http.ResponseWriter, r *http.Request) {
    projectID := r.FormValue("ProjectID")
    command := r.FormValue("Command")

    project, err := projectModel.FindByID(projectID)
    if err != nil {
        http.Error(w, "Project lookup failed", http.StatusInternalServerError)
        return
    }

    if project == nil {
        http.Error(w, "project not found", http.StatusNotFound)
        return
    }

    session, err := sessionModel.Create(projectID, command)
    if err != nil {
        http.Error(w, "Session creation failed", http.StatusInternalServerError)
        return
    }

    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(map[string]interface{}{
        "session": session,
    })
}

シーケンスタイプ(10)

タイプ役割
authorize権限検査(OPA等)
getリソース検索
guard nilnullなら終了
guard exists存在すれば終了
postリソース作成
putリソース更新
deleteリソース削除
passwordパスワード比較
call外部呼び出し(@component / @func)
responseレスポンス返却(json)

コード生成機能

/api/reservations:
  get:
    operationId: ListReservations
    x-pagination:
      style: offset
      defaultLimit: 20
      maxLimit: 100
    x-sort:
      allowed: [start_at, created_at]
      default: start_at
      direction: desc
    x-filter:
      allowed: [status, room_id]
    x-include:
      allowed: [room, user]

ライセンス

MIT — GitHub