Conceito independente de linguagem que decompõe o fluxo de negócios dentro de funções de serviço em blocos declarativos (sequences).
Problema
O SSOT existente cobre apenas o exterior das funções:
| SSOT existente | Escopo coberto | Interior da função? |
|---|---|---|
| OpenAPI | Rotas da API, parâmetros, schema de resposta | X |
| SQL DDL | Estrutura de tabelas, índices, constraints | X |
O interior da função – o fluxo de negócios “consulta -> validação -> criação -> resposta” – não tem onde ser declarado. Só é possível entendê-lo lendo o código de implementação. O sequence preenche esse espaço vazio.
Hierarquia SSOT
O SSaC é a terceira camada, construída sobre os SSOTs existentes.
OpenAPI → API 경계 (경로, 파라미터, 응답)
SQL DDL → 데이터 경계 (테이블, 제약, 인덱스)
SSaC → 함수 내부 (비즈니스 흐름, sequence 선언)
─────────────────────────────────────────────────
구현 코드 → 코드젠이 생성 (에러 핸들링, 보일러플레이트)
As três camadas acima são responsáveis pelas declarações, e o código de implementação é derivado dessas declarações. Tudo que o ser humano escreve são declarações.
Conceitos Fundamentais
sequence
Unidade de declaração tipada dos blocos de execução dentro de uma função.
Declara-se apenas o what (o que fazer); o codegen preenche o how (como fazer).
10 Tipos Fixos
| Tipo | Papel | Exemplo |
|---|---|---|
| authorize | Verificação de permissão | Consulta de política baseada em action/resource/ID |
| get | Consulta de recurso | Model.FindByID(id) -> result |
| guard nil | Encerra se o resultado for null | Erro e encerramento se não existir |
| guard exists | Encerra se o resultado existir | Erro e encerramento se já existir |
| post | Criação de recurso | Model.Create(fields…) -> result |
| put | Atualização de recurso | Model.Update(id, fields…) |
| delete | Exclusão de recurso | Model.Delete(id) |
| password | Comparação de senha | Comparação de hash, encerramento em caso de falha |
| call | Chamada externa | Operações de recurso não-CRUD, encerramento em caso de falha |
| response | Retorno de resposta | json, view, redirect |
Como os tipos são fechados, a geração de código por template matching por tipo é possível. Esta é a base que permite codegen simbólico sem LLM.
Escopo do model
O model não se limita a tabelas do banco de dados. Qualquer recurso que possa ser manipulado via CRUD é um model. Consultas ao banco, verificação de existência de arquivos e chamadas a APIs externas são todos expressos de forma uniforme com get/post/put/delete.
Exemplo de Sintaxe (Go PoC)
É um conceito independente de linguagem, mas a implementação de referência usa a sintaxe de comentários Go. Como a IA já conhece o Go AST, não há custo adicional de aprendizado.
Simples (Criação)
// @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) {}
Complexo (Exclusão + Permissão + Validação + Chamada externa)
// @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) {}
Resultado do Codegen
Implementação derivada da declaração de sequence acima:
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,
})
}
Comparação de Custo de Tokens
| Declaração de sequence | Código de implementação | |
|---|---|---|
| Linhas | 10~15 linhas | 30~100 linhas |
| Conteúdo expresso | what (o que fazer) | how (como fazer) |
| Error handling | Nenhum (gerado pelo codegen) | Totalmente incluído |
| Dependência de bibliotecas | Nenhuma | import, inicialização, chamadas |
| Momento da alteração | Quando o fluxo de negócios muda | Refletido automaticamente ao reexecutar o codegen |
O que o humano mantém é apenas a declaração de sequence. Quando a declaração muda, basta reexecutar o codegen para sobrescrever o código de implementação.
Princípios de Design
early return – contrato comum de todos os tipos
A premissa que sustenta a listagem linear de sequences. Exceto response, todos os sequences encerram imediatamente em caso de falha. call não é exceção. Basta ler de cima para baixo, sem ramificações.
| Tipo | Condição de falha |
|---|---|
| authorize | Sem permissão -> return |
| get | Erro de consulta -> return |
| guard nil | null -> return |
| guard exists | Existe -> return |
| post/put/delete | Erro de DB -> return |
| password | Não corresponde -> return |
| call | Falha -> return |
| response | Último (retorno) |
Como call segue o mesmo contrato que guard, não é necessário adicionar um guard separado após call. O codegen gera automaticamente verificação de erro + early return para todos os calls.
@transaction
Metadado em nível de função. Não é um tipo de sequence (dos 10), mas declara se a função inteira deve ser envolvida em uma transação.
// @transaction
// @sequence get
// @model Account.FindByID
// @param AccountID request
// @result account Account
// ...
Combinado com a estrutura de early return, os limites da transação se tornam naturais:
@transaction declarado
-> falha no guard -> rollback + return
-> último sequence bem-sucedido -> commit
-> erro ocorrido -> rollback + return
Como não há ramificações, o limite da transação também é singular: “a função inteira”. Não é necessário especificar posições de begin/end, e o codegen decide o wrapping apenas pela presença ou ausência de @transaction. Se duas transações forem necessárias, isso significa que há duas responsabilidades. Separe a função.
call – forma especial do model
call possui a mesma essência que model. Se model é a manipulação de recursos expressa via CRUD (get/post/put/delete), call é a manipulação de recursos que não pode ser expressa via CRUD. Ambos invocam operações com dependências externas e retornam em caso de falha.
Manipulação de recursos
+-- model (CRUD) -> get/post/put/delete
+-- call (não-CRUD) -> component ou func
@component– por registro. Quando um padrão repetitivo aparece 3 ou mais vezes, ele é promovido.@func– lógica única. Implementada diretamente por pessoas ou IA.
Lógicas complexas como ramificação com convergência e processamento condicional dentro de loops não estendem o sequence, mas são delegadas ao call. Delega-se, mas o contrato permanece o mesmo – encerramento em caso de falha.
@message
Metadado opcional que pode ser anexado a qualquer tipo de sequence. Especifica a mensagem a ser transmitida ao usuário em caso de falha.
// @sequence guard nil project
// @message "프로젝트가 존재하지 않습니다"
// @sequence post
// @model Session.Create
// @param ProjectID request
// @param Command request
// @result session Session
// @message "세션 생성에 실패했습니다"
Se @message for omitido, o codegen gera automaticamente uma mensagem padrão a partir do tipo + nome do model. Declare apenas quando uma mensagem personalizada for necessária.
Funções puras não pertencem à camada de serviço
Todos os blocos declarados em um sequence são operações com dependências externas. Funcionalidades puras como conversão de formato e cálculo de valores são tratadas internamente no model ou dentro das funções chamadas, não na camada de serviço. A função de serviço faz apenas orquestração (orchestration), e o cálculo puro pertence ao alvo da chamada.
Referência de Tipos
O SSaC não define seus próprios tipos. Ele referencia tipos derivados de SSOTs existentes.
| Origem | Exemplo |
|---|---|
| DB schema (SQL DDL) | Project, Session |
| Especificação de API (OpenAPI) | CreateSessionRequest |
| Definição de interface | FileSystem, Cache |
Convenções de Nomenclatura
| Categoria | Regra | Exemplo |
|---|---|---|
| Tipo | PascalCase, importado do SSOT | Project, Session |
| Variável | camelCase, declarada via @result | project, sessionCount |
| Campo de request | PascalCase, extraído da requisição | ProjectID, Command |
| Variável reservada | camelCase, fornecida pelo framework | currentUser, config |
A diferença de maiúsculas/minúsculas entre tipos e variáveis permite distingui-los apenas pela declaração. project é uma variável, Project é um tipo.
Extensão de Linguagem
O SSaC é um conceito independente de linguagem. Go é a implementação de referência (PoC), e a partir da mesma declaração de sequence é possível gerar código em outras linguagens.
sequence 선언 (공통)
|
+-- Go 코드젠
+-- Python 코드젠
+-- TypeScript 코드젠
+-- ...
A especificação (definição de tipos, sintaxe, regras de validação) e o codegen são separados.
A implementação de referência em Go está disponível no GitHub.