Konsep independen bahasa yang mendekomposisi alur bisnis di dalam fungsi layanan menjadi blok deklaratif (sequence).

Masalah

SSOT yang ada saat ini hanya mencakup hingga bagian luar fungsi:

SSOT yang AdaCakupanBagian dalam fungsi?
OpenAPIRoute API, parameter, skema responsX
SQL DDLStruktur tabel, indeks, constraintX

Bagian dalam fungsi — alur bisnis seperti “query -> validasi -> buat -> respons” tidak memiliki tempat untuk dideklarasikan. Satu-satunya cara mengetahuinya adalah dengan membaca kode implementasi. Ruang kosong inilah yang diisi oleh sequence.

Hierarki SSOT

SSaC adalah lapisan ketiga yang dibangun di atas SSOT yang sudah ada.

OpenAPI       → API 경계 (경로, 파라미터, 응답)
SQL DDL       → 데이터 경계 (테이블, 제약, 인덱스)
SSaC          → 함수 내부 (비즈니스 흐름, sequence 선언)
─────────────────────────────────────────────────
구현 코드      → 코드젠이 생성 (에러 핸들링, 보일러플레이트)

Ketiga lapisan di atas bertanggung jawab atas deklarasi, dan kode implementasi diturunkan dari deklarasi tersebut. Yang ditulis manusia hanyalah deklarasi.

Konsep Inti

sequence

Unit deklarasi yang mengetipekan blok eksekusi di dalam fungsi.

Hanya deklarasikan what (apa yang dilakukan), dan codegen yang mengisi how (bagaimana melakukannya).

10 Tipe Tetap

TipePeranContoh
authorizeVerifikasi otorisasiQuery kebijakan berdasarkan action/resource/ID
getQuery resourceModel.FindByID(id) -> result
guard nilKeluar jika hasilnya nullError dan keluar jika tidak ditemukan
guard existsKeluar jika hasilnya adaError dan keluar jika sudah ada
postBuat resourceModel.Create(fields…) -> result
putPerbarui resourceModel.Update(id, fields…)
deleteHapus resourceModel.Delete(id)
passwordBandingkan passwordBandingkan hash, keluar jika gagal
callPanggilan eksternalOperasi resource yang tidak bisa dinyatakan sebagai CRUD, keluar jika gagal
responseKembalikan responsjson, view, redirect

Karena tipe-tipenya tertutup, pembuatan kode melalui template matching per tipe dimungkinkan. Inilah dasar mengapa symbolic codegen dapat bekerja tanpa LLM.

Cakupan model

model tidak terbatas pada tabel DB. Semua resource yang dapat ditangani dengan CRUD adalah model. Query DB, pemeriksaan keberadaan file, panggilan API eksternal — semuanya diekspresikan secara seragam sebagai get/post/put/delete.

Contoh Sintaks (Go PoC)

Meskipun konsepnya independen bahasa, implementasi referensi menggunakan sintaks komentar Go. Karena AI sudah mengenal Go AST, tidak ada biaya pembelajaran tambahan.

Sederhana (Pembuatan)

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

// @sequence guard nil project
// @message "프로젝트가 존재하지 않습니다"

// @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) {}

Kompleks (Hapus + Otorisasi + Validasi + Panggilan Eksternal)

// @sequence authorize
// @action delete
// @resource project
// @id ProjectID

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

// @sequence guard nil project
// @message "프로젝트가 존재하지 않습니다"

// @sequence get
// @model Session.CountByProjectID
// @param ProjectID request
// @result sessionCount int

// @sequence guard exists sessionCount
// @message "하위 세션이 존재하여 삭제할 수 없습니다"

// @sequence call
// @component notification
// @param project.OwnerEmail
// @param "프로젝트가 삭제됩니다"

// @sequence call
// @func cleanupProjectResources
// @param project
// @result cleaned bool

// @sequence delete
// @model Project.Delete
// @param ProjectID request

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

Hasil Codegen

Implementasi yang dihasilkan dari deklarasi sequence di atas:

func CreateSession(w http.ResponseWriter, r *http.Request) {
    // get
    project, err := projectModel.FindByID(projectID)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    // guard nil
    if project == nil {
        http.Error(w, "프로젝트가 존재하지 않습니다", http.StatusNotFound)
        return
    }

    // post
    session, err := sessionModel.Create(projectID, command)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    // response json
    json.NewEncoder(w).Encode(map[string]interface{}{
        "session": session,
    })
}

Perbandingan Biaya Token

Deklarasi sequenceKode implementasi
Jumlah baris10~15 baris30~100 baris
Isi yang diekspresikanwhat (apa yang dilakukan)how (bagaimana melakukannya)
Error handlingTidak ada (dihasilkan codegen)Semuanya disertakan
Dependensi libraryTidak adaimport, inisialisasi, pemanggilan
Waktu perubahanSaat alur bisnis berubahTercermin otomatis dengan menjalankan ulang codegen

Yang dipelihara manusia hanyalah deklarasi sequence. Ketika deklarasi berubah, cukup jalankan ulang codegen untuk menimpa kode implementasi.

