yutna/oo-design

Use ao iniciar um novo módulo, funcionalidade ou sistema em uma base de código orientada a objetos, dimensionar o design ou quando não tiver certeza de qual regra de objeto se aplica.

O que é oo-design?

Este skill fornece um guia abrangente de design orientado a objetos para ajudar desenvolvedores a tomar decisões de design consistentes e bem fundamentadas. Ele cobre todo o ciclo de vida do design, desde a avaliação de quanto design é necessário até a aplicação de regras específicas com base em sintomas comuns. O skill é baseado em um conjunto de regras principais categorizadas como 'Regra', 'Padrão' ou 'Julgamento', e inclui um 'loop de design' de sete etapas que orienta o desenvolvedor desde a compreensão do domínio até a revisão do design final. Ele também vincula sintomas comuns (por exemplo, 'esta classe faz demais') às skills específicas que os tratam, facilitando a localização da orientação exata necessária. Além disso, oferece skills específicos de linguagem (Java, Kotlin, TypeScript, JavaScript) que adaptam os princípios centrais às idiossincrasias de cada linguagem, sem substituir as regras fundamentais. O skill é projetado para ser usado como um ponto de partida: ele dimensiona a tarefa e nomeia a skill apropriada, que deve então ser carregada para obter as regras e exemplos detalhados.

Funciona com✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/yutna/object-oriented-design-skills/tree/HEAD/plugins/core/skills/oo-design

Installed? Explore more Programação e Desenvolvimento skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Design Orientado a Objetos

Visão Geral

Este pacote contém regras de design para bases de código escritas em estilo orientado a objetos, não conselhos universais. As convenções escritas do próprio projeto prevalecem sobre o pacote. Siga o idioma do módulo que está sendo modificado. Este skill dimensiona a tarefa e nomeia o skill que se encaixa.

Carregue o skill que este índice nomeia antes de responder: suas regras e exemplos estão lá, não aqui.

Quanto design uma tarefa justifica

TarefaUsarIgnorar
Uma resposta usada uma vez e depois descartadaNadaTudo
Um método em uma classe que existeSeu nome e seu contratoRemodelação
Uma funcionalidade dentro de um fluxo existenteO idioma que aquele fluxo usaNovos limites
Uma nova classe ou móduloO loop de designNada
Um novo contextoO loop, depois seus limitesNada
Um novo sistema do zeroO loop, contextos, depois estruturaNada

Antes de projetar

Antes de projetar, declare o portão: uma regra que o software deve seguir, com um exemplo que ela aceita e um que rejeita. Por exemplo, "Um slot pode conter no máximo um agendamento." Ela aceita agendar um segundo paciente em um slot diferente e rejeita agendar um segundo paciente no mesmo slot. Se você consegue escrever a regra, comece. Se não consegue, o que falta não é design, e este pacote não pode fornecê-lo.

O loop de design

  1. Diga o que o software deve fazer nas palavras do domínio (falando a linguagem do domínio), e encontre o objeto que sabe o que cada comportamento precisa (atribuindo responsabilidades).
  2. Encontre o limite de consistência: o que deve ser verdadeiro junto em uma transação (projetando agregados).
  3. Decida onde cada regra vive: uma entidade, um objeto de valor ou um serviço de domínio (posicionando a lógica de domínio).
  4. Projete as mensagens que cada objeto responde (encapsulando estado e comportamento), e torne estados ilegais impossíveis de construir (tornando estados ilegais impossíveis).
  5. Inverta as dependências para que o domínio não saiba nada sobre o banco de dados ou o framework (invertendo dependências, em camadas no sistema).
  6. Nomeie as coisas nas palavras do domínio, e comente apenas o que o código não pode dizer (nomeando classes e métodos, comentando o que o código não pode dizer).
  7. Verifique o resultado contra as bandeiras vermelhas abaixo (revisando design de objetos).

Quão estritamente uma regra é aplicada

