Aula 06 · 50–65 minutos
Escolha com critério
Sexta aula: escolha quando aplicar inversão de dependência em Go.
Resultado e mapa da aula
Esta conclusão transforma o padrão em decisão de engenharia. Você poderá apresentar uma evidência para criar ou recusar uma interface, explicar seu custo e registrar o limite da decisão para que uma futura mudança seja mais simples.
- Localize a política e a colaboração.
- Verifique se existe variação ou teste relevante.
- Compare contrato mínimo e concreto simples.
- Defenda o trade-off em revisão e entrevista.
O critério é uma necessidade, não uma estética
Interfaces são úteis quando um consumidor tem uma colaboração clara e você quer testar ou trocar o detalhe. Elas custam leitura, nomes e mais pontos de navegação. Sem um motivo concreto, esse custo não compra flexibilidade útil.
necessidade do consumidor? → variação ou teste relevante? → interface pequena; caso contrário → tipo concretoFaça três perguntas
- Há uma regra de negócio? Se não há política a proteger, talvez seja apenas uma chamada local simples.
- O consumidor precisa de poucos comportamentos? Se sim, ele pode possuir um contrato mínimo.
- Há uma variação real? Banco, API externa, relógio ou teste determinístico podem justificá-la.
Uma resposta "não" não é fracasso de design. Em Go, começar com o tipo concreto e extrair a interface no consumidor quando o uso aparece costuma ser a opção mais clara.
Trade-offs em linguagem de conversa técnica
Esse argumento descreve fluxo, responsabilidade e alternativa de teste sem prometer abstração para mudanças imaginárias.
Recupere da memória
Qual evidência justifica criar uma interface em Go?
Fonte primária recomendada
Effective Go — Interfaces. Compare interfaces pequenas e concretas como io.Writer com as necessidades do seu caso.
Concluiu a trilha: volte ao índice e use o glossário durante uma refatoração real.
Uma abstração deve pagar seu próprio custo
Problema em trabalho real: Uma interface para cada struct cria mais nomes, indireção e superfície pública, mas não remove acoplamento se não houver um consumidor, uma borda ou uma variação real. A estética de “tudo abstraído” substitui evidência por suposição.
Fluxo e momento de execução: Comece pela política: há uma regra a proteger? Observe a colaboração que ela usa e a variação que precisa controlar. Se ambas são reais, declare o menor contrato no consumidor; se não são, mantenha o concreto e extraia depois, orientado pelo uso.
Abordagem insuficiente: Não crie interfaces antecipadas para “mockar qualquer coisa”. Um tipo concreto simples é a opção mais clara quando não há limite externo, comportamento alternativo ou teste determinístico que precise ser injetado.
Decisão recomendada: Defenda o contrato com a evidência concreta: checkout precisa salvar, PostgreSQL é uma borda e um fake permite provar a regra. Diga também o custo: mais uma API e indireção. Essa honestidade é parte de uma boa decisão de design.
Como verificar na prática: Para cada interface candidata, responda por escrito: qual consumidor a usa, quais métodos ele chama, qual detalhe varia e qual teste ficaria impossível ou caro sem ela? Se não houver resposta específica, não extraia ainda.
Limite de segurança: Não use uma interface como argumento de segurança por si só. Autorização, validação, limite de taxa e proteção de segredos são requisitos explícitos que devem ser testados na camada responsável.
Fonte primária: Effective Go — Interfaces.
Guia de solução do exercício
Fluxo de execução: Identifique uma regra, a colaboração que ela consome e a variação real. Só então decida entre interface pequena ou tipo concreto.
Abordagem inadequada: Criar uma interface antes de qualquer consumidor por “padronização” é abstração prematura.
type Clock interface { Now() time.Time }
// criada sem teste, troca ou consumidor que justifique o contrato
Por que falha e como corrigir: Você adiciona nomes e indireção, mas não remove um acoplamento real. A equipe passa a manter contratos especulativos e mocks sem uma decisão de negócio associada.
Abordagem correta: Extraia a interface no consumidor quando houver variação concreta, como um fake determinístico ou uma borda externa.
type OrderSaver interface { Save(Order) error }
// checkout usa; Postgres e fake satisfazem
Raciocínio, trade-offs e limites: Use tipo concreto para colaboração interna estável e simples. Use interface para uma borda ou quando o teste precisa controlar a colaboração. Explique o trade-off: o ganho é testabilidade e troca localizada; o custo é indireção e mais uma API a manter.
Abra o diagrama relacionado e compare o fluxo.
Pergunta de mercado e entrevista
1. Quando você não criaria uma interface?
Como responder: Quando não há consumidor, variação ou necessidade de teste. Um tipo concreto simples e estável é mais claro.
2. Qual trade-off você explicaria ao revisor?
Como responder: O ganho é testabilidade e troca localizada; o custo é indireção e mais uma API para manter. A decisão deve apontar o acoplamento real que está sendo removido.
3. Interfaces são só para mocks?
Como responder: Não. Elas modelam colaboração entre política e detalhe. Um fake de teste é uma consequência útil, mas não deve ser a única razão para abstrair prematuramente.
Pratique mais 9 questões de recuperação
Responda sem consultar a aula. O feedback é imediato; volte ao trecho relevante antes de tentar de novo.
DI entrega uma dependência; DIP define:
Em Go, uma interface é satisfeita quando:
Quem deve possuir uma interface pequena?
Onde a implementação concreta é escolhida?
Para testar uma regra sem banco, injete:
Uma interface deve conter:
O detalhe PostgreSQL deve depender de:
Qual sinal pede uma interface?
Após a refatoração, a regra não deve importar: