![Search icon](https://hackernoon.imgix.net/search-new.png?w=19&h=19)
Os acordos são uma parte essencial do desenvolvimento de software. Eles reduzem os custos de desenvolvimento e facilitam a vida dos desenvolvedores. Mas há um problema - eles geralmente complicam as coisas porque não são devidamente documentados e transmitidos à equipe de boca em boca, como velhos contos de fadas. Enquanto se espalha, os acordos mudam. De repente, novos detalhes aparecem e os antigos desaparecem. No final, cada membro da equipe tem sua própria imagem de acordo na cabeça, e mesmo essa imagem às vezes desaparece.
Pior ainda - quando as equipes começam a documentar esses acordos, eles o fazem de forma aleatória e muitas vezes criam uma confusão de documentos frouxamente acoplados, metade dos quais nem mesmo está atualizado.
Neste artigo, vou lhe dizer a maneira correta de documentar os acordos, para que eles possam ajudá-lo.
Então, como podemos tornar os acordos úteis? Não só temos que documentá-los, mas também fazê-lo para que:
eram fáceis de usar;
seguir esses acordos exigia um esforço mínimo;
seria fácil entender se esses acordos ainda são válidos;
seria fácil entender por que esses acordos existem;
idealmente - eles foram automatizados.
Pode-se chegar a muitas maneiras de classificar os acordos. Vou dividi-los por seu nível de abstração:
Acordos em diferentes níveis requerem diferentes formas de documentá-los e trazem diferentes benefícios. Vamos dar uma olhada em cada nível.
O objetivo desses acordos é tornar o código uniforme, abrangente e legível. aqui estão alguns exemplos:
Usamos aspas duplas em vez de simples.
Não chamamos ENV diretamente do código, exceto na classe Config
, onde agrupamos essas chamadas em métodos.
Os objetos de serviço têm o pós-fixo Service
e uma call
de método público.
Esses tipos de acordos são criados para diminuir a carga cognitiva do leitor e ajudá-lo a se acostumar com códigos desconhecidos mais rapidamente. Como Martin disse, o código é lido até 10 vezes mais do que escrito.
Apesar da sua opinião sobre o framework Ruby on Rails - ele tem uma convention over configuration
em seu núcleo, que permite que qualquer desenvolvedor Rails abra o projeto de outra pessoa e navegue imediatamente muito bem.
Então, como documentar essas convenções? Ferramenta Linter! Se não houver uma regra de linter adequada, escreva seu próprio lint. Quase todo linter permite que você faça isso: aqui está um exemplo em linguagem Go e aqui está para Ruby .
O uso do linter para tais convenções traz três benefícios:
Não há necessidade de um desenvolvedor pensar sobre eles - o linter destacará todos os erros e, muitas vezes, até os corrigirá para você.
Se você usar revisões de código em sua equipe - você libera seus revisores de pensar sobre essas coisas e dá a eles mais tempo para olhar para coisas mais importantes.
O desenvolvedor verá um problema logo no início do ciclo de desenvolvimento, então ele o corrigirá imediatamente sem perder tempo para retornar ao contexto posteriormente. Fica mais barato manter o acordo.
Mais um bônus: escrever uma nova regra linter é um excelente treinamento para um desenvolvedor júnior. Ao concluir esta tarefa, ele aprenderá muito sobre análise de código e construção de AST e entenderá a linguagem mais profundamente.
Este é um tipo de acordo de nível superior que visa tornar sua arquitetura pensativa, coerente e uniforme. Alguns exemplos:
Usamos o Python para escrever serviços regulares e Elixir nas partes de alta carga do sistema.
O back-end retorna erros no formato descrito.
Cada serviço é necessário para enviar métricas no prometheus, no endpoint /metrics
, a porta para envio de métricas é configurada pela variável de ambiente PROMETHEUS_PORT
.
Tais acordos não apenas reduzem a carga cognitiva, mas também resolvem mais três problemas:
Reduzir custos operacionais. Se os serviços forem iniciados da mesma forma, com o mesmo formato de logs, publicando as mesmas métricas, será muito mais fácil manter o serviço e lidar com os incidentes.
Reduzir custos de projeto. O desenvolvedor não precisa projetar a arquitetura do zero toda vez - você pensou com antecedência, e agora ele precisa projetar apenas uma funcionalidade ou serviço específico, sem se preocupar com coisas básicas.
Reduza os custos de comunicação. Se a resposta do servidor ou o formato do evento no Kafka for predeterminado, os desenvolvedores não precisam discutir sua interação a cada vez; em vez disso, eles podem simplesmente consultar a convenção.
Esses acordos são mais complexos e prefiro resolvê-los em duas etapas.
Etapa 1 - Descrever
O Architecture Decision Record (ADR) é uma ferramenta para documentar tais acordos. Seu charme é que ele captura metainformações junto com um acordo: por que tal acordo foi adotado; quais alternativas foram discutidas; quando foi revisado pela última vez; o acordo ainda é válido?
Isso permite que o novo membro da equipe entenda os motivos das decisões tomadas e não pergunte às pessoas sobre isso.
ADR consiste em vários blocos principais:
Que problema o acordo resolve?
Quais opções para resolver o problema foram consideradas e quais foram seus prós e contras?
Qual opção foi escolhida no final?
Pode haver blocos adicionais - por exemplo, cálculo de custos de implementação.
É mais conveniente manter o ADR em um sistema onde se pode ver o histórico de mudanças e discussões. Minha escolha é Github e Notion, cada um com seus prós e contras. A vantagem do Github é que ele possui uma ferramenta de revisão e um histórico de versões pronto para uso. O Notion pode ser uma boa solução devido à conveniência de trabalhar com bancos de dados e tags. E também - não desenvolvedores podem lidar com isso facilmente.
Se você deseja começar com o ADR, recomendo consultar o repositório , onde você pode encontrar diferentes modelos de ADR e exemplos de como usá-los.
Etapa 2 - Automatizar
Os ADRs são mais desafiadores de automatizar do que as convenções em nível de código: os linters de design ainda não foram inventados (que pena!). No entanto, é possível automatizá-los parcialmente, dependendo do tipo de contrato.
Crie e atualize modelos de serviço para acordos sobre idiomas, bibliotecas e serviços de incorporação na infraestrutura. Então, o desenvolvedor não escreverá novos serviços do zero, mas sim copiará do modelo e receberá imediatamente o Dockerfile configurado, publicação de métricas, etc.
Da mesma forma, você pode criar geradores de classe dentro de um aplicativo. Suponha que você tenha concordado com várias camadas de aplicativo (controlador => formulário => objeto de serviço). Nesse caso, você pode fazer um simples comando de console que irá gerar todas as camadas para um novo recurso de uma só vez.
Se você concordou com alguns princípios que não podem ser automatizados dessa maneira, pode organizar listas de verificação que são adicionadas automaticamente a uma solicitação de mesclagem ou a uma tarefa no rastreador; assim, o desenvolvedor pode passar rapidamente por eles antes de passar a tarefa adiante.
Existem muitos acordos para processos em cada empresa, por exemplo:
Descrição de como funciona a contratação na empresa.
Descrição do processo de lançamento da versão.
Requisito para revisões de projeto para grandes tarefas.
Conduzir uma reunião de equipe duas vezes por semana com uma discussão sobre as tarefas atuais e os obstáculos.
Até recentemente, não pensava em documentar esses acordos, embora afetem significativamente o sucesso da empresa. A documentação desses acordos não só traz benefícios dos tipos mencionados acima, mas também permite racionalizar os processos, transferi-los para o plano visível e pensar em sua conveniência.
Tive a ideia de . Ele propôs uma ferramenta semelhante ao ADR - Process Decision Record (PDR). A única diferença é que, em vez de decisões arquitetônicas, ele descreve decisões sobre processos. Além disso, ele sugeriu colocar uma "data de repensar" em cada PDR - uma data em que você volte ao documento para ver se ele ainda resolve seus problemas da melhor forma, n meses após a adoção (aliás, o mesmo pode ser feito com ADR).
Quanto à automação, há pouco que você pode fazer. Você pode automatizar alguns processos configurando um fluxo de trabalho no Jira, definindo lembretes para reuniões ou criando um bot que prepara automaticamente uma apresentação dos resultados da semana (eu fiz isso, porém, em uma empresa estrangeira).
Mas muitas vezes você não pode realmente automatizar processos, e seu principal objetivo é torná-los mais fáceis de seguir do que não seguir. No entanto, documentar os acordos ainda será útil, mesmo que seus processos já sejam fáceis de seguir - a formalização e a racionalização permitirão que você os melhore.
A documentação e a automação subsequente são benéficas: o tempo gasto no desenvolvimento diminui, os aplicativos tornam-se mais suportáveis e os processos tornam-se mais inteligentes.
Pode-se pensar que tudo isso é burocracia desnecessária porque "somos bons - podemos desenvolver código sem ela". Mas, na verdade, os acordos economizarão quantidades substanciais de tempo e dinheiro e protegerão as células nervosas dos funcionários. Claro, você não precisa negociar de forma absoluta e rejeitar qualquer coisa que vá contra os acordos - isso pode ser um sinal de que o acordo precisa ser atualizado ou que você não pensou inicialmente em alguns de seus aspectos.
Se você ainda não começou a documentar os acordos em sua equipe, passe dos níveis de abstração mais baixos para os mais altos: comece pelos acordos no nível do código, depois no nível da arquitetura e só então lide com o nível dos processos. A documentação de acordos é um hábito a ser desenvolvido em sua equipe, e começar com conceitos menos abstratos é muito mais fácil.
Além disso, nem todos os tipos são descritos no artigo. Por exemplo, você pode documentar o contrato de design como componentes de biblioteca.
Cada novo tipo de acordo passa pelas mesmas três etapas:
Descubra como documentá-lo.
Descubra como automatizá-lo.
Com o passar do tempo, garanta que ele economize mais recursos do que o necessário para mantê-lo.
E o último. Durante o processo de documentação, pode-se verificar que alguns dos acordos existentes aparentemente não se justificam por nada, desperdiçam o tempo de sua equipe e geralmente são prejudiciais, mas você já está acostumado com eles. Nesse caso, você precisa superar a barreira do hábito na cabeça da equipe e convencê-la de que a rejeição de acordos às vezes é mais importante do que aceitá-los. Mas essa é uma história totalmente diferente.
Publicado também aqui .