Sistemas de software devem possuir baixo acoplamento e alta coesão. Desconhecido |
Um dos principais motivos para que times de engenharia de software sofram para evoluir sistemas é o acoplamento. Desconsiderar o acoplamento, tanto no planejamento da arquitetura como no dia a dia implementando novas funcionalidades é comprometer a manutenabilidade dos sistemas a longo prazo.
No decorrer do tempo, temos observado times de engenharia, bem intencionados, que tomam decisões que se revertem em custo para manter um software. Sem o entendimento, do queria “baixo acoplamento”, decisões que deveriam combater o acoplamento acabam trazendo mais dores ao longo do tempo para o software. Entender mais profundamente sobre acoplamento, resulta na formação de um time de engenharia com mais senioridade e que é capaz de compor melhor trade-offs das decisões sobre arquitetura de software.
Então, buscando reduzir as dores que o acoplamento pode trazer para um software, gostaríamos de trazer algumas reflexões que podem auxiliar os times de engenharia.
Acoplamento e testes
Uma vez compreendida a natureza do acoplamento eferente e aferente, é possível debater uma nova perspectiva sobre a pirâmide de testes (unidade, integração e end-2-end). Definir o percentual de cobertura de testes, bem como, o tipo de teste tende ser mais fácil quando olhamos para os componentes sob a perspectiva de acoplamento.
Componentes de software que possuem um alto acoplamento eferente, que dependem de outros componentes para executar seu trabalho, são naturalmente componentes “orquestradores”. Realizar testes de unidade, demandaria a escrita de mocks/stubs e outros, pois a qualidade interna destes componentes é determinada pelo acoplamento a outros componentes. Na prática, realizar testes de integração em componentes como command handlers, application services e/ou use cases, fazem mais sentido, pois o valor do teste justamente é a “integração” com outros componentes, ou seja, estamos “testando” o acoplamento dos componentes.
Agora, componentes de software que fornecem funcionalidade para outros componentes, ou seja, alto acoplamento aferente, normalmente são componentes mais coesos. Considerando essa natureza, faz todo o sentido ter um maior índice de cobertura de testes de unidade, pois a qualidade destes componentes impactam muitos outros. No dia a dia, estes componentes são normalmente classes dentro do domínio do software e fazem parte do “caminho crítico” para um processo de negócio.
Change coupling
No combate ao acoplamento, David J. Wheeler nos ensina que todo problema na ciência da computação pode ser resolvido por outro nível de indireção, exceto o problema de muitos níveis de indireção. Ou seja, introduzir abstrações normalmente é um caminho para mitigar o acoplamento entre componentes. Na mesma linha de pensamento, introduzir camadas (layers) na aplicação, ajuda a organizar os projetos e mitigar acoplamento entre as camadas.
Mas, ignorar as desvantagens que o excesso de abstrações pode trazer é uma armadilha perigosa. Um dos principais problemas é o “changing coupling”, custo que o acoplamento traz na alteração de uma funcionalidade. Esse custo é percebido principalmente quando, para uma simples alteração na aplicação, é necessário alterar muitas camadas, interfaces e classes.
Acoplamento e dívida técnica
Times de engenharia irão assumir dívidas técnicas ao passar do tempo, é fato. Pela nossa experiência, tais dívidas com frequência têm relação direta com acoplamento de componentes. Trazer métricas relacionadas ao acoplamento pode auxiliar a quantificar “juros” cobrados por uma dívida técnica, facilitando a priorização das mesmas.
Por exemplo, identificar o grau de instabilidade e abstração dos componentes pode trazer insights valiosos sobre o custo e risco de uma alteração em determinado componente. Tais métricas, são base para montarmos o gráfico de “main sequence” que nos traz quais componentes estão na “zona de desuso” e quais estão na “zona de dor”. Componentes que estão na zona de desuso, têm código tão abstrato que é difícil de manter. Já componentes que estão na zona de dor, têm um acoplamento aferente tão elevado que a alteração nestes componentes, costumam a ser complexas pelo efeito colateral em outros componentes.
Sabendo quais são os componentes que estão em cada uma destas zonas, aliado à frequência de alteração destes componentes, trazem um ótimo indicador para priorizar onde começar a pagar dívidas técnicas.
Considerações finais
Acoplamento é inevitável, então todo time de engenharia deveria conhecer mais sobre o assunto para uma convivência mais “pacifica”. Práticas de arquitetura de software auxiliam a monitorar e estabelecer estratégias para lidar com o acoplamento. No final do dia, compreender mais sobre acoplamento nos torna engenheiros melhores, pois entregamos software com testes mais adequados, que aumentam a qualidade, reduz a complexidade da solução, diminuindo o changing coupling e auxilia a identificar quais dívidas técnicas que causam mais dor.
Gostou destas dicas? Quais estratégias você utiliza para conviver com o acoplamento? Precisa de ajuda para combater o acoplamento?
Recentemente participei de um bate-papo com Elemar Júnior na série Eximia Talks, onde falamos bastante sobre acoplamento, assista agora: