Communitygithub.com

Usar Dependências de Forma Idiomática

Use as bibliotecas e frameworks de um projeto de forma idiomática: aprendendo o modelo de cada um em vez de reinventar a roda ou lutar contra o framework.

O que é Usar Dependências de Forma Idiomática?

Esta habilidade ensina como utilizar dependências de forma idiomática em projetos de desenvolvimento de software, focando em aprender o modelo que cada biblioteca ou framework encapsula. Ela é útil para evitar armadilhas comuns como reinventar a roda, lutar contra o framework ou subutilizar funcionalidades existentes. A habilidade é aplicável em qualquer plataforma de agente de IA focada em engenharia de software (como Claude Code, Cursor, Codex, etc.) e baseia-se em uma metodologia documentada. O processo envolve reafirmar o problema, verificar se ele já foi resolvido pela própria dependência, aprender o modelo a partir da documentação da versão instalada, escolher a abordagem correta e escrever o código de acordo com a API pública. A habilidade também identifica 'cheiros' de código que indicam quando se está lutando contra ou subutilizando uma biblioteca, além de cobrir revisão, auditoria e atualização de dependências.

Funciona com✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/AndrewIngram/swe-skills/tree/HEAD/skills/engineering/use-dependencies-idiomatically

Perguntar na sua IA favorita

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

Documentação

Use Dependências de Forma Idiomática

Toda dependência foi construída para um formato específico de problema. Sua API codifica esse modelo: o que ela possui, o que deixa para você, o que garante e onde espera ser estendida. Escreva a solução idiomática, aquela que os próprios documentos e exemplos canônicos da biblioteca mostrariam, e quando o problema tiver um formato diferente (um desajuste de impedância), escolha a ferramenta certa para o trabalho. As falhas a evitar são reinventar a roda, lutar contra o framework e subutilizar silenciosamente uma funcionalidade construída para o caso.

Atrito é um cheiro: um cast, patch ou workaround no caminho óbvio significa que o modelo foi mal interpretado ou a ferramenta está errada. As violações mais custosas não têm atrito algum: elas passam na verificação de tipos e parecem locais enquanto derrotam uma garantia que a biblioteca existe para fornecer, então procure por elas propositalmente.

Escrevendo código que usa uma dependência

