Clean architecture
Skill tbc-servicos/dataagile-agent-kit/fluig/skills/clean-architecture
Plugin Claude Code para Protheus e ADVPL/TLPP — base 155k+ registros, Agent Teams, compilação TDS-CLI, testes TIR e MCP PO-UI
npx -y skills add tbc-servicos/dataagile-agent-kit --skill clean-architectureAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Aplica os princípios de Clean Architecture (livro de Robert Martin, o Uncle Bob) ao desenvolvimento Fluig — regra de dependência e camadas no widget Angular + PO-UI (component → service de aplicação → domínio puro → adapter HTTP/Dataset), datasets server-side e eventos de workflow como adaptadores finos, SOLID em TypeScript com a DI do Angular. Use quando o dev pedir para "organizar o widget em camadas", "desacoplar regra de negócio do componente", "aplicar clean architecture", "aplicar SOLID", "onde colocar essa regra", "dataset está gigante" ou quando o brainstorm/plan/review precisar de critério estrutural de design.
SKILL.md
7.3 KB, as published. Nobody here has run it
Clean Architecture aplicada ao Fluig
Destilação prática dos princípios de Clean Architecture para os dois mundos do Fluig: o widget Angular + PO-UI (front) e o lado plataforma (datasets, eventos de workflow e formulários). Objetivo: regra de negócio que sobrevive a troca de tela, de endpoint e de versão — e é testável com Jasmine/Karma sem HTTP nem plataforma no ar.
Skills irmãs:
/fluig:ddd(modelagem — o que construir), esta (estrutura — como organizar). Se o time também usa o plugin protheus, os equivalentes são/protheus:clean-architecturee/protheus:ddd— mesmos princípios, outro stack.
Consulta MCP (antes de gerar código)
- Versão do Angular/PO-UI: nunca fixe em código novo. Leia o
package.jsondo projeto; para projeto novo, use a versão estável atual do Angular (o PO-UI acompanha o major do Angular). Confirme via MCP — não confie na memória do modelo para versão. - MCP do Angular CLI (
npx -y @angular/cli mcp):get_best_practicesesearch_documentationantes de decidir padrão (standalone, signals, control flow);list_projectspara entender o workspace;modernize/onpush_zoneless_migrationem código legado. - MCP do PO-UI (
@po-ui/mcp, já configurado no plugin):list_components+get_component_docsantes de escrever qualquer componente visual;get_guidepara temas (acessibilidade, theming). - MCP tbc-knowledge:
searchFluigPatterns({ category: "conventions" })para as convenções do plugin (estrutura de pastas, namingwg_/ds_/wf_).
A Regra de Dependência
Dependências apontam para dentro: apresentação → aplicação → domínio ← infraestrutura. A regra de negócio não conhece componente, template, HttpClient nem DatasetFactory.
[ Component/Page PO-UI · template · evento de form · evento de workflow ] ← entrada/saída
↓ chama
[ Service de aplicação (caso de uso): orquestra, coordena estado ] ← aplicação
↓ chama ↓ chama (via interface)
[ Domínio: classes/funções TS puras ] [ Adapter: HttpClient, DatasetFactory, hAPI ]
Teste rápido de violação: se o mesmo arquivo tem template/HTTP E um cálculo/decisão de
negócio, ele está em duas camadas — dividir. Vale para .component.ts e para ds_*.js.
Mapa de camadas → artefatos Fluig
No widget (Angular + PO-UI)
| Camada | Artefato | Regra |
|---|---|---|
| Domínio | domain/ — classes e funções TS puras (cálculo, validação, decisão) | Zero import de @angular/* ou @po-ui/*. Testável com Jasmine puro, sem TestBed |
| Casos de uso | services/ de aplicação (aprovacao.service.ts) | Orquestra: chama domínio + repositórios, expõe estado (signal/observable) para a página |
| Adaptadores de dados | services/api/ (pedido-api.service.ts) | Só HTTP/DatasetFactory: monta request, traduz response em modelo do domínio. Nenhum if de negócio |
| Apresentação | components/, pages/ | Dumb por padrão: recebe input, emite output, delega ao service. Lógica no template = só exibição |
- A DI do Angular já entrega o DIP: o caso de uso recebe o adapter pelo construtor
(
inject()); para testar, provê-se um dublê noTestBed— semHttpTestingControllerpara testar regra de negócio. - Componente com
HttpClientinjetado = violação direta (pula duas camadas).
No lado plataforma (server-side JS)
| Camada | Artefato | Regra |
|---|---|---|
| Adaptador | createDataset() / evento (afterStateEntry, validateForm) | Fino: extrai entrada (constraints, hAPI, campos), chama as funções de regra, devolve/grava. try/catch + log aqui |
| Domínio | Funções puras no mesmo arquivo (Rhino não tem import) | Recebem dados, devolvem resultado. Sem DatasetFactory, sem hAPI, sem log |
| Infra | Funções buscarX()/gravarY() que encapsulam DatasetFactory/SQL/REST | Todo acesso a dado externo vive aqui; a URL/serviço do Protheus aparece num único lugar |
O antipadrão nº 1 do Fluig é o god-dataset: createDataset() com 300 linhas fazendo
constraint parsing + REST + regra + montagem de dataset. A refatoração guiada está em
references/plataforma-datasets-eventos.md.
SOLID em TypeScript/Angular — resumo operacional
- SRP — um service = um assunto; componente > ~200 linhas ou service que mistura HTTP + regra + formatação → dividir.
- OCP — variação por estratégia injetada (token de DI + implementações), não
switchde tipo replicado. - LSP — implementações de uma interface honram o contrato (sem
throw "não suportado"). - ISP — interfaces por papel (
ConsultaPedidos,AprovaPedidos), não umApiServicegordo. - DIP — casos de uso dependem de abstração (
abstract class/token); Angular DI injeta a concreta. Detalhes e exemplos:references/camadas-widget-angular.md.
Quando aplicar (pragmatismo)
| Tamanho | Estrutura mínima |
|---|---|
| Dataset de consulta simples, evento trivial | Só a regra de sempre: função extraída se houver decisão de negócio |
| Widget pequeno (1 página, 1 fonte de dados) | api.service separado do service de aplicação; domínio se houver cálculo |
| Widget grande / processo com regra rica | Camadas completas + domain/ com specs próprios |
Não crie domain/ para um widget que só lista um dataset — sobre-engenharia também é dívida.
Fluxo de uso
- Design (
/fluig:brainstorm//fluig:plan): por caso de uso, defina os artefatos por camada antes de codar; marque o que é regra pura (testável sem TestBed/plataforma). - Implementação (
/fluig:widget,/fluig:dataset,/fluig:workflow,/fluig:implement): siga os esqueletos das references. - Review (
/fluig:review): checklist estrutural emreferences/plataforma-datasets-eventos.mdereferences/camadas-widget-angular.md. - Teste (
/fluig:test): a recompensa — domínio com Jasmine puro (rápido, sem TestBed); adapter comHttpTestingController; componente só com teste de interação.
Regras inegociáveis
- Componente/página nunca injeta
HttpClientnem chamaDatasetFactory— sempre via service. - Regra de negócio nunca importa
@angular/*,@po-ui/*, nem tocahAPI/DatasetFactory. - Evento de workflow/form delega para função nomeada — a lógica nunca mora inline no evento.
- Integração REST Protheus: URL/rota/parse em um único adapter por recurso.
- Toda regra pura nasce com spec Jasmine (o
/fluig:testcobra cobertura ≥ 70%). - try/catch + log nos adaptadores server-side (regra do plugin) — mas o catch não engole: loga e propaga/devolve erro estruturado.