Prinsip Desain

early return — Kontrak Bersama Semua Tipe

Prasyarat agar sequence dapat disusun secara linear. Semua sequence kecuali response langsung keluar saat gagal. call pun bukan pengecualian. Cukup baca dari atas ke bawah tanpa percabangan, dan selesai.

TipeKondisi Kegagalan
authorizeTidak memiliki otorisasi -> return
getError query -> return
guard nilnull -> return
guard existsAda -> return
post/put/deleteError DB -> return
passwordTidak cocok -> return
callGagal -> return
responseTerakhir (pengembalian)

Karena call mengikuti kontrak yang sama dengan guard, tidak perlu menambahkan guard terpisah setelah call. Codegen secara otomatis menghasilkan error check + early return untuk setiap call.

@transaction

Metadata level fungsi. Bukan tipe sequence (10 tipe), melainkan deklarasi apakah seluruh fungsi di-wrap dalam transaksi atau tidak.

// @transaction
// @sequence get
// @model Account.FindByID
// @param AccountID request
// @result account Account
// ...

Ketika dikombinasikan dengan struktur early return, batas transaksi menjadi alami:

@transaction dideklarasikan
  -> guard gagal -> rollback + return
  -> sequence terakhir berhasil -> commit
  -> error terjadi -> rollback + return

Karena tidak ada percabangan, batas transaksi juga tunggal yaitu “seluruh fungsi”. Tidak perlu menentukan posisi begin/end, dan codegen menentukan apakah perlu wrapping hanya berdasarkan ada tidaknya @transaction. Jika diperlukan 2 transaksi, itu berarti ada 2 tanggung jawab. Pisahkan fungsinya.

call — Bentuk Khusus dari model

call memiliki esensi yang sama dengan model. Jika model adalah operasi resource yang diekspresikan sebagai CRUD (get/post/put/delete), maka call adalah operasi resource yang tidak bisa diekspresikan sebagai CRUD. Keduanya memanggil pekerjaan yang memiliki dependensi eksternal, dan return saat gagal.

Operasi resource
  +-- model (CRUD)      -> get/post/put/delete
  +-- call (non-CRUD)   -> component atau func
  • @component — Sistem registrasi. Dipromosikan ketika pola berulang muncul 3 kali atau lebih.
  • @func — Logika unik. Diimplementasikan langsung oleh manusia atau AI.

Logika kompleks seperti percabangan lalu penggabungan, pemrosesan kondisional dalam loop, didelegasikan ke call tanpa memperluas sequence. Didelegasikan, tetapi kontraknya tetap sama — keluar saat gagal.

@message

Metadata opsional yang dapat dilampirkan ke semua tipe sequence. Menentukan pesan yang akan disampaikan kepada pengguna saat terjadi kegagalan.

// @sequence guard nil project
// @message "프로젝트가 존재하지 않습니다"

// @sequence post
// @model Session.Create
// @param ProjectID request
// @param Command   request
// @result session Session
// @message "세션 생성에 실패했습니다"

Jika @message dihilangkan, codegen secara otomatis menghasilkan pesan default dari tipe + nama model. Deklarasikan hanya ketika pesan kustom diperlukan.

Fungsi Murni Tidak Ada di Lapisan Layanan

Semua blok yang dideklarasikan dalam sequence adalah pekerjaan yang memiliki dependensi eksternal. Fungsi murni seperti konversi format dan perhitungan nilai ditangani di dalam model atau di dalam fungsi yang dipanggil, bukan di lapisan layanan. Fungsi layanan hanya melakukan orchestration, dan komputasi murni menjadi milik target yang dipanggil.

Referensi Tipe

SSaC tidak mendefinisikan tipenya sendiri. SSaC mereferensikan tipe yang dihasilkan dari SSOT yang sudah ada.

SumberContoh
Skema DB (SQL DDL)Project, Session
Spesifikasi API (OpenAPI)CreateSessionRequest
Definisi interfaceFileSystem, Cache

Konvensi Penamaan

KategoriAturanContoh
TipePascalCase, diambil dari SSOTProject, Session
VariabelcamelCase, dideklarasikan via @resultproject, sessionCount
Field requestPascalCase, diekstrak dari requestProjectID, Command
Variabel reservedcamelCase, disediakan oleh frameworkcurrentUser, config

Perbedaan huruf besar-kecil antara tipe dan variabel memungkinkan pembedaan hanya dari deklarasi. project adalah variabel, Project adalah tipe.

Ekstensi Bahasa

SSaC adalah konsep independen bahasa. Go adalah implementasi referensi (PoC), dan dari deklarasi sequence yang sama dapat dihasilkan kode dalam bahasa lain.

sequence 선언 (공통)
  |
  +-- Go 코드젠
  +-- Python 코드젠
  +-- TypeScript 코드젠
  +-- ...

Spesifikasi (definisi tipe, sintaks, aturan validasi) dan codegen dipisahkan.

Implementasi referensi Go tersedia di GitHub.