O caminho padrão. Revisão, auditoria, adição e atualização partem dele (abaixo).

  1. Reformule o problema. Cuidado com o problema XY: a tarefa frequentemente chega como uma solução, vinda de você ou do usuário. Reformule-a como o problema geral:

    • "Repetir o upload três vezes" é uma política de repetição.
    • "Preciso de row_number() over (partition by account_id) para as faturas mais recentes de cada conta" é top-N por grupo, que um ORM pode modelar sem função de janela.

    "A biblioteca não consegue fazer X" é uma afirmação a verificar no passo 3, independentemente de quem a faça.

    Concluído quando você consegue nomear o problema nas palavras que os documentos da biblioteca usariam.

  2. Encontre onde já está resolvido, primeiro o mais próximo:

    1. O framework no qual você está inserido: políticas de repetição e temporizadores de um mecanismo de fluxo de trabalho, paginação e atualizadores de armazenamento de um cliente GraphQL, temporizadores falsos de um executor de testes.
    2. As dependências declaradas do projeto (package.json, pyproject.toml, go.mod, Cargo.toml) e como a base de código as importa. O uso existente mostra a convenção da casa, que pode diferir do design da biblioteca.
    3. Os pacotes compartilhados do projeto, que frequentemente encapsulam uma dependência da maneira que o projeto deseja usá-la.
    4. A biblioteca padrão, para a versão do runtime em uso (engines, .nvmrc, requires-python). As bibliotecas padrão abrangentes cobrem mais do que as pessoas lembram: itertools, collections, functools, pathlib do Python; fetch, AbortSignal.timeout, util.parseArgs, node:test do Node moderno.

    Concluído quando cada fonte é verificada e você tem uma lista de candidatos, possivelmente vazia.

  3. Aprenda o modelo a partir da documentação da versão instalada. Considere a versão do arquivo de bloqueio; uma fonte conta apenas se corresponder. Leia, em ordem:

    1. A orientação do projeto para esta dependência, encontrada e mantida em GUIDANCE.md. Ela é a autoridade sobre decisões deliberadas da casa e um cache do modelo da biblioteca: quando sua versão registrada difere do arquivo de bloqueio, ou uma afirmação decide sua abordagem, confirme-a nas fontes abaixo.
    2. Um checkout de referência: o repositório da dependência clonado no projeto ou obtido por uma ferramenta como opensrc, geralmente com um ponteiro em AGENTS.md ou CLAUDE.md. Verifique sua tag em relação ao arquivo de bloqueio. Seus documentos, exemplos e testes são o melhor registro do uso pretendido.
    3. O pacote instalado: tipos exportados e seus comentários de documentação, frequentemente sem os documentos e exemplos.
    4. Online, quando nenhuma das duas últimas tem documentos: a documentação oficial para aquela versão principal, páginas de conceito e guia, bem como a referência da API; em seguida, o repositório upstream na tag correspondente.

    Construa apenas sobre a API pública: o que os documentos descrevem, alcançado por meio de pontos de entrada declarados (um mapa exports, __all__, nomes sem sublinhado inicial). Leia o código-fonte para entender o comportamento; qualquer coisa que você encontrou apenas lá é privada. O Semver protege a API pública e nada mais. Sua memória da biblioteca é uma hipótese a ser verificada contra os documentos, e arquivos de runtime que você por acaso abre não substituem a documentação.

    Concluído quando você consegue responder a partir dos documentos, antes de escrever ou julgar código que a utiliza:

    • Para que foi construída e o que ela deliberadamente deixa de fora?
    • O que ela possui (armazenamento, cache, ciclo de vida, repetições, transações), o que ela gera ou pede que você declare (saída de codegen, esquemas, tipos), e para qual parte do seu código cada peça é?
    • Qual garantia ela mantém (mascaramento de dados, determinismo de fluxo de trabalho, isolamento de transações), entre quais partes do sistema, e o que a derrotaria silenciosamente? Frequentemente, ela fica entre seus próprios módulos.
    • Qual API pública e pontos de extensão documentados (opções, plugins, middleware, hooks, escotilhas de escape) cobrem isso, e como é o exemplo canônico, até quais módulos importam o quê?
    • Quais verificações ela fornece (um plugin de lint, validação de compilador ou codegen, um modo de tipo estrito), e o projeto as executa?
  4. Escolha o ajuste:

    • O problema corresponde ao modelo: use-o.
    • Parte dele fica fora da API principal: use a escotilha de escape documentada para essa parte (SQL bruto em um ORM, um componente sem cabeça, um resolvedor personalizado). Escotilhas de escape fazem parte do design.
    • A versão instalada não possui o recurso: se o changelog mostrar que uma versão mais recente o tem, proponha a atualização conforme UPGRADING.md.
    • Desajuste de impedância: use uma dependência cujo modelo se ajuste, ou código simples que fique longe desta, atrás de uma costura que possuímos. Estar instalada, ou usada nas proximidades, não torna uma biblioteca a ferramenta certa.

    Concluído quando você escolheu uma e pode justificá-la a partir do modelo.

  5. Escreva do jeito da biblioteca, em sua API pública. A primeira versão que funciona frequentemente não é a idiomática. Onde o código vizinho e o exemplo canônico discordarem, siga o exemplo canônico e informe o usuário sobre a deriva. Execute as próprias verificações da biblioteca enquanto avança; se o projeto as desabilitar, diga o que ativá-las pegaria.

    Concluído quando as verificações da biblioteca passam, nenhum cheiro abaixo se aplica (ou cada um que se aplica é uma escolha que você relatará), e os mantenedores da biblioteca reconheceriam o código como a biblioteca usada conforme o design.

  6. Quando o atrito persistir, primeiro adapte nosso design ao modelo da biblioteca; suas restrições frequentemente codificam uma lição (regras de determinismo de um mecanismo de fluxo de trabalho, mascaramento de dados de um cliente GraphQL). Em seguida, revisite o passo 4. Trabalhe contra a biblioteca apenas com o acordo do usuário, nomeando o comportamento não documentado no qual você confia na proposta e em um comentário no workaround. Um conflito entre o modelo e um requisito de produto é uma decisão do usuário.

