Leis da Arquitetura de Software

Apesar de ser um assunto tremendamente amplo, existem algumas coisas que se provam verdadeiras em todo processo de desenvolver e manter software, dessa forma, existem duas leis que dizem respeito a arquitetura de software:

  1. Tudo é um trade-off;
  2. O porquê é mais importante que o como.

Essas são frases que você deve manter sempre em mente quando estiver desenvolvendo, visto que mesmo fora de um contexto de arquitetura de software, elas se demonstram verdadeiras muitas das vezes, sendo conceitos que você vai se deparar sempre quanto mais desenvolver software.

Lei Nº 1 - Tudo é um Trade-Off

Existe uma piada na comunidade de desenvolvimento que diz que a resposta para tudo é simplesmente "depende", e existe muito fundo de verdade por trás dela.

Quando a gente se anima em estudar as coisas, descobrir tópicos mais avançados, complexos, boas práticas ou simplesmente algo novo, temos uma tendência de achar que mais sempre é melhor.

Por exemplo, mesmo que você não entenda o significado desses termos ainda, o que parece melhor? Um sistema feito com MVC com deploy num servidor só, ou um sistema feito com Clean Architecture, DDD, CQRS, Event Sourcing, com deploy distribuído na nuvem via Microsserviços?

Claramente o segundo é "melhor", mas o que significa "melhor"? Isso depende do contexto, se a gente tiver falando puramente de mérito técnico, óbvio que, de fato, ele vai ser melhor, ssas práticas representam o que há de mais avançado hoje, tanto na teoria quanto na prática, não existe comparação com MVC que é no máximo uma arquitetura bem popular.

Entretanto, projetos de software não existem num vácuo teórico, se a gente pudesse simplesmente fazer tudo da melhor forma ideal mesmo, a gente não teria que pagar boleto, ou se preocupar em quanto tempo aquilo vai sair, a gente só teria que considerar conhecimento infinito, tempo infinito, e dinheiro infinito, aí é fácil dizer que algo é necessariamente melhor.

O que essa lei nos ensina é que mesmo que algo seja melhor por um critério arbitrário, mesmo que um bem importante como o mérito técnico, a melhor resposta é "depende", pois não existe almoço grátis, sempre vai existir prós e contras de qualquer decisão tomada.

Pode acontecer de ser um contra quase que irrelevante, tipo o sistema começar a dar pau se tiver mais que 10 bilhões de usuários simultâneos, só que o seu caso é de um sistema para ser usado na igreja local que tem no máximo uns 200 membros, muito provavelmente isso nunca vai ser um problema então.

Também pode ser que os prós sejam vários, mas não façam tanta diferença assim no seu caso, enquanto os contras pesam muito.

Voltando no nosso exemplo original, a primeira vista, a segunda solução pode até parecer melhor, só que e se o nosso sistema for só um CRUD simples que vai ser usado por umas 10 pessoas, implementar DDD não vai te trazer benefício quase que nenhum, pois não existe domínio rico ali para se trabalhar em cima, todas as outras letrinhas citadas só vão adicionar muita complexidade em cima, o que vai fazer entregar esse sistema demorar muito mais, os custos de infraestrutura vão ser altíssimos por conta do modelo de microsserviços.

Enquanto simplesmente fazer um MVC da massa, seria rápido, prático, e barato. Pode até ser que ele não escale tão bem caso o sistema venha a ficar mais complexo, não seja tão fácil de testar, ou até mesmo não tenha a performance mais impressionante do mundo, mas compensa todo o trabalho hérculeo que você teria, além dos custos gigantescos para operar uma solução técnica mais robusta? Claro que não.

Essa reflexão toda nos leva a um corolário dessa lei que é:

Se você acha que algo não é um trade-off, o mais provável é que você só não identificou o trade-off daquilo ainda.

No nosso exemplo, a gente poderia ter caído nisso ao se manter a mente fechada só na questão técnica, nisso achando que mais complexo seria necessariamente melhor, mas a falha ali seria que nós não avaliamos o contexto todo, e quando se pensa duma perspectiva de gerenciamento de projetos, fica claro qual o trade-off daquela decisão.