Toda regra principal neste pacote carrega um de três rótulos, e o rótulo diz quão estritamente ela é aplicada.

  • Regra. Quebrá-la é um defeito. Nenhum framework a desculpa.
  • Padrão. Faça isso a menos que uma condição declarada se aplique. A condição é sua própria frase, nunca uma cláusula final.
  • Julgamento. Duas respostas são defensíveis. O skill diz o que inclina a balança.

Sintomas para skills

Sintomas apontam para o skill que os trata, e esta tabela cresce à medida que skills são adicionados.

SintomaSkill
Qual classe deve fazer isso?Atribuindo responsabilidades
Esta classe faz demaisAtribuindo responsabilidades
Uma mudança se propaga por muitas classesDiagnosticando acoplamento
Quão fortemente essas duas partes estão ligadas?Diagnosticando acoplamento
Isto é um objeto ou apenas dados?Decidindo objeto ou dados
Nosso modelo de domínio é anêmicoDecidindo objeto ou dados
Outro código decide por este objetoEncapsulando estado e comportamento
Setters permitem que este objeto quebre suas regrasEncapsulando estado e comportamento
Este objeto pode existir meio construídoConstruindo objetos válidos
Este construtor recebe muitos argumentosConstruindo objetos válidos
Cada novo caso significa editar código funcionalEncapsulando o que varia
Quanta flexibilidade isto deve ter?Encapsulando o que varia
Isto é um valor ou uma entidade?Modelando valores e entidades
Strings e números brutos carregam regras de domínioModelando valores e entidades
Isto deve estender aquela classe ou mantê-la?Escolhendo composição sobre herança
Mudar uma classe base quebra suas subclassesEscolhendo composição sobre herança
Uma subclasse quebra o que seu pai prometeHonrando substituibilidade
Código verifica qual subtipo ele contémHonrando substituibilidade
O mesmo switch em um tipo continua voltandoSubstituindo condicionais por polimorfismo
Subclasses ou pattern matching?Substituindo condicionais por polimorfismo
Código atravessa uma cadeia de objetosLimitando o que um objeto sabe
Esta classe apenas encaminha chamadasLimitando o que um objeto sabe
Como esta classe ou método deve ser chamado?Nomeando classes e métodos
Nomes como Manager, Helper ou UtilNomeando classes e métodos
Chamadores dependem de métodos de interface que nunca usamProjetando interfaces
Interface ou classe base abstrata?Projetando interfaces
Código de domínio depende de um banco de dados ou frameworkInvertendo dependências
Onde os objetos são criados e conectados?Invertendo dependências
Chamadores sabem como outra classe armazena ou formata dadosEscondendo implementação
Uma classe vaza seus erros internos ou etapasEscondendo implementação
Flags ou campos opcionais permitem combinações impossíveisTornando estados ilegais impossíveis
Um tipo admite valores que o domínio nunca temTornando estados ilegais impossíveis
As palavras do código diferem das da equipeFalando a linguagem do domínio
Uma palavra significa coisas diferentes para duas equipesFalando a linguagem do domínio
Quais objetos devem mudar juntos?Projetando agregados
Salvamentos colidem ou uma carga puxa demaisProjetando agregados
Quais mudanças de status são permitidas?Modelando ciclos de vida
Um objeto cancelado ou fechado muda novamenteModelando ciclos de vida
Como os objetos de domínio devem ser armazenados e encontrados?Projetando repositórios
O repositório tem um método find por telaProjetando repositórios
Casos de uso repetem a mesma verificação de negócioPosicionando a lógica de domínio
Serviço de domínio, método de entidade ou serviço de aplicação?Posicionando a lógica de domínio
Outras partes devem reagir após uma mudança ser salvaPublicando eventos de domínio
Uma mensagem saiu para uma mudança que foi desfeitaPublicando eventos de domínio
Onde termina o modelo de uma equipe e começa o de outra?Delimitando contextos
Quais partes são centrais e quais podemos comprar?Delimitando contextos
Em qual direção as camadas devem depender?Em camadas no sistema
Uma tela ou job não pode ser testado sem seu frameworkEm camadas no sistema
Módulos dependem uns dos outros em um cicloOrganizando módulos
Monólito modular ou serviços separados?Organizando módulos
Uma mudança na nossa API quebra os aplicativos que a chamamCruzando limites do sistema
Como devemos versionar esta API ou mensagem?Cruzando limites do sistema
A ferramenta de mapeamento molda nossas classes de domínioDomando persistência
Uma lista executa uma consulta por linhaDomando persistência
Telas precisam de dados moldados de forma diferente do modeloSeparando leituras de escritas
Modelo de leitura, projeção ou event sourcing?Separando leituras de escritas
MVC, MVP ou MVVM para esta tela?Separando apresentação do domínio
Uma tela edita objetos de domínio diretamenteSeparando apresentação do domínio
Qual padrão de design se encaixa neste problema?Escolhendo um padrão
Um padrão foi adicionado antes do seu problemaEscolhendo um padrão
Estas classes de padrão poderiam ser uma funçãoPadrões que a linguagem fornece
Visitor ou um conjunto fechado com matching?Padrões que a linguagem fornece
Um método retorna null quando não encontra nadaProjetando comportamento de falha
Recusas retornam como códigos que os chamadores ignoramProjetando comportamento de falha
Threads compartilham um objeto e perdem ou misturam suas mudançasGerenciando estado compartilhado
Um lock ou um único dono para este estado?Gerenciando estado compartilhado
Uma chamada para outro sistema trava ou falha no meioTornando o trabalho confiável
Uma tentativa fez o trabalho duas vezesTornando o trabalho confiável
Não conseguimos explicar um incidente a partir de nossos registrosProjetando o que registrar
O que devemos logar, contar ou auditar?Projetando o que registrar
Uma revisão encontrou uma god class ou fluxo de lavaReconhecendo antipadrões
Qual antipadrão devemos corrigir primeiro?Reconhecendo antipadrões
Testes quebram embora o comportamento não tenha mudadoTestando código orientado a objetos
Mock, stub ou fake para este colaborador?Testando código orientado a objetos
Testes dependem do tempo ou de valores aleatóriosProjetando para testabilidade
Código é tornado público apenas para que testes possam alcançá-loProjetando para testabilidade
Como reestruturamos este código com segurança?Refatorando em direção ao design de objetos
Uma refatoração cresceu demais para terminarRefatorando em direção ao design de objetos
Precisamos alterar código que não tem testesTrabalhando com código legado
Substituir um sistema antigo peça por peçaTrabalhando com código legado
O que esta revisão deve verificar?Revisando design de objetos
Quais descobertas da revisão bloqueiam um merge?Revisando design de objetos
Ninguém lembra por que o código tem esta formaDocumentando decisões de design
O que devemos desenhar, e em que nível?Documentando decisões de design
Comentários repetem o código ou o contradizemComentando o que o código não pode dizer
Onde explicamos por que este código parece estranho?Comentando o que o código não pode dizer
Um hook ou marcador de framework contém uma regra de negócioTrabalhando dentro de um framework
Até onde devemos seguir o framework?Trabalhando dentro de um framework
Um cálculo também salva, envia ou muda suas entradasAplicando técnicas funcionais
Quais técnicas funcionais se encaixam em código de objeto?Aplicando técnicas funcionais

Skills de linguagem

Um skill de linguagem mantém as regras principais em uma linguagem e nunca as substitui. Um skill de linguagem base é para código sem framework.

  • oo-java, de object-oriented-design-java: records, sealed types, equals e hashCode, exceções verificadas, Optional e classes fechadas para extensão.
  • oo-kotlin, de object-oriented-design-kotlin: data classes, sealed types, tipos anuláveis, delegação com by e funções de extensão.
  • oo-typescript, de object-oriented-design-typescript: identificadores marcados, estado #private, classes abstratas, decorators, uniões discriminadas e uma raiz de composição.
  • oo-javascript, de object-oriented-design-javascript: c

…

[truncado para tradução]

Habilidades Relacionadas