Cheiros: lutando contra a biblioteca

Cada um o envia de volta ao passo 4. Classifique pelo que a biblioteca existe para fornecer: uma garantia derrotada supera todo o resto, mesmo quando nada está quebrado hoje, e uma regra da casa que codifica o modelo assume a gravidade do modelo.

  • Garantia derrotada: código gerado usado fora do módulo para o qual foi gerado (tipos de fragmento de outro componente), leitura de dados mascarados de outro módulo, um fragmento ou esquema compartilhado entre chamadores não relacionados, não determinismo dentro de um fluxo de trabalho determinístico. Eles passam na verificação de tipos silenciosamente, então procure por eles deliberadamente.
  • Casts ou supressões de verificador de tipos (as, any, @ts-expect-error, # type: ignore) onde nosso código encontra os tipos da biblioteca.
  • API privada: caminhos internos (pkg/dist/…, pkg._internal), nomes com sublinhado, exportações não documentadas, casts em campos privados de um objeto da biblioteca, comportamento encontrado apenas no código-fonte. Uma API instável ou experimental é documentada, mas fora do semver: use-a quando os documentos a recomendarem aqui, e diga isso.
  • Um patch que altera o comportamento da biblioteca (patch do gerenciador de pacotes, monkey-patching, fork vendido). Um patch que a faz fazer o que seus documentos já prometem é uma correção de bug e a ação correta: mantenha-o focado na correção e vincule o problema upstream.
  • Estado duplicado: uma segunda fonte de verdade para algo que a biblioteca possui, como um cache GraphQL espelhado no estado da store ou contagens de repetição que o framework já rastreia.
  • Temporizadores, flags ou cadeias de efeitos que executam código "após" a biblioteca, onde ela oferece um callback, evento ou hook.
  • Um padrão substituído em todo ponto de chamada, ou um wrapper que desfaz um comportamento em toda chamada.
  • Um wrapper raso que basicamente renomeia a API que encapsula. Aplique o teste de exclusão: se excluí-lo apenas move suas chamadas de volta para a biblioteca, ele não está valendo seu custo.
  • Parte de um recurso da biblioteca reconstruída porque o todo parecia mais do que você precisava.

Cheiros: subutilizando a biblioteca

O código funciona na API pública, mas uma funcionalidade construída para este caso o tornaria mais curto ou mais declarativo. Para encontrá-la, leia o tipo de cada objeto de opções que você passa e o guia da biblioteca para o problema do passo 1.

  • Várias chamadas fazendo uma operação: find-then-create onde há um upsert, escritas em loop onde há uma API em lote.
  • Código cola remodelando a saída, onde a consulta ou hook aceita uma opção de seleção ou projeção.
  • Estado que a biblioteca rastreia, reconstruído manualmente: flags de carregamento, pendente, sujo ou repetição.
  • As mesmas opções em todo ponto de chamada, onde há padrões, configuração compartilhada, um tema ou uma fábrica.
  • Código imperativo para algo que a biblioteca permite declarar: um esquema, uma variante, uma relação, uma política.

A proporção funciona nos dois sentidos: quando algumas linhas claras de código simples fazem o trabalho, o código simples é idiomático.

Revisando, auditando, adicionando e atualizando

  • Revisando a alteração de outra pessoa: leia REVIEWING.md.
  • Auditando o uso de uma dependência em uma base de código: leia AUDITING.md.
  • Adicionando um pacote, ou atualizando uma dependência ou o runtime: leia UPGRADING.md primeiro.
  • Encontrando, escrevendo ou atualizando a orientação do projeto para uma dependência: leia GUIDANCE.md.

Responda: os recursos da biblioteca que carregam o comportamento que você não escreveu; para código de propósito geral que você escreveu, o que você verificou e por que nada se encaixou; cada dependência que você ignorou e a parte de seu modelo que não correspondia; e cada cheiro que você manteve, com o motivo. Quando você aprendeu algo duradouro sobre a dependência, adicione a orientação que propõe, conforme GUIDANCE.md.

Habilidades Relacionadas