Lei Nº 2 - O porquê é mais importante que o como

Ainda nessa questão que contexto importa, e importa muito! A segunda lei é importante pois não dá para avaliar um sistema só olhando a planta produzida para ele, por exemplo lendo diagramas, ou analisando a estrutura de um repositório com o código do projeto.

Você pode até inferir muitas coisas com isso, mas no final das contas, a informação que será obtida vai ser como o problema foi resolvido, mas não porquê essas foram as decisões de design tomadas.

Novamente no nosso exemplo original, se a gente só olhasse uns diagramas mostrando que o sistema era feito em MVC, como pessoas técnicas, poderíamos nos perguntar: mas por que não usar uma arquitetura mais robusta?

Não teríamos como responder isso, pois só temos a informação de qual foi a decisão tomada, mas não o que motivou ela, sendo assim, em última análise, não teríamos acesso aos trade-offs que vimos serem tão importantes na lei anterior.

Nisso, se nós simplesmente seguissemos o que foi feito sem entender os porquês envolvidos, seria como andar no escuro, não conseguiríamos tomar boas decisões, pois não estão embasadas adequadamente.

Para finalizar, uma última lição que podemos aprender com essa lei é que visto que somos seres humanos falhos, sem acesso a todas as informações em todos os momentos, e muito menos sem a capacidade de prever o futuro, o nosso trabalho seja como arquitetos, engenheiros, ou só desenvolvedores mesmo é tomar decisões sabendo dos trade-offs, e torcer para que elas sejam as melhores decisões possíveis, mas certeza a gente nunca vai ter na hora, só no futuro quando os resultados das nossas decisões vierem nos cobrar a conta.

Por isso se deriva essa lei, seja qual for a decisão tomada, se mostrando ela boa ou ruim no futuro, o importante é justificar bem a decisão tomada, independente de qual for ela, visto que o porquê é mais importante que o como.

Arquitetura de software não é sobre acertar sempre, mas sobre tomar decisões conscientes e defendê-las com clareza — mesmo que o tempo revele que existia uma escolha melhor.

Extra: Lei de Conway

Eu sei que eu disse que existiam só duas leis, mas uma terceira lei que é mais sobre relações sócio-tecnologicas do que sobre arquitetura em si seria a Lei de Conway, por isso ela aparece aqui como um extra.

Basicamente a Lei de Conway diz que:

Qualquer organização que projeta um sistema (definido de forma ampla) produzirá um design cuja estrutura é uma cópia da estrutura de comunicação da organização.

~ Melvin Conway

Isso tem algumas implicações interessantes que se relacionam com as leis que vimos antes, por exemplo reforçar o ponto que nem sempre o que é "melhor" não é o melhor.

No futuro, iremos falar sobre estilos arquiteturais principalmente sobre desenvolvimento em camadas e sistemas distribuídos, mas existe uma enorme discussão e polêmica quanto ao que seria "melhor", visto que ambos são estilos muito populares.

Tecnicamente falando, um sistema com estrutura distribuida é melhor, entretanto, se nós aplicarmos a Lei de Conway numa organização pequena e com um time só, logo veremos que isso é um tiro no pé, visto que um time só teria que lidar com múltiplas aplicações independentes, ao invés de uma só bem grande que lida com tudo num lugar só.

Da mesma forma, dividir tudo puramento pelo mérito técnico (banco de dados num lugar, tela no outro, etc) acaba sendo um pesadelo em empresas gigantes, onde o comum é ter uma estrutura distribuída com diversos times cada um sendo dono de um produto, nesses cenários arquiteturas distribuídas brilham, por refletirem no software como essas empresas funcionam na vida real.

Logo, apesar de ser, a princípio, ela não parecer ter muito a ver com desenvolvimento de software, na verdade ela tem várias implicações bem sérias na arquitetura, por exemplo de que a organização e comunicação do(s) time(s) influencia no design e arquitetura do sistema, e se o software tiver uma estrutura e o time outra, ele naturalmente vai ser difícil de mudar/evoluir.