@luanpdd/kit-mcp 1.34.0 → 1.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/bin/cli.js +2 -2
- package/bin/mcp.js +6 -6
- package/bin/ui.js +74 -74
- package/gates/ai-prompt-stability.md +120 -120
- package/gates/budget-description.md +68 -68
- package/gates/confidence.md +29 -29
- package/gates/dependency-check.md +33 -33
- package/gates/dept-cycle-prevention.md +179 -179
- package/gates/golden-signals-coverage.md +133 -133
- package/gates/legacy-refactor-safety.md +178 -178
- package/gates/multi-tenant-rls-coverage.md +102 -102
- package/gates/no-personal-uuid.md +72 -72
- package/gates/obs-agents-mcp-supabase.md +86 -86
- package/gates/obs-skills-frontmatter.md +76 -76
- package/gates/observability-coverage.md +151 -151
- package/gates/omm-no-regression.md +83 -83
- package/gates/postmortem-template-required.md +127 -127
- package/gates/prr-checklist-coverage.md +128 -128
- package/gates/regression.md +32 -32
- package/gates/release-pipeline-policy.md +132 -132
- package/gates/secrets-scan.md +33 -33
- package/gates/service-role-not-in-user-facing.md +113 -113
- package/gates/skill-must-include.md +71 -71
- package/gates/sync-idempotent.md +62 -62
- package/gates/verify-phase-goal.md +34 -34
- package/kit/agents/designer-ui.md +216 -216
- package/kit/agents/workflow-generator.md +537 -0
- package/kit/commands/adicionar-backlog.md +1 -1
- package/kit/commands/adicionar-fase.md +1 -1
- package/kit/commands/adicionar-tarefa.md +1 -1
- package/kit/commands/auditar-observabilidade.md +103 -103
- package/kit/commands/auditar-toil.md +129 -129
- package/kit/commands/caracterizar-prompt.md +195 -195
- package/kit/commands/criar-workflow.md +158 -0
- package/kit/commands/definir-perfil.md +1 -1
- package/kit/commands/definir-slo.md +108 -108
- package/kit/commands/fio.md +1 -1
- package/kit/commands/golden-signals.md +142 -142
- package/kit/commands/instrumentar-fase.md +200 -200
- package/kit/commands/investigar-producao.md +162 -162
- package/kit/commands/observabilidade.md +118 -118
- package/kit/commands/postmortem.md +179 -179
- package/kit/commands/prr.md +205 -205
- package/kit/commands/publicar-rapido.md +207 -207
- package/kit/commands/risk-budget.md +220 -220
- package/kit/commands/sre.md +230 -230
- package/kit/file-manifest.json +5 -2
- package/kit/framework/references/output-style.md +22 -22
- package/kit/hooks/post-apply-migration.js +199 -199
- package/kit/hooks/sidecar-tool-publisher.js +210 -210
- package/kit/skills/_shared-dados-distribuidos/glossary.md +224 -224
- package/kit/skills/_shared-legacy/glossary.md +389 -389
- package/kit/skills/_shared-multi-tenant/glossary.md +186 -186
- package/kit/skills/_shared-observability/glossary.md +396 -396
- package/kit/skills/_shared-sre/glossary.md +712 -712
- package/kit/skills/_shared-supabase/glossary.md +234 -234
- package/kit/skills/blameless-postmortems/SKILL.md +340 -340
- package/kit/skills/burn-rate-alerting/SKILL.md +258 -258
- package/kit/skills/cascading-failures/SKILL.md +311 -311
- package/kit/skills/core-analysis-loop/SKILL.md +352 -352
- package/kit/skills/distributed-tracing/SKILL.md +362 -362
- package/kit/skills/dynamic-workflow-authoring/SKILL.md +327 -0
- package/kit/skills/eliminating-toil/SKILL.md +243 -243
- package/kit/skills/event-based-slos/SKILL.md +296 -296
- package/kit/skills/four-golden-signals/SKILL.md +314 -314
- package/kit/skills/hermetic-builds/SKILL.md +323 -323
- package/kit/skills/legacy-monster-methods/SKILL.md +444 -444
- package/kit/skills/llm-as-dependency/SKILL.md +436 -436
- package/kit/skills/load-shedding-graceful-degradation/SKILL.md +396 -396
- package/kit/skills/observability-driven-development/SKILL.md +315 -315
- package/kit/skills/observability-maturity-model/SKILL.md +222 -222
- package/kit/skills/opentelemetry-standard/SKILL.md +351 -351
- package/kit/skills/production-readiness-review/SKILL.md +305 -305
- package/kit/skills/release-engineering/SKILL.md +367 -367
- package/kit/skills/retry-strategies/SKILL.md +372 -372
- package/kit/skills/sre-risk-management/SKILL.md +221 -221
- package/kit/skills/structured-events/SKILL.md +265 -265
- package/kit/skills/supabase-cron-queues/SKILL.md +275 -275
- package/kit/skills/supabase-database-functions/SKILL.md +332 -332
- package/kit/skills/supabase-declarative-schema/SKILL.md +183 -183
- package/kit/skills/supabase-pgvector-rag/SKILL.md +253 -253
- package/kit/skills/supabase-postgres-style/SKILL.md +138 -138
- package/kit/skills/supabase-storage/SKILL.md +234 -234
- package/kit/skills/telemetry-pipelines/SKILL.md +259 -259
- package/kit/skills/telemetry-sampling/SKILL.md +256 -256
- package/kit/skills/ui-anti-padroes-ia/SKILL.md +261 -261
- package/kit/skills/ui-contexto-produto/SKILL.md +248 -248
- package/kit/skills/ui-cor-estrategia/SKILL.md +213 -213
- package/kit/skills/ui-critica-auditoria/SKILL.md +260 -260
- package/kit/skills/ui-motion-funcional/SKILL.md +264 -264
- package/kit/skills/ui-ritmo-espacial/SKILL.md +259 -259
- package/kit/skills/ui-tipografia/SKILL.md +211 -211
- package/package.json +1 -1
- package/src/cli/index.js +1114 -1114
- package/src/cli/render.js +194 -194
- package/src/cli/upgrade-check.js +135 -135
- package/src/core/error-redaction.js +76 -76
- package/src/core/failures.js +153 -153
- package/src/core/gate-runner.js +205 -205
- package/src/core/gates.js +82 -82
- package/src/core/logger.js +170 -170
- package/src/core/manifest-verify.js +174 -174
- package/src/core/metrics.js +268 -268
- package/src/core/notify.js +60 -60
- package/src/core/path-safety.js +141 -141
- package/src/core/replays.js +120 -120
- package/src/core/ui.js +185 -185
- package/src/mcp-server/install.js +149 -149
- package/src/mcp-server/roots.js +124 -124
- package/src/ui/auto-spawn.js +113 -113
- package/src/ui/browser.js +78 -78
- package/src/ui/client.js +130 -130
- package/src/ui/events.js +65 -65
- package/src/ui/lockfile.js +191 -191
- package/src/ui/port.js +67 -67
- package/src/ui/server.js +547 -547
- package/src/ui/wrapper.js +129 -129
|
@@ -1,389 +1,389 @@
|
|
|
1
|
-
# Glossário Legacy Code — Termos, Técnicas e Patterns Canônicos
|
|
2
|
-
|
|
3
|
-
> Arquivo de referência compartilhado pelas skills `legacy-*` e `pre-refactor-characterization`. **NÃO é skill** — não tem `description:` triggerável; não aparece em `listKit`. Cross-referenciado pelas skills via Markdown link relativo.
|
|
4
|
-
|
|
5
|
-
> **Material-fonte:** *Working Effectively with Legacy Code* — Michael C. Feathers (Prentice Hall / Robert C. Martin Series, 2004). ISBN 978-0-13-117705-5.
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## (a) Termos PT-BR ↔ EN
|
|
10
|
-
|
|
11
|
-
### Definições fundacionais
|
|
12
|
-
|
|
13
|
-
> Vocabulário do prefácio + cap 1 (Changing Software). A definição de Feathers é deliberadamente operacional, não emocional — "legacy code" não significa "código antigo" ou "código feio", significa **código sem testes**. Essa redefinição muda completamente a estratégia: o problema é falta de cobertura comportamental, não estética.
|
|
14
|
-
|
|
15
|
-
| EN | PT-BR / Significado |
|
|
16
|
-
|---|---|
|
|
17
|
-
| **legacy code** | Código legado — para Feathers: **código sem testes**, independente de idade ou qualidade. Sem testes, qualquer mudança é "edit and pray" — você modifica e reza. |
|
|
18
|
-
| **edit and pray** | Editar e rezar — o modo default em legacy code. Você muda, lê o diff, deploya, espera. Confiança vem de inspeção visual + sorte. |
|
|
19
|
-
| **cover and modify** | Cobrir e modificar — o modo desejado. Primeiro adicione cobertura (tests), depois modifique. Confiança vem do safety net. |
|
|
20
|
-
| **change point** | Ponto de mudança — local específico onde a alteração será feita. Tipicamente uma linha, método ou bloco. |
|
|
21
|
-
| **inflection point** | Ponto de inflexão — junção estreita por onde os efeitos da mudança fluem. Testar aqui cobre múltiplos change points downstream. |
|
|
22
|
-
| **pinch point** | Funil estreito (sinônimo de inflection point usado em cap 11) — interface natural na qual concentrar testes. |
|
|
23
|
-
| **safety net** | Rede de segurança — suite de testes que detecta regressão imediatamente após edição. Cap 1 é todo sobre construir isso. |
|
|
24
|
-
| **legacy code dilemma** | Dilema do código legado — para mudar com segurança preciso testar; para testar preciso refatorar; para refatorar preciso testar. Quebrado por **dependency-breaking techniques** (cap 25). |
|
|
25
|
-
|
|
26
|
-
### Seams e Test Harness
|
|
27
|
-
|
|
28
|
-
> Vocabulário do cap 4 (The Seam Model). Conceito central. Seam = lugar onde você pode alterar comportamento **sem editar naquele lugar**. Sem seams, o código está "fundido" — toda mudança requer modificação direta, sem possibilidade de substituição em teste.
|
|
29
|
-
|
|
30
|
-
| EN | PT-BR / Significado |
|
|
31
|
-
|---|---|
|
|
32
|
-
| **seam** | Costura — local onde se pode alterar comportamento sem editar ali. Tipicamente onde existe ponto de extensibilidade que pode ser exercitado por testes. |
|
|
33
|
-
| **enabling point** | Ponto habilitador — mecanismo concreto que ativa a substituição naquela costura (subclasse, link table, build flag, parâmetro). |
|
|
34
|
-
| **preprocessing seam** | Costura de pré-processamento — substituição via macros/preprocessor (C/C++). Raríssima em runtimes modernos. |
|
|
35
|
-
| **link seam** | Costura de link — substituição via linker (DLL/object/jar) ou loader (require/import shim). Útil em código sem orientação a objetos. |
|
|
36
|
-
| **object seam** | Costura de objeto — substituição via polimorfismo (interface, classe abstrata, duck typing). A mais comum e poderosa em OO. |
|
|
37
|
-
| **test harness** | Arnês de teste — infraestrutura mínima para fazer um pedaço de código rodar isolado em testes. Cap 9-10 inteiro é sobre construir isso. |
|
|
38
|
-
| **dependency** | Dependência — qualquer entidade externa que o código sob teste invoca. Bloqueia testes quando incontrolável (DB real, rede, clock, FS). |
|
|
39
|
-
| **collaborator** | Colaborador — instância concreta de uma dependência. Ex.: `EmailSender` vs concept "envio de email". |
|
|
40
|
-
| **fake** | Fake — implementação substituta de uma dependência que satisfaz a interface mas não faz o trabalho real (ex: `FakeEmailSender` que só salva em lista). |
|
|
41
|
-
| **sensing** | Sensoriamento — observar via testes que algo aconteceu (assertion sobre `fake.sentEmails.length`). |
|
|
42
|
-
| **separation** | Separação — quebrar a dependência para que o código rode sem o colaborador real. Pré-requisito de sensing. |
|
|
43
|
-
| **break dependencies** | Quebrar dependências — aplicar uma das ~24 técnicas do cap 25 para tornar testável o que não era. |
|
|
44
|
-
|
|
45
|
-
### Characterization Tests
|
|
46
|
-
|
|
47
|
-
> Vocabulário do cap 13 (Characterization Tests). **A skill foundacional**. Characterization test não verifica se o código está certo — verifica **o que o código atualmente faz**. É um snapshot comportamental que vira oracle imutável durante o refactor.
|
|
48
|
-
|
|
49
|
-
| EN | PT-BR / Significado |
|
|
50
|
-
|---|---|
|
|
51
|
-
| **characterization test** | Teste de caracterização — teste que captura o comportamento **atual** do código (não o desejado). Não pergunta "está certo?" — pergunta "o que faz?". |
|
|
52
|
-
| **golden master** | Mestre dourado — output capturado de uma execução real, salvo em arquivo, que vira oracle. Subsequentes execuções comparam contra ele (snapshot test). |
|
|
53
|
-
| **golden snapshot** | Snapshot dourado — sinônimo de golden master, terminologia mais comum em frameworks modernos (Jest, Vitest, Pytest). |
|
|
54
|
-
| **expected behavior trap** | Armadilha do "comportamento esperado" — escrever testes do que o código **deveria** fazer em vez do que **faz**. Resultado: teste falha imediatamente porque o bug atual é o estado atual. Sempre comece pelo atual. |
|
|
55
|
-
| **bug preservation** | Preservação de bug — characterization tests preservam bugs existentes. Refactor não muda comportamento, então o bug deve continuar reproduzível. Bug fix é outra mudança, separada. |
|
|
56
|
-
| **observation point** | Ponto de observação — saída capturada (return value, side effect, log, DB write). Cada ponto vira uma asserção. |
|
|
57
|
-
| **input enumeration** | Enumeração de entradas — cobrir caminhos via grupos de equivalência: input nulo, vazio, válido típico, válido extremo, inválido recoverable, inválido fatal. |
|
|
58
|
-
| **behavioral coverage** | Cobertura comportamental — não % de linhas executadas, mas % de **branches** + observation points. Métrica para liberar refactor é cobertura comportamental, não code coverage. |
|
|
59
|
-
| **edit-then-characterize** | Editar-então-caracterizar — anti-pattern. Você muda, depois escreve teste do "novo" comportamento. Não há baseline para detectar quebra. |
|
|
60
|
-
|
|
61
|
-
### Sprout / Wrap Techniques
|
|
62
|
-
|
|
63
|
-
> Vocabulário do cap 6 (I Don't Have Much Time and I Have to Change It). Quando você não tem tempo para colocar legado em test harness, mas precisa adicionar comportamento novo. Estratégia: adicionar código novo **isolado** e testado, conectado ao legado por chamada mínima.
|
|
64
|
-
|
|
65
|
-
| EN | PT-BR / Significado |
|
|
66
|
-
|---|---|
|
|
67
|
-
| **sprout method** | Método broto — extrair a nova lógica para método novo (tipicamente `static` ou injetável), testar isolado, chamar do método legado em 1 linha. |
|
|
68
|
-
| **sprout class** | Classe broto — quando o sprout method cresce, externalize para classe nova com test harness próprio. |
|
|
69
|
-
| **wrap method** | Método invólucro — renomeie o método legado (`foo` → `fooLegacy`), crie `foo` novo que chama `fooLegacy` + nova lógica. Novo `foo` é testável. |
|
|
70
|
-
| **wrap class** | Classe invólucro — análogo ao wrap method em escala de classe. Decorator pattern aplicado pragmaticamente. |
|
|
71
|
-
| **boy scout rule (sprout edition)** | Regra do escoteiro (versão sprout) — deixe o código mais limpo do que encontrou ao **adicionar** novo, mesmo sem refatorar o velho. Sprout/wrap concretiza isso. |
|
|
72
|
-
|
|
73
|
-
### Effect Analysis
|
|
74
|
-
|
|
75
|
-
> Vocabulário do cap 11 (I Need to Make a Change. What Methods Should I Test?) e cap 12 (I Need to Make Many Changes in One Area). Sem testes, qual é o subset mínimo de coisas a testar para sentir-se seguro? Resposta: rastreie efeitos do change point para fora, encontre inflection points, teste lá.
|
|
76
|
-
|
|
77
|
-
| EN | PT-BR / Significado |
|
|
78
|
-
|---|---|
|
|
79
|
-
| **effect sketch** | Esboço de efeitos — diagrama (papel mesmo) com setas do change point para tudo que muda. Variáveis afetadas, retornos, side effects, callbacks. |
|
|
80
|
-
| **effect propagation** | Propagação de efeito — como um change ripple através do código. Cap 11 lista 4 vetores: return value, parâmetros mutados, globals, side effects via colaborador. |
|
|
81
|
-
| **interception point** | Ponto de interceptação — local onde inserir teste para observar efeitos. Idealmente coincide com inflection point. |
|
|
82
|
-
| **effect-narrowing** | Estreitamento de efeito — refatorar para reduzir o número de pontos afetados (encapsular variáveis, eliminar globals). Pré-trabalho para tornar effect sketch menor. |
|
|
83
|
-
| **shotgun surgery** | Cirurgia espalhada — anti-pattern (cap 21): mesma mudança espalhada em N lugares; cada incidência é um change point separado. Effect sketch detecta. |
|
|
84
|
-
|
|
85
|
-
### Monster Methods
|
|
86
|
-
|
|
87
|
-
> Vocabulário do cap 22 (I Need to Change a Monster Method and I Can't Write Tests for It). Métodos absurdamente longos (> 200 linhas) onde você não consegue nem entender o que faz, muito menos testar. Estratégia: scratch refactoring + single-goal editing + extrair pedacinhos sem mudar comportamento.
|
|
88
|
-
|
|
89
|
-
| EN | PT-BR / Significado |
|
|
90
|
-
|---|---|
|
|
91
|
-
| **monster method** | Método monstro — método com várias páginas de código, múltiplos níveis de aninhamento, múltiplas responsabilidades. Heurística: > 100 linhas ou > 5 níveis de indent. |
|
|
92
|
-
| **bulleted method** | Método com bullets — variante: linhas longas mas planas (sem nesting). Mais fácil de domar. |
|
|
93
|
-
| **snarled method** | Método emaranhado — variante: nesting profundo, condicionais aninhadas, control flow espaguete. Mais difícil. |
|
|
94
|
-
| **scratch refactoring** | Refactor de rascunho — quebra estética sem commitar. Use uma branch lixo, refatore para entender, descarte. Conhecimento adquirido vai para a refatoração real. |
|
|
95
|
-
| **single-goal editing** | Edição com objetivo único — mudar UMA coisa por vez. Renomear OU extrair OU mover, nunca os 3 juntos. Cada mudança é um diff legível. |
|
|
96
|
-
| **safe extraction** | Extração segura — extrair método sem mover lógica entre escopos. Apenas levantar bloco contíguo + capturar variáveis usadas como parâmetros. |
|
|
97
|
-
| **method blob** | Blob de método — sinônimo informal de monster method. |
|
|
98
|
-
|
|
99
|
-
### Dependency-Breaking Techniques
|
|
100
|
-
|
|
101
|
-
> Vocabulário do cap 25 (Dependency-Breaking Techniques) — o catálogo principal. ~24 técnicas para tornar testável o que não era. Cada técnica tem trade-offs diferentes (segurança, custo, mecanização).
|
|
102
|
-
|
|
103
|
-
| EN | PT-BR / Significado |
|
|
104
|
-
|---|---|
|
|
105
|
-
| **subclass and override method** | Subclassificar e sobrescrever método — criar subclasse de teste que substitui método problemático. Funciona em qualquer linguagem com herança virtual. |
|
|
106
|
-
| **extract interface** | Extrair interface — criar interface a partir da classe concreta, fazer cliente depender da interface, fornecer fake implementation em teste. |
|
|
107
|
-
| **adapt parameter** | Adaptar parâmetro — quando parâmetro tem tipo difícil de criar (ex: `HttpServletRequest`), envolver em interface mais simples e fazer cliente depender dela. |
|
|
108
|
-
| **introduce static setter** | Introduzir setter estático — adicionar setter para singleton/global; teste injeta fake; teardown restaura. **Risk: thread safety** — só em ambientes single-threaded de teste. |
|
|
109
|
-
| **encapsulate global references** | Encapsular referências globais — substituir acesso direto a variáveis globais por método de instância da classe. Permite override em teste. |
|
|
110
|
-
| **expose static method** | Expor método estático — promover método de instância a estático para testar sem instanciar a classe inteira (quando construtor é caro). |
|
|
111
|
-
| **break out method object** | Quebrar para method object — extrair método grande para classe com `run()`. Variáveis locais viram fields, fácil de testar. |
|
|
112
|
-
| **parameterize constructor** | Parametrizar construtor — passar dependência via construtor (DI manual) em vez de criar dentro. Default constructor mantém retrocompatibilidade. |
|
|
113
|
-
| **parameterize method** | Parametrizar método — passar dependência como argumento da chamada. Útil quando dependency só é usada num método específico. |
|
|
114
|
-
| **pull up feature** | Subir feature — mover método/field para superclasse para que subclasse de teste possa override. |
|
|
115
|
-
| **push down dependency** | Empurrar dependência — mover dependência problemática para subclasse, fazer base abstrata sem ela; teste usa subclasse de teste sem dependência real. |
|
|
116
|
-
| **replace function with function pointer** | Substituir função por ponteiro de função — em C, substituir chamada estática por ponteiro que teste pode reapontar. |
|
|
117
|
-
| **introduce instance delegator** | Introduzir delegador de instância — método estático vira fino wrapper que chama método de instância injetada. Permite mock. |
|
|
118
|
-
| **link substitution** | Substituição de link — providenciar `.so`/`.dll`/`.jar` alternativo em test classpath/library path. |
|
|
119
|
-
| **definition completion** | Completar definição (C/C++) — fornecer `.cpp` alternativo no link de teste para sobrescrever função declarada em `.h`. |
|
|
120
|
-
|
|
121
|
-
---
|
|
122
|
-
|
|
123
|
-
## (b) Patterns canônicos
|
|
124
|
-
|
|
125
|
-
### Pattern: Algoritmo de mudança em legacy code (cap 1)
|
|
126
|
-
|
|
127
|
-
```text
|
|
128
|
-
1. Identify change points (onde mudar)
|
|
129
|
-
2. Find test points (onde testar — idealmente nas inflection points)
|
|
130
|
-
3. Break dependencies (cap 25 — aplicar técnica adequada)
|
|
131
|
-
4. Write characterization tests (cap 13 — congelar comportamento atual)
|
|
132
|
-
5. Make changes and refactor (cover and modify, não edit and pray)
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
**Insight central:** os passos 1-4 são **investimento prévio à mudança**. Quem pula direto ao passo 5 está em "edit and pray" — pode ter sorte 9 vezes em 10 mas a 10ª vez é incident SEV1.
|
|
136
|
-
|
|
137
|
-
### Pattern: identificar legacy code via critérios
|
|
138
|
-
|
|
139
|
-
```text
|
|
140
|
-
Um arquivo/módulo é "legacy" no sentido Feathers se:
|
|
141
|
-
|
|
142
|
-
1. Cobertura de testes < 60%? → SIM → legacy
|
|
143
|
-
2. Existem branches sem teste algum? → SIM → legacy
|
|
144
|
-
3. Mudanças recentes (último mês) não tiveram teste novo correspondente? → SIM → legacy
|
|
145
|
-
4. Faz parte de contrato externo (webhook, API pública, integração)? → SIM → legacy MESMO COM testes (porque consumer breakage é pior)
|
|
146
|
-
5. Tem mais de 500 linhas em arquivo único? → SIM → legacy candidate (pelo menos suspeito)
|
|
147
|
-
6. Tem métodos > 100 linhas? → SIM → monster methods, candidato a cap 22
|
|
148
|
-
|
|
149
|
-
Heurística agregada: se 2+ critérios = legacy → exigir characterization tests antes de qualquer refactor.
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
### Pattern: decision tree para escolher técnica de quebra de dependência
|
|
153
|
-
|
|
154
|
-
```text
|
|
155
|
-
Posso modificar o código? (acesso write?)
|
|
156
|
-
├─ Não → preprocessing seam (C/C++) ou link seam (qualquer linguagem)
|
|
157
|
-
└─ Sim →
|
|
158
|
-
├─ Linguagem tem herança/polimorfismo? (Java, C#, Python, Ruby, TS...)
|
|
159
|
-
│ ├─ Sim → object seam (preferred)
|
|
160
|
-
│ │ ├─ Dependência é classe? → extract interface OU subclass and override
|
|
161
|
-
│ │ ├─ Dependência é singleton/global? → encapsulate global references OU introduce static setter
|
|
162
|
-
│ │ ├─ Dependência é tipo de framework? (HttpServletRequest, Context) → adapt parameter
|
|
163
|
-
│ │ └─ Dependência é construído internamente? → parameterize constructor / parameterize method
|
|
164
|
-
│ └─ Não (C, COBOL, código procedural) → link seam OU function pointer substitution
|
|
165
|
-
└─ Construtor da classe é caro? → expose static method (testar sem instanciar)
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
### Pattern: Sprout decision tree (cap 6)
|
|
169
|
-
|
|
170
|
-
```text
|
|
171
|
-
Tenho que adicionar comportamento a método não testado.
|
|
172
|
-
|
|
173
|
-
Tenho tempo para colocar o método inteiro sob test harness primeiro?
|
|
174
|
-
├─ Sim → técnicas do cap 25 (preferencial)
|
|
175
|
-
└─ Não →
|
|
176
|
-
├─ Comportamento novo é coeso e separável? → SPROUT METHOD
|
|
177
|
-
│ 1. Escrever método novo (static ou de classe nova) — testável
|
|
178
|
-
│ 2. Chamar do método legado em 1 linha
|
|
179
|
-
│ 3. Test do sprout via test harness próprio
|
|
180
|
-
│ 4. Método legado permanece untested mas o NOVO comportamento está coberto
|
|
181
|
-
├─ Comportamento novo é grande (>30 linhas)? → SPROUT CLASS
|
|
182
|
-
│ 1. Criar classe nova encapsulando o novo comportamento
|
|
183
|
-
│ 2. Construir + chamar a classe do método legado
|
|
184
|
-
│ 3. Test class isoladamente
|
|
185
|
-
└─ Preciso modificar pré ou pós-condição do método legado? → WRAP METHOD
|
|
186
|
-
1. Renomear `foo` → `fooLegacy` (apenas mecânico)
|
|
187
|
-
2. Criar novo `foo` que chama `fooLegacy` + adiciona comportamento
|
|
188
|
-
3. Testes do `foo` cobrem composição; `fooLegacy` ainda untested mas chamável
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
### Pattern: characterization tests workflow (cap 13)
|
|
192
|
-
|
|
193
|
-
```text
|
|
194
|
-
1. Escolher input typical → rodar código → capturar output
|
|
195
|
-
2. Escrever teste assertando output capturado (mesmo se output for um bug)
|
|
196
|
-
3. Repetir para 5-10 inputs cobrindo grupos de equivalência:
|
|
197
|
-
- null/vazio
|
|
198
|
-
- válido típico
|
|
199
|
-
- válido extremo (boundaries)
|
|
200
|
-
- inválido recoverable
|
|
201
|
-
- inválido fatal
|
|
202
|
-
4. Rodar todos verde → BASELINE estabelecido
|
|
203
|
-
5. AGORA refactor pode começar — qualquer test que vire vermelho = regressão real
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
**Anti-pattern:** começar a "consertar" o teste para o output "correto". Isso destrói o oracle. Bug → preserve, fix em commit separado depois do refactor.
|
|
207
|
-
|
|
208
|
-
### Pattern: 6 níveis de "está testável?" (cap 9-10)
|
|
209
|
-
|
|
210
|
-
| Nível | Sintoma | Solução |
|
|
211
|
-
|---|---|---|
|
|
212
|
-
| **L0** | Não consigo construir a classe (construtor irritado, faz I/O, throws) | Cap 9 técnicas — fake constructor parameters, expose static method |
|
|
213
|
-
| **L1** | Classe constrói mas método não roda isolado (depende de globals) | Encapsulate global references |
|
|
214
|
-
| **L2** | Método roda mas dependências reais (DB, rede, clock) executam | Inject collaborator OR subclass and override |
|
|
215
|
-
| **L3** | Dependências stubadas mas effects spread (DB grava, email envia) | Sense via fake (verify-no-side-effect) |
|
|
216
|
-
| **L4** | Roda isolado, mas saída não-determinística (random, datetime.now) | Inject clock/random como dependência |
|
|
217
|
-
| **L5** | Roda isolado e determinístico mas eu não entendo o que testa | Characterization tests para descobrir |
|
|
218
|
-
|
|
219
|
-
Meta é L5+. Antes de refatorar, código deve estar em L4 ou melhor.
|
|
220
|
-
|
|
221
|
-
---
|
|
222
|
-
|
|
223
|
-
## (c) Anti-patterns canônicos
|
|
224
|
-
|
|
225
|
-
### ANTI: refactor sem characterization tests
|
|
226
|
-
|
|
227
|
-
```text
|
|
228
|
-
ANTI: "vou refatorar esse método de 200 linhas, depois adiciono testes do
|
|
229
|
-
novo design".
|
|
230
|
-
|
|
231
|
-
PROBLEMA: você não sabe o que está preservando. O método tem branches que
|
|
232
|
-
você não sabe que existem. Bugs antigos que clientes dependem
|
|
233
|
-
(Hyrum's Law) somem silenciosamente. Resultado típico: incident
|
|
234
|
-
em prod 2 semanas depois quando edge case dispara.
|
|
235
|
-
|
|
236
|
-
CERTO: characterize first (cap 13), refactor second. Pelo menos 5-10
|
|
237
|
-
inputs cobrindo grupos de equivalência ANTES de mover qualquer
|
|
238
|
-
linha. Se o método é de 200 linhas, esse trabalho leva 1-2 dias.
|
|
239
|
-
Aceite o custo — alternativa é o incident.
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
### ANTI: edit and pray (cap 1)
|
|
243
|
-
|
|
244
|
-
```text
|
|
245
|
-
ANTI: "vou modificar essa linha, rodar smoke test, dar push e ver no
|
|
246
|
-
monitoring".
|
|
247
|
-
|
|
248
|
-
PROBLEMA: smoke test cobre golden path. Branches raras (1% do tráfego)
|
|
249
|
-
escapam silenciosamente. Bugs em borda manifestam horas/dias
|
|
250
|
-
depois. Forensics fica difícil porque change set tem N edits
|
|
251
|
-
no mesmo PR.
|
|
252
|
-
|
|
253
|
-
CERTO: cover and modify. Antes de modificar, encontre o seam e adicione
|
|
254
|
-
teste que exercita a branch específica. Se não há seam, primeiro
|
|
255
|
-
adicione um (cap 25). Investimento de 1-4h vs incident de 4-40h.
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
### ANTI: fix bug ANTES do characterization
|
|
259
|
-
|
|
260
|
-
```text
|
|
261
|
-
ANTI: "ah, esse método tem um bug óbvio na linha 42, vou consertar
|
|
262
|
-
enquanto refatoro".
|
|
263
|
-
|
|
264
|
-
PROBLEMA: characterization test capturou o bug como comportamento
|
|
265
|
-
esperado. Você consertou → teste fica vermelho → você
|
|
266
|
-
"atualiza o teste" → oracle morto → não há baseline mais.
|
|
267
|
-
|
|
268
|
-
CERTO: 2 commits separados. (1) characterize + refactor preservando
|
|
269
|
-
bug. (2) bug fix com teste novo do comportamento correto. Aplique
|
|
270
|
-
o fix DEPOIS, com seu próprio test antes (TDD agora possível
|
|
271
|
-
porque você tem test harness funcionando).
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
### ANTI: golden master sem revisão humana
|
|
275
|
-
|
|
276
|
-
```text
|
|
277
|
-
ANTI: rodar code → capturar output → commitar como `expected.txt` sem
|
|
278
|
-
ler. "É o que o código produz, deve estar certo".
|
|
279
|
-
|
|
280
|
-
PROBLEMA: output captura inclui bugs já existentes. Sem revisão, você
|
|
281
|
-
congela bugs como contrato. Se o output incluir PII, secret,
|
|
282
|
-
UUID local — você acabou de commitar dado sensível.
|
|
283
|
-
|
|
284
|
-
CERTO: ler o output capturado linha por linha antes de salvar. Marcar
|
|
285
|
-
expectativas conhecidas-buggy com comentário inline (`// BUG #123:
|
|
286
|
-
deveria ser X, é Y`). Redact PII/secret/UUID via post-processing
|
|
287
|
-
deterministic (hash, mask). Commit do golden é uma decisão, não
|
|
288
|
-
um copy-paste.
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
### ANTI: monster method "limpado" em 1 PR
|
|
292
|
-
|
|
293
|
-
```text
|
|
294
|
-
ANTI: PR com 800 linhas de diff: extract method × 12, rename × 5, move
|
|
295
|
-
logic × 3, fix off-by-one × 2 — tudo junto.
|
|
296
|
-
|
|
297
|
-
PROBLEMA: PR não-revisável. Reviewer não consegue separar refactor
|
|
298
|
-
(nullable) de fix (semântico). Se algo quebra, bisect aponta
|
|
299
|
-
para o PR inteiro. CI verde não significa nada — branch
|
|
300
|
-
coverage caiu silenciosa.
|
|
301
|
-
|
|
302
|
-
CERTO: 1 PR por single-goal edit (cap 22). Sequência típica:
|
|
303
|
-
PR1 — extract method (3 helpers, mecânico, comportamento idêntico)
|
|
304
|
-
PR2 — extract class (mover helpers para nova classe)
|
|
305
|
-
PR3 — invert dependency (constructor injection)
|
|
306
|
-
PR4 — fix bug X (com teste novo, semântico)
|
|
307
|
-
Cada PR ≤ 100 linhas. Cada um é revisável e revertível.
|
|
308
|
-
```
|
|
309
|
-
|
|
310
|
-
### ANTI: substituir testes "falhos" sem investigar
|
|
311
|
-
|
|
312
|
-
```text
|
|
313
|
-
ANTI: characterization test virou vermelho após refactor. "Provavelmente
|
|
314
|
-
o teste estava errado, vou atualizar o expected".
|
|
315
|
-
|
|
316
|
-
PROBLEMA: você acabou de pintar "Vermelho → verde" em cima de regressão
|
|
317
|
-
real. Comportamento mudou e você passou por cima da rede de
|
|
318
|
-
segurança. Próximo bug em prod vem por essa porta.
|
|
319
|
-
|
|
320
|
-
CERTO: vermelho de characterization test = regressão até prova ao
|
|
321
|
-
contrário. Investigue: o que no refactor mudou comportamento?
|
|
322
|
-
Reverte aquele pedaço, refatore de outra forma. Só atualize o
|
|
323
|
-
golden APÓS confirmar que o novo comportamento É o desejado e
|
|
324
|
-
documentar no commit (`// behavior change: rounds half-up; was
|
|
325
|
-
half-even`).
|
|
326
|
-
```
|
|
327
|
-
|
|
328
|
-
### ANTI: confiar em coverage % como proxy de safety
|
|
329
|
-
|
|
330
|
-
```text
|
|
331
|
-
ANTI: "linha de coverage está em 85%, posso refatorar tranquilo".
|
|
332
|
-
|
|
333
|
-
PROBLEMA: coverage % = "linha foi executada", não "comportamento foi
|
|
334
|
-
observado". Teste pode entrar na linha sem assertar. 85%
|
|
335
|
-
line coverage com 10% behavioral coverage é frágil mesmo.
|
|
336
|
-
|
|
337
|
-
CERTO: behavioral coverage = % de branches × observation points
|
|
338
|
-
cobertos por characterization tests. Pelo menos 70-80% antes de
|
|
339
|
-
refactor pesado. Use mutation testing (stryker, mutmut, pitest)
|
|
340
|
-
para confirmar — survived mutants = pontos cegos não cobertos.
|
|
341
|
-
```
|
|
342
|
-
|
|
343
|
-
---
|
|
344
|
-
|
|
345
|
-
## (d) Mapa de capítulos do livro
|
|
346
|
-
|
|
347
|
-
> Capa-índice para localizar qual skill consultar dado um sintoma específico. Skills cobrem capítulos do livro Feathers.
|
|
348
|
-
|
|
349
|
-
| Capítulo | Tema | Skill no kit |
|
|
350
|
-
|---|---|---|
|
|
351
|
-
| Cap 1 | Changing Software (edit and pray vs cover and modify) | `legacy-characterization-tests` (intro) |
|
|
352
|
-
| Cap 2 | Working with Feedback | `legacy-characterization-tests` (rationale) |
|
|
353
|
-
| Cap 3 | Sensing and Separation | `legacy-seams-and-test-harness` |
|
|
354
|
-
| Cap 4 | The Seam Model | `legacy-seams-and-test-harness` (foundation) |
|
|
355
|
-
| Cap 5 | Tools | (tooling — não é skill, mencionado em refs) |
|
|
356
|
-
| Cap 6 | I Don't Have Much Time and I Have to Change It | `legacy-sprout-wrap-techniques` |
|
|
357
|
-
| Cap 7-8 | It Takes Forever / How Do I Add a Feature | (gerais — disseminados em skills) |
|
|
358
|
-
| Cap 9-10 | I Can't Get This Class/Method into a Test Harness | `legacy-seams-and-test-harness` |
|
|
359
|
-
| Cap 11 | What Methods Should I Test? | `legacy-effect-analysis` |
|
|
360
|
-
| Cap 12 | Many Changes in One Area | `legacy-effect-analysis` |
|
|
361
|
-
| Cap 13 | What Tests to Write — **Characterization Tests** | `legacy-characterization-tests` ⭐ |
|
|
362
|
-
| Cap 14-15 | Libraries / API Calls | (caso especial — refs em sprout-wrap) |
|
|
363
|
-
| Cap 16 | I Don't Understand the Code | `legacy-effect-analysis` (sketches) |
|
|
364
|
-
| Cap 17 | Application Has No Structure | (refactor de larga escala — fora de scope) |
|
|
365
|
-
| Cap 18-21 | Test code in the way / Procedural / Big classes / Shotgun | (referências) |
|
|
366
|
-
| Cap 22 | Monster Method | `legacy-monster-methods` |
|
|
367
|
-
| Cap 23 | How Do I Know I'm Not Breaking Anything | `legacy-characterization-tests` |
|
|
368
|
-
| Cap 24 | Overwhelmed | (cultural — refs em commands) |
|
|
369
|
-
| Cap 25 | **Dependency-Breaking Techniques** (catálogo) | `legacy-seams-and-test-harness` |
|
|
370
|
-
|
|
371
|
-
---
|
|
372
|
-
|
|
373
|
-
## (e) Cross-references
|
|
374
|
-
|
|
375
|
-
- [`legacy-characterization-tests`](../legacy-characterization-tests/SKILL.md) — cap 13 + 23, foundational
|
|
376
|
-
- [`legacy-seams-and-test-harness`](../legacy-seams-and-test-harness/SKILL.md) — cap 3-4 + 9-10 + 25
|
|
377
|
-
- [`legacy-sprout-wrap-techniques`](../legacy-sprout-wrap-techniques/SKILL.md) — cap 6
|
|
378
|
-
- [`legacy-effect-analysis`](../legacy-effect-analysis/SKILL.md) — cap 11-12 + 16
|
|
379
|
-
- [`legacy-monster-methods`](../legacy-monster-methods/SKILL.md) — cap 22
|
|
380
|
-
- [`pre-refactor-characterization`](../pre-refactor-characterization/SKILL.md) — auto-trigger gate (workflow integration)
|
|
381
|
-
|
|
382
|
-
### Cross-suite
|
|
383
|
-
|
|
384
|
-
- [`event-based-slos`](../event-based-slos/SKILL.md) (v1.9) — characterization tests defendem SLO durante refactor; behavioral diff = budget burn
|
|
385
|
-
- [`production-readiness-review`](../production-readiness-review/SKILL.md) (v1.10) — PRR Axe 5 (Change Management) consume characterization status
|
|
386
|
-
- [`blameless-postmortems`](../blameless-postmortems/SKILL.md) (v1.10) — postmortems pós-refactor sem characterization viram lesson learned canônica
|
|
387
|
-
- [`observability-driven-development`](../observability-driven-development/SKILL.md) (v1.9) — characterization + ODD instrumentation = safety + visibility durante refactor
|
|
388
|
-
|
|
389
|
-
*Material-fonte: Working Effectively with Legacy Code — Feathers, 2004. ISBN 978-0-13-117705-5.*
|
|
1
|
+
# Glossário Legacy Code — Termos, Técnicas e Patterns Canônicos
|
|
2
|
+
|
|
3
|
+
> Arquivo de referência compartilhado pelas skills `legacy-*` e `pre-refactor-characterization`. **NÃO é skill** — não tem `description:` triggerável; não aparece em `listKit`. Cross-referenciado pelas skills via Markdown link relativo.
|
|
4
|
+
|
|
5
|
+
> **Material-fonte:** *Working Effectively with Legacy Code* — Michael C. Feathers (Prentice Hall / Robert C. Martin Series, 2004). ISBN 978-0-13-117705-5.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## (a) Termos PT-BR ↔ EN
|
|
10
|
+
|
|
11
|
+
### Definições fundacionais
|
|
12
|
+
|
|
13
|
+
> Vocabulário do prefácio + cap 1 (Changing Software). A definição de Feathers é deliberadamente operacional, não emocional — "legacy code" não significa "código antigo" ou "código feio", significa **código sem testes**. Essa redefinição muda completamente a estratégia: o problema é falta de cobertura comportamental, não estética.
|
|
14
|
+
|
|
15
|
+
| EN | PT-BR / Significado |
|
|
16
|
+
|---|---|
|
|
17
|
+
| **legacy code** | Código legado — para Feathers: **código sem testes**, independente de idade ou qualidade. Sem testes, qualquer mudança é "edit and pray" — você modifica e reza. |
|
|
18
|
+
| **edit and pray** | Editar e rezar — o modo default em legacy code. Você muda, lê o diff, deploya, espera. Confiança vem de inspeção visual + sorte. |
|
|
19
|
+
| **cover and modify** | Cobrir e modificar — o modo desejado. Primeiro adicione cobertura (tests), depois modifique. Confiança vem do safety net. |
|
|
20
|
+
| **change point** | Ponto de mudança — local específico onde a alteração será feita. Tipicamente uma linha, método ou bloco. |
|
|
21
|
+
| **inflection point** | Ponto de inflexão — junção estreita por onde os efeitos da mudança fluem. Testar aqui cobre múltiplos change points downstream. |
|
|
22
|
+
| **pinch point** | Funil estreito (sinônimo de inflection point usado em cap 11) — interface natural na qual concentrar testes. |
|
|
23
|
+
| **safety net** | Rede de segurança — suite de testes que detecta regressão imediatamente após edição. Cap 1 é todo sobre construir isso. |
|
|
24
|
+
| **legacy code dilemma** | Dilema do código legado — para mudar com segurança preciso testar; para testar preciso refatorar; para refatorar preciso testar. Quebrado por **dependency-breaking techniques** (cap 25). |
|
|
25
|
+
|
|
26
|
+
### Seams e Test Harness
|
|
27
|
+
|
|
28
|
+
> Vocabulário do cap 4 (The Seam Model). Conceito central. Seam = lugar onde você pode alterar comportamento **sem editar naquele lugar**. Sem seams, o código está "fundido" — toda mudança requer modificação direta, sem possibilidade de substituição em teste.
|
|
29
|
+
|
|
30
|
+
| EN | PT-BR / Significado |
|
|
31
|
+
|---|---|
|
|
32
|
+
| **seam** | Costura — local onde se pode alterar comportamento sem editar ali. Tipicamente onde existe ponto de extensibilidade que pode ser exercitado por testes. |
|
|
33
|
+
| **enabling point** | Ponto habilitador — mecanismo concreto que ativa a substituição naquela costura (subclasse, link table, build flag, parâmetro). |
|
|
34
|
+
| **preprocessing seam** | Costura de pré-processamento — substituição via macros/preprocessor (C/C++). Raríssima em runtimes modernos. |
|
|
35
|
+
| **link seam** | Costura de link — substituição via linker (DLL/object/jar) ou loader (require/import shim). Útil em código sem orientação a objetos. |
|
|
36
|
+
| **object seam** | Costura de objeto — substituição via polimorfismo (interface, classe abstrata, duck typing). A mais comum e poderosa em OO. |
|
|
37
|
+
| **test harness** | Arnês de teste — infraestrutura mínima para fazer um pedaço de código rodar isolado em testes. Cap 9-10 inteiro é sobre construir isso. |
|
|
38
|
+
| **dependency** | Dependência — qualquer entidade externa que o código sob teste invoca. Bloqueia testes quando incontrolável (DB real, rede, clock, FS). |
|
|
39
|
+
| **collaborator** | Colaborador — instância concreta de uma dependência. Ex.: `EmailSender` vs concept "envio de email". |
|
|
40
|
+
| **fake** | Fake — implementação substituta de uma dependência que satisfaz a interface mas não faz o trabalho real (ex: `FakeEmailSender` que só salva em lista). |
|
|
41
|
+
| **sensing** | Sensoriamento — observar via testes que algo aconteceu (assertion sobre `fake.sentEmails.length`). |
|
|
42
|
+
| **separation** | Separação — quebrar a dependência para que o código rode sem o colaborador real. Pré-requisito de sensing. |
|
|
43
|
+
| **break dependencies** | Quebrar dependências — aplicar uma das ~24 técnicas do cap 25 para tornar testável o que não era. |
|
|
44
|
+
|
|
45
|
+
### Characterization Tests
|
|
46
|
+
|
|
47
|
+
> Vocabulário do cap 13 (Characterization Tests). **A skill foundacional**. Characterization test não verifica se o código está certo — verifica **o que o código atualmente faz**. É um snapshot comportamental que vira oracle imutável durante o refactor.
|
|
48
|
+
|
|
49
|
+
| EN | PT-BR / Significado |
|
|
50
|
+
|---|---|
|
|
51
|
+
| **characterization test** | Teste de caracterização — teste que captura o comportamento **atual** do código (não o desejado). Não pergunta "está certo?" — pergunta "o que faz?". |
|
|
52
|
+
| **golden master** | Mestre dourado — output capturado de uma execução real, salvo em arquivo, que vira oracle. Subsequentes execuções comparam contra ele (snapshot test). |
|
|
53
|
+
| **golden snapshot** | Snapshot dourado — sinônimo de golden master, terminologia mais comum em frameworks modernos (Jest, Vitest, Pytest). |
|
|
54
|
+
| **expected behavior trap** | Armadilha do "comportamento esperado" — escrever testes do que o código **deveria** fazer em vez do que **faz**. Resultado: teste falha imediatamente porque o bug atual é o estado atual. Sempre comece pelo atual. |
|
|
55
|
+
| **bug preservation** | Preservação de bug — characterization tests preservam bugs existentes. Refactor não muda comportamento, então o bug deve continuar reproduzível. Bug fix é outra mudança, separada. |
|
|
56
|
+
| **observation point** | Ponto de observação — saída capturada (return value, side effect, log, DB write). Cada ponto vira uma asserção. |
|
|
57
|
+
| **input enumeration** | Enumeração de entradas — cobrir caminhos via grupos de equivalência: input nulo, vazio, válido típico, válido extremo, inválido recoverable, inválido fatal. |
|
|
58
|
+
| **behavioral coverage** | Cobertura comportamental — não % de linhas executadas, mas % de **branches** + observation points. Métrica para liberar refactor é cobertura comportamental, não code coverage. |
|
|
59
|
+
| **edit-then-characterize** | Editar-então-caracterizar — anti-pattern. Você muda, depois escreve teste do "novo" comportamento. Não há baseline para detectar quebra. |
|
|
60
|
+
|
|
61
|
+
### Sprout / Wrap Techniques
|
|
62
|
+
|
|
63
|
+
> Vocabulário do cap 6 (I Don't Have Much Time and I Have to Change It). Quando você não tem tempo para colocar legado em test harness, mas precisa adicionar comportamento novo. Estratégia: adicionar código novo **isolado** e testado, conectado ao legado por chamada mínima.
|
|
64
|
+
|
|
65
|
+
| EN | PT-BR / Significado |
|
|
66
|
+
|---|---|
|
|
67
|
+
| **sprout method** | Método broto — extrair a nova lógica para método novo (tipicamente `static` ou injetável), testar isolado, chamar do método legado em 1 linha. |
|
|
68
|
+
| **sprout class** | Classe broto — quando o sprout method cresce, externalize para classe nova com test harness próprio. |
|
|
69
|
+
| **wrap method** | Método invólucro — renomeie o método legado (`foo` → `fooLegacy`), crie `foo` novo que chama `fooLegacy` + nova lógica. Novo `foo` é testável. |
|
|
70
|
+
| **wrap class** | Classe invólucro — análogo ao wrap method em escala de classe. Decorator pattern aplicado pragmaticamente. |
|
|
71
|
+
| **boy scout rule (sprout edition)** | Regra do escoteiro (versão sprout) — deixe o código mais limpo do que encontrou ao **adicionar** novo, mesmo sem refatorar o velho. Sprout/wrap concretiza isso. |
|
|
72
|
+
|
|
73
|
+
### Effect Analysis
|
|
74
|
+
|
|
75
|
+
> Vocabulário do cap 11 (I Need to Make a Change. What Methods Should I Test?) e cap 12 (I Need to Make Many Changes in One Area). Sem testes, qual é o subset mínimo de coisas a testar para sentir-se seguro? Resposta: rastreie efeitos do change point para fora, encontre inflection points, teste lá.
|
|
76
|
+
|
|
77
|
+
| EN | PT-BR / Significado |
|
|
78
|
+
|---|---|
|
|
79
|
+
| **effect sketch** | Esboço de efeitos — diagrama (papel mesmo) com setas do change point para tudo que muda. Variáveis afetadas, retornos, side effects, callbacks. |
|
|
80
|
+
| **effect propagation** | Propagação de efeito — como um change ripple através do código. Cap 11 lista 4 vetores: return value, parâmetros mutados, globals, side effects via colaborador. |
|
|
81
|
+
| **interception point** | Ponto de interceptação — local onde inserir teste para observar efeitos. Idealmente coincide com inflection point. |
|
|
82
|
+
| **effect-narrowing** | Estreitamento de efeito — refatorar para reduzir o número de pontos afetados (encapsular variáveis, eliminar globals). Pré-trabalho para tornar effect sketch menor. |
|
|
83
|
+
| **shotgun surgery** | Cirurgia espalhada — anti-pattern (cap 21): mesma mudança espalhada em N lugares; cada incidência é um change point separado. Effect sketch detecta. |
|
|
84
|
+
|
|
85
|
+
### Monster Methods
|
|
86
|
+
|
|
87
|
+
> Vocabulário do cap 22 (I Need to Change a Monster Method and I Can't Write Tests for It). Métodos absurdamente longos (> 200 linhas) onde você não consegue nem entender o que faz, muito menos testar. Estratégia: scratch refactoring + single-goal editing + extrair pedacinhos sem mudar comportamento.
|
|
88
|
+
|
|
89
|
+
| EN | PT-BR / Significado |
|
|
90
|
+
|---|---|
|
|
91
|
+
| **monster method** | Método monstro — método com várias páginas de código, múltiplos níveis de aninhamento, múltiplas responsabilidades. Heurística: > 100 linhas ou > 5 níveis de indent. |
|
|
92
|
+
| **bulleted method** | Método com bullets — variante: linhas longas mas planas (sem nesting). Mais fácil de domar. |
|
|
93
|
+
| **snarled method** | Método emaranhado — variante: nesting profundo, condicionais aninhadas, control flow espaguete. Mais difícil. |
|
|
94
|
+
| **scratch refactoring** | Refactor de rascunho — quebra estética sem commitar. Use uma branch lixo, refatore para entender, descarte. Conhecimento adquirido vai para a refatoração real. |
|
|
95
|
+
| **single-goal editing** | Edição com objetivo único — mudar UMA coisa por vez. Renomear OU extrair OU mover, nunca os 3 juntos. Cada mudança é um diff legível. |
|
|
96
|
+
| **safe extraction** | Extração segura — extrair método sem mover lógica entre escopos. Apenas levantar bloco contíguo + capturar variáveis usadas como parâmetros. |
|
|
97
|
+
| **method blob** | Blob de método — sinônimo informal de monster method. |
|
|
98
|
+
|
|
99
|
+
### Dependency-Breaking Techniques
|
|
100
|
+
|
|
101
|
+
> Vocabulário do cap 25 (Dependency-Breaking Techniques) — o catálogo principal. ~24 técnicas para tornar testável o que não era. Cada técnica tem trade-offs diferentes (segurança, custo, mecanização).
|
|
102
|
+
|
|
103
|
+
| EN | PT-BR / Significado |
|
|
104
|
+
|---|---|
|
|
105
|
+
| **subclass and override method** | Subclassificar e sobrescrever método — criar subclasse de teste que substitui método problemático. Funciona em qualquer linguagem com herança virtual. |
|
|
106
|
+
| **extract interface** | Extrair interface — criar interface a partir da classe concreta, fazer cliente depender da interface, fornecer fake implementation em teste. |
|
|
107
|
+
| **adapt parameter** | Adaptar parâmetro — quando parâmetro tem tipo difícil de criar (ex: `HttpServletRequest`), envolver em interface mais simples e fazer cliente depender dela. |
|
|
108
|
+
| **introduce static setter** | Introduzir setter estático — adicionar setter para singleton/global; teste injeta fake; teardown restaura. **Risk: thread safety** — só em ambientes single-threaded de teste. |
|
|
109
|
+
| **encapsulate global references** | Encapsular referências globais — substituir acesso direto a variáveis globais por método de instância da classe. Permite override em teste. |
|
|
110
|
+
| **expose static method** | Expor método estático — promover método de instância a estático para testar sem instanciar a classe inteira (quando construtor é caro). |
|
|
111
|
+
| **break out method object** | Quebrar para method object — extrair método grande para classe com `run()`. Variáveis locais viram fields, fácil de testar. |
|
|
112
|
+
| **parameterize constructor** | Parametrizar construtor — passar dependência via construtor (DI manual) em vez de criar dentro. Default constructor mantém retrocompatibilidade. |
|
|
113
|
+
| **parameterize method** | Parametrizar método — passar dependência como argumento da chamada. Útil quando dependency só é usada num método específico. |
|
|
114
|
+
| **pull up feature** | Subir feature — mover método/field para superclasse para que subclasse de teste possa override. |
|
|
115
|
+
| **push down dependency** | Empurrar dependência — mover dependência problemática para subclasse, fazer base abstrata sem ela; teste usa subclasse de teste sem dependência real. |
|
|
116
|
+
| **replace function with function pointer** | Substituir função por ponteiro de função — em C, substituir chamada estática por ponteiro que teste pode reapontar. |
|
|
117
|
+
| **introduce instance delegator** | Introduzir delegador de instância — método estático vira fino wrapper que chama método de instância injetada. Permite mock. |
|
|
118
|
+
| **link substitution** | Substituição de link — providenciar `.so`/`.dll`/`.jar` alternativo em test classpath/library path. |
|
|
119
|
+
| **definition completion** | Completar definição (C/C++) — fornecer `.cpp` alternativo no link de teste para sobrescrever função declarada em `.h`. |
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## (b) Patterns canônicos
|
|
124
|
+
|
|
125
|
+
### Pattern: Algoritmo de mudança em legacy code (cap 1)
|
|
126
|
+
|
|
127
|
+
```text
|
|
128
|
+
1. Identify change points (onde mudar)
|
|
129
|
+
2. Find test points (onde testar — idealmente nas inflection points)
|
|
130
|
+
3. Break dependencies (cap 25 — aplicar técnica adequada)
|
|
131
|
+
4. Write characterization tests (cap 13 — congelar comportamento atual)
|
|
132
|
+
5. Make changes and refactor (cover and modify, não edit and pray)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**Insight central:** os passos 1-4 são **investimento prévio à mudança**. Quem pula direto ao passo 5 está em "edit and pray" — pode ter sorte 9 vezes em 10 mas a 10ª vez é incident SEV1.
|
|
136
|
+
|
|
137
|
+
### Pattern: identificar legacy code via critérios
|
|
138
|
+
|
|
139
|
+
```text
|
|
140
|
+
Um arquivo/módulo é "legacy" no sentido Feathers se:
|
|
141
|
+
|
|
142
|
+
1. Cobertura de testes < 60%? → SIM → legacy
|
|
143
|
+
2. Existem branches sem teste algum? → SIM → legacy
|
|
144
|
+
3. Mudanças recentes (último mês) não tiveram teste novo correspondente? → SIM → legacy
|
|
145
|
+
4. Faz parte de contrato externo (webhook, API pública, integração)? → SIM → legacy MESMO COM testes (porque consumer breakage é pior)
|
|
146
|
+
5. Tem mais de 500 linhas em arquivo único? → SIM → legacy candidate (pelo menos suspeito)
|
|
147
|
+
6. Tem métodos > 100 linhas? → SIM → monster methods, candidato a cap 22
|
|
148
|
+
|
|
149
|
+
Heurística agregada: se 2+ critérios = legacy → exigir characterization tests antes de qualquer refactor.
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Pattern: decision tree para escolher técnica de quebra de dependência
|
|
153
|
+
|
|
154
|
+
```text
|
|
155
|
+
Posso modificar o código? (acesso write?)
|
|
156
|
+
├─ Não → preprocessing seam (C/C++) ou link seam (qualquer linguagem)
|
|
157
|
+
└─ Sim →
|
|
158
|
+
├─ Linguagem tem herança/polimorfismo? (Java, C#, Python, Ruby, TS...)
|
|
159
|
+
│ ├─ Sim → object seam (preferred)
|
|
160
|
+
│ │ ├─ Dependência é classe? → extract interface OU subclass and override
|
|
161
|
+
│ │ ├─ Dependência é singleton/global? → encapsulate global references OU introduce static setter
|
|
162
|
+
│ │ ├─ Dependência é tipo de framework? (HttpServletRequest, Context) → adapt parameter
|
|
163
|
+
│ │ └─ Dependência é construído internamente? → parameterize constructor / parameterize method
|
|
164
|
+
│ └─ Não (C, COBOL, código procedural) → link seam OU function pointer substitution
|
|
165
|
+
└─ Construtor da classe é caro? → expose static method (testar sem instanciar)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Pattern: Sprout decision tree (cap 6)
|
|
169
|
+
|
|
170
|
+
```text
|
|
171
|
+
Tenho que adicionar comportamento a método não testado.
|
|
172
|
+
|
|
173
|
+
Tenho tempo para colocar o método inteiro sob test harness primeiro?
|
|
174
|
+
├─ Sim → técnicas do cap 25 (preferencial)
|
|
175
|
+
└─ Não →
|
|
176
|
+
├─ Comportamento novo é coeso e separável? → SPROUT METHOD
|
|
177
|
+
│ 1. Escrever método novo (static ou de classe nova) — testável
|
|
178
|
+
│ 2. Chamar do método legado em 1 linha
|
|
179
|
+
│ 3. Test do sprout via test harness próprio
|
|
180
|
+
│ 4. Método legado permanece untested mas o NOVO comportamento está coberto
|
|
181
|
+
├─ Comportamento novo é grande (>30 linhas)? → SPROUT CLASS
|
|
182
|
+
│ 1. Criar classe nova encapsulando o novo comportamento
|
|
183
|
+
│ 2. Construir + chamar a classe do método legado
|
|
184
|
+
│ 3. Test class isoladamente
|
|
185
|
+
└─ Preciso modificar pré ou pós-condição do método legado? → WRAP METHOD
|
|
186
|
+
1. Renomear `foo` → `fooLegacy` (apenas mecânico)
|
|
187
|
+
2. Criar novo `foo` que chama `fooLegacy` + adiciona comportamento
|
|
188
|
+
3. Testes do `foo` cobrem composição; `fooLegacy` ainda untested mas chamável
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Pattern: characterization tests workflow (cap 13)
|
|
192
|
+
|
|
193
|
+
```text
|
|
194
|
+
1. Escolher input typical → rodar código → capturar output
|
|
195
|
+
2. Escrever teste assertando output capturado (mesmo se output for um bug)
|
|
196
|
+
3. Repetir para 5-10 inputs cobrindo grupos de equivalência:
|
|
197
|
+
- null/vazio
|
|
198
|
+
- válido típico
|
|
199
|
+
- válido extremo (boundaries)
|
|
200
|
+
- inválido recoverable
|
|
201
|
+
- inválido fatal
|
|
202
|
+
4. Rodar todos verde → BASELINE estabelecido
|
|
203
|
+
5. AGORA refactor pode começar — qualquer test que vire vermelho = regressão real
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**Anti-pattern:** começar a "consertar" o teste para o output "correto". Isso destrói o oracle. Bug → preserve, fix em commit separado depois do refactor.
|
|
207
|
+
|
|
208
|
+
### Pattern: 6 níveis de "está testável?" (cap 9-10)
|
|
209
|
+
|
|
210
|
+
| Nível | Sintoma | Solução |
|
|
211
|
+
|---|---|---|
|
|
212
|
+
| **L0** | Não consigo construir a classe (construtor irritado, faz I/O, throws) | Cap 9 técnicas — fake constructor parameters, expose static method |
|
|
213
|
+
| **L1** | Classe constrói mas método não roda isolado (depende de globals) | Encapsulate global references |
|
|
214
|
+
| **L2** | Método roda mas dependências reais (DB, rede, clock) executam | Inject collaborator OR subclass and override |
|
|
215
|
+
| **L3** | Dependências stubadas mas effects spread (DB grava, email envia) | Sense via fake (verify-no-side-effect) |
|
|
216
|
+
| **L4** | Roda isolado, mas saída não-determinística (random, datetime.now) | Inject clock/random como dependência |
|
|
217
|
+
| **L5** | Roda isolado e determinístico mas eu não entendo o que testa | Characterization tests para descobrir |
|
|
218
|
+
|
|
219
|
+
Meta é L5+. Antes de refatorar, código deve estar em L4 ou melhor.
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## (c) Anti-patterns canônicos
|
|
224
|
+
|
|
225
|
+
### ANTI: refactor sem characterization tests
|
|
226
|
+
|
|
227
|
+
```text
|
|
228
|
+
ANTI: "vou refatorar esse método de 200 linhas, depois adiciono testes do
|
|
229
|
+
novo design".
|
|
230
|
+
|
|
231
|
+
PROBLEMA: você não sabe o que está preservando. O método tem branches que
|
|
232
|
+
você não sabe que existem. Bugs antigos que clientes dependem
|
|
233
|
+
(Hyrum's Law) somem silenciosamente. Resultado típico: incident
|
|
234
|
+
em prod 2 semanas depois quando edge case dispara.
|
|
235
|
+
|
|
236
|
+
CERTO: characterize first (cap 13), refactor second. Pelo menos 5-10
|
|
237
|
+
inputs cobrindo grupos de equivalência ANTES de mover qualquer
|
|
238
|
+
linha. Se o método é de 200 linhas, esse trabalho leva 1-2 dias.
|
|
239
|
+
Aceite o custo — alternativa é o incident.
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### ANTI: edit and pray (cap 1)
|
|
243
|
+
|
|
244
|
+
```text
|
|
245
|
+
ANTI: "vou modificar essa linha, rodar smoke test, dar push e ver no
|
|
246
|
+
monitoring".
|
|
247
|
+
|
|
248
|
+
PROBLEMA: smoke test cobre golden path. Branches raras (1% do tráfego)
|
|
249
|
+
escapam silenciosamente. Bugs em borda manifestam horas/dias
|
|
250
|
+
depois. Forensics fica difícil porque change set tem N edits
|
|
251
|
+
no mesmo PR.
|
|
252
|
+
|
|
253
|
+
CERTO: cover and modify. Antes de modificar, encontre o seam e adicione
|
|
254
|
+
teste que exercita a branch específica. Se não há seam, primeiro
|
|
255
|
+
adicione um (cap 25). Investimento de 1-4h vs incident de 4-40h.
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### ANTI: fix bug ANTES do characterization
|
|
259
|
+
|
|
260
|
+
```text
|
|
261
|
+
ANTI: "ah, esse método tem um bug óbvio na linha 42, vou consertar
|
|
262
|
+
enquanto refatoro".
|
|
263
|
+
|
|
264
|
+
PROBLEMA: characterization test capturou o bug como comportamento
|
|
265
|
+
esperado. Você consertou → teste fica vermelho → você
|
|
266
|
+
"atualiza o teste" → oracle morto → não há baseline mais.
|
|
267
|
+
|
|
268
|
+
CERTO: 2 commits separados. (1) characterize + refactor preservando
|
|
269
|
+
bug. (2) bug fix com teste novo do comportamento correto. Aplique
|
|
270
|
+
o fix DEPOIS, com seu próprio test antes (TDD agora possível
|
|
271
|
+
porque você tem test harness funcionando).
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### ANTI: golden master sem revisão humana
|
|
275
|
+
|
|
276
|
+
```text
|
|
277
|
+
ANTI: rodar code → capturar output → commitar como `expected.txt` sem
|
|
278
|
+
ler. "É o que o código produz, deve estar certo".
|
|
279
|
+
|
|
280
|
+
PROBLEMA: output captura inclui bugs já existentes. Sem revisão, você
|
|
281
|
+
congela bugs como contrato. Se o output incluir PII, secret,
|
|
282
|
+
UUID local — você acabou de commitar dado sensível.
|
|
283
|
+
|
|
284
|
+
CERTO: ler o output capturado linha por linha antes de salvar. Marcar
|
|
285
|
+
expectativas conhecidas-buggy com comentário inline (`// BUG #123:
|
|
286
|
+
deveria ser X, é Y`). Redact PII/secret/UUID via post-processing
|
|
287
|
+
deterministic (hash, mask). Commit do golden é uma decisão, não
|
|
288
|
+
um copy-paste.
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### ANTI: monster method "limpado" em 1 PR
|
|
292
|
+
|
|
293
|
+
```text
|
|
294
|
+
ANTI: PR com 800 linhas de diff: extract method × 12, rename × 5, move
|
|
295
|
+
logic × 3, fix off-by-one × 2 — tudo junto.
|
|
296
|
+
|
|
297
|
+
PROBLEMA: PR não-revisável. Reviewer não consegue separar refactor
|
|
298
|
+
(nullable) de fix (semântico). Se algo quebra, bisect aponta
|
|
299
|
+
para o PR inteiro. CI verde não significa nada — branch
|
|
300
|
+
coverage caiu silenciosa.
|
|
301
|
+
|
|
302
|
+
CERTO: 1 PR por single-goal edit (cap 22). Sequência típica:
|
|
303
|
+
PR1 — extract method (3 helpers, mecânico, comportamento idêntico)
|
|
304
|
+
PR2 — extract class (mover helpers para nova classe)
|
|
305
|
+
PR3 — invert dependency (constructor injection)
|
|
306
|
+
PR4 — fix bug X (com teste novo, semântico)
|
|
307
|
+
Cada PR ≤ 100 linhas. Cada um é revisável e revertível.
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### ANTI: substituir testes "falhos" sem investigar
|
|
311
|
+
|
|
312
|
+
```text
|
|
313
|
+
ANTI: characterization test virou vermelho após refactor. "Provavelmente
|
|
314
|
+
o teste estava errado, vou atualizar o expected".
|
|
315
|
+
|
|
316
|
+
PROBLEMA: você acabou de pintar "Vermelho → verde" em cima de regressão
|
|
317
|
+
real. Comportamento mudou e você passou por cima da rede de
|
|
318
|
+
segurança. Próximo bug em prod vem por essa porta.
|
|
319
|
+
|
|
320
|
+
CERTO: vermelho de characterization test = regressão até prova ao
|
|
321
|
+
contrário. Investigue: o que no refactor mudou comportamento?
|
|
322
|
+
Reverte aquele pedaço, refatore de outra forma. Só atualize o
|
|
323
|
+
golden APÓS confirmar que o novo comportamento É o desejado e
|
|
324
|
+
documentar no commit (`// behavior change: rounds half-up; was
|
|
325
|
+
half-even`).
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
### ANTI: confiar em coverage % como proxy de safety
|
|
329
|
+
|
|
330
|
+
```text
|
|
331
|
+
ANTI: "linha de coverage está em 85%, posso refatorar tranquilo".
|
|
332
|
+
|
|
333
|
+
PROBLEMA: coverage % = "linha foi executada", não "comportamento foi
|
|
334
|
+
observado". Teste pode entrar na linha sem assertar. 85%
|
|
335
|
+
line coverage com 10% behavioral coverage é frágil mesmo.
|
|
336
|
+
|
|
337
|
+
CERTO: behavioral coverage = % de branches × observation points
|
|
338
|
+
cobertos por characterization tests. Pelo menos 70-80% antes de
|
|
339
|
+
refactor pesado. Use mutation testing (stryker, mutmut, pitest)
|
|
340
|
+
para confirmar — survived mutants = pontos cegos não cobertos.
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
---
|
|
344
|
+
|
|
345
|
+
## (d) Mapa de capítulos do livro
|
|
346
|
+
|
|
347
|
+
> Capa-índice para localizar qual skill consultar dado um sintoma específico. Skills cobrem capítulos do livro Feathers.
|
|
348
|
+
|
|
349
|
+
| Capítulo | Tema | Skill no kit |
|
|
350
|
+
|---|---|---|
|
|
351
|
+
| Cap 1 | Changing Software (edit and pray vs cover and modify) | `legacy-characterization-tests` (intro) |
|
|
352
|
+
| Cap 2 | Working with Feedback | `legacy-characterization-tests` (rationale) |
|
|
353
|
+
| Cap 3 | Sensing and Separation | `legacy-seams-and-test-harness` |
|
|
354
|
+
| Cap 4 | The Seam Model | `legacy-seams-and-test-harness` (foundation) |
|
|
355
|
+
| Cap 5 | Tools | (tooling — não é skill, mencionado em refs) |
|
|
356
|
+
| Cap 6 | I Don't Have Much Time and I Have to Change It | `legacy-sprout-wrap-techniques` |
|
|
357
|
+
| Cap 7-8 | It Takes Forever / How Do I Add a Feature | (gerais — disseminados em skills) |
|
|
358
|
+
| Cap 9-10 | I Can't Get This Class/Method into a Test Harness | `legacy-seams-and-test-harness` |
|
|
359
|
+
| Cap 11 | What Methods Should I Test? | `legacy-effect-analysis` |
|
|
360
|
+
| Cap 12 | Many Changes in One Area | `legacy-effect-analysis` |
|
|
361
|
+
| Cap 13 | What Tests to Write — **Characterization Tests** | `legacy-characterization-tests` ⭐ |
|
|
362
|
+
| Cap 14-15 | Libraries / API Calls | (caso especial — refs em sprout-wrap) |
|
|
363
|
+
| Cap 16 | I Don't Understand the Code | `legacy-effect-analysis` (sketches) |
|
|
364
|
+
| Cap 17 | Application Has No Structure | (refactor de larga escala — fora de scope) |
|
|
365
|
+
| Cap 18-21 | Test code in the way / Procedural / Big classes / Shotgun | (referências) |
|
|
366
|
+
| Cap 22 | Monster Method | `legacy-monster-methods` |
|
|
367
|
+
| Cap 23 | How Do I Know I'm Not Breaking Anything | `legacy-characterization-tests` |
|
|
368
|
+
| Cap 24 | Overwhelmed | (cultural — refs em commands) |
|
|
369
|
+
| Cap 25 | **Dependency-Breaking Techniques** (catálogo) | `legacy-seams-and-test-harness` |
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
## (e) Cross-references
|
|
374
|
+
|
|
375
|
+
- [`legacy-characterization-tests`](../legacy-characterization-tests/SKILL.md) — cap 13 + 23, foundational
|
|
376
|
+
- [`legacy-seams-and-test-harness`](../legacy-seams-and-test-harness/SKILL.md) — cap 3-4 + 9-10 + 25
|
|
377
|
+
- [`legacy-sprout-wrap-techniques`](../legacy-sprout-wrap-techniques/SKILL.md) — cap 6
|
|
378
|
+
- [`legacy-effect-analysis`](../legacy-effect-analysis/SKILL.md) — cap 11-12 + 16
|
|
379
|
+
- [`legacy-monster-methods`](../legacy-monster-methods/SKILL.md) — cap 22
|
|
380
|
+
- [`pre-refactor-characterization`](../pre-refactor-characterization/SKILL.md) — auto-trigger gate (workflow integration)
|
|
381
|
+
|
|
382
|
+
### Cross-suite
|
|
383
|
+
|
|
384
|
+
- [`event-based-slos`](../event-based-slos/SKILL.md) (v1.9) — characterization tests defendem SLO durante refactor; behavioral diff = budget burn
|
|
385
|
+
- [`production-readiness-review`](../production-readiness-review/SKILL.md) (v1.10) — PRR Axe 5 (Change Management) consume characterization status
|
|
386
|
+
- [`blameless-postmortems`](../blameless-postmortems/SKILL.md) (v1.10) — postmortems pós-refactor sem characterization viram lesson learned canônica
|
|
387
|
+
- [`observability-driven-development`](../observability-driven-development/SKILL.md) (v1.9) — characterization + ODD instrumentation = safety + visibility durante refactor
|
|
388
|
+
|
|
389
|
+
*Material-fonte: Working Effectively with Legacy Code — Feathers, 2004. ISBN 978-0-13-117705-5.*
|