Por que a arquitetura do meu software deu errado?

Atualmente, muitos desenvolvedores estão dando um pouco mais de relevância para algo que não era tão levado em consideração há pouco tempo atrás: a arquitetura do código. Muitas profissionais de TI estão dando cada vez mais valor para a qualidade do código que é produzido, ao invés de simplesmente se preocuparem em “fazer funcionar”. E isso é excelente! =)

Agora, também é notório que muitas pessoas estão aplicando a arquitetura no código que elas constroem de maneira equivocada, quer seja porque aquela arquitetura não era muito adequada à situação, ou porque houve um overhead arquitetural, ou por falta de preocupação com outros fatores além da arquitetura utilizada no código ou até mesmo pela simples falta de domínio. E qual é o resultado disso? Softwares ruins, difíceis de testar e até mesmo com baixa legibilidade, indo completamente contra tudo que arquitetura de software tenta alcançar.

Por que será que esse tipo de coisa acaba acontecendo? Vamos ver algumas possíveis razões.

C# (C Sharp) - APIs REST com ASP.NET Web API
Curso de C# (C Sharp) - APIs REST com ASP.NET Web API
CONHEÇA O CURSO
Esquecimento de que produzir um software não é simplesmente escrever código

Alguns desenvolvedores dão muita atenção a somente… codificar! Porém, produzir um software não consiste somente em produzir código. Muitos se esquecem que existe a parte de testes de software, a parte de configuração do ambiente de execução do software, a parte de validação do funcionamento do software, entre vários outros fatores. Se você vai, por exemplo, construir uma aplicação web, você ou outra pessoa deverão em algum momento configurar servidores de aplicação, firewalls, permissões de acesso e outras coisas. Tudo isso, no final, impacta até mesmo na maneira como você irá realizar a codificação da sua aplicação. O mesmo ocorre com relação aos testes: se você quiser criar um projeto que possa ser testado de verdade, você precisará se preocupar com a maneira como você produz seu código, para que seja possível realizar os testes até mesmo nos menores níveis (como os testes unitários). Também podemos considerar conceitos como granularidade e até mesmo complexidade de algoritmos.

Outro exemplo: você precisa criar um software de missão crítica que irá realizar intercâmbio de informações com o meio externo. Será que aqui, ao invés de utilizar o padrão JSON para fazer este intercâmbio de informações, não caberia o bom e velho SOAP? Perceba que até mesmo esse tipo de situação pode impactar na maneira como você vai montar a arquitetura de seu software, impactando de maneira direta até mesmo na codificação.

Aplicação incorreta de conceitos

Isso é algo comum se tratando de arquitetura e pode até ser “mal de desenvolvedor”: quando aprendemos algo novo, queremos logo sair aplicando em nossos projetos. O grande problema disso é que é bem complicado conseguirmos aplicar um conceito novo em um projeto que tenha uma certa complexidade e da maneira correta, assim, “logo de cara”. Além disso, geralmente nem avaliamos se a situação com a qual nos deparamos é realmente a ideal para aplicar aquele novo conceito que estamos loucos para mostrar para todo mundo que já “dominamos”, quer seja esse conceito uma nova arquitetura (como DDD, por exemplo) ou mesmo algum design pattern. O resultado disso: um código conceitualmente incorreto, com várias falhas de implementação, de manutenção e testes muito complicados e que ninguém sente orgulho em dizer que participou da respectiva codificação. O mais complicado dessa situação: o prazo do projeto vai fatalmente apertar e no final, para cumprimento do prazo, você estará apelando para “gambiarras” que vão contra a própria arquitetura que você tinha imaginado inicialmente.

Eu já tive esse tipo de experiência na pele… Por várias vezes precisei trabalhar em um projeto em que a impressão era que o responsável simplesmente resolveu aplicar todos os design patterns existentes! No final, o que era para facilitar a manutenção e tornar o código mais legível, causou o efeito completamente contrário. O código tinha um custo muito alto de manutenção e era muito mais complexo do que deveria ser. E por que isso aconteceu? Porque vários conceitos de design patterns que estavam sendo utilizados foram aplicados de maneira completamente equivocada. O efeito foi justamente o contrário do que era esperado. Faltou talvez um pouco de conhecimento e bom senso a quem desenvolveu a arquitetura do projeto inicialmente.

É comum aprendermos conceitos de arquitetura de código e querermos aplicá-los de maneira imediata em nossos projetos. Mas, um mantra que acaba ficando é: domine-o primeiro. Estude-o bastante, aplique-o em projetos menores e de menor relevância inicialmente, para que você possa de fato dominar o que você acabou de aprender. Depois, avalie com frieza se realmente é necessário aplicar o conceito em questão. Não adianta você aplicar uma série de conceitos em um software que não exige um código tão complexo. É como se você estivesse “matando uma mosca com um tiro de bazuca”. Não é porque você acabou de aprender algo que você precisa aplicar a novidade em todos os seus projetos e em todas as situações. Se caso for viável e prudente a aplicação de um conceito em seu código, utilize o ciclo de refactoring para realizar esta alteração! =)

Falta de alinhamento de conhecimento entre a equipe

Isso também, infelizmente, é muito comum… Dificilmente você irá desenvolver um software sozinho: você estará inserido em uma equipe. E isso fatalmente irá causar um desalinhamento de conhecimento entre os componentes da equipe, afinal, é normal sabermos mais que alguém e alguém saber mais que a gente. E aqui está uma grande armadilha.

É importante definir um estilo de arquitetura que esteja congruente com o nível de conhecimento da equipe.

Por exemplo: existe um padrão arquitetural que está ficando cada vez mais popular, que é o DDD (Domain Driven Design). O grande ponto é que, para um desenvolvedor conseguir entender e aplicar corretamente os conceitos previstos pelo DDD, ele tem que ter um certo domínio de, no mínimo, orientação a objetos… A chance de as coisas darem erradas se você tentar codificar um projeto baseado no DDD com uma equipe mais iniciante ou que não conheça muito bem orientação a objetos é muito grande. Neste caso, a atitude mais sensata é utilizar um estilo arquitetural mais simples, como por exemplo uma arquitetura baseada em domínios anêmicos (por mais que esta deturpe alguns conceitos de orientação a objetos, rs).

Isso não quer dizer que você não deve estimular a equipe a aprender novos padrões arquiteturais e expandir os conhecimentos, muito pelo contrário. O grande ponto é que isso não deve ser feito com o projeto que está sendo desenvolvido. Ao invés disso, a criação de grupos de estudos paralelos ao desenvolvimento do projeto é, por exemplo, uma excelente idéia. Pode ser que a equipe não possa aplicar a arquitetura desejada no projeto atual, mas certamente estará preparada e entenderá a necessidade de se aplicar uma arquitetura mais elaborada nos próximos projetos.

Muitas vezes, o simples é melhor

De nada adianta pensarmos em uma arquitetura super mirabolante se ela não puder ser implementada com sucesso, ou se ela se demonstrar complexa demais para a situação a qual ela tenta resolver. Aqui, cabe o velho ditado: “menos é mais”. Código não tem que ser algo complexo de se entender e complicado de lidar. Muito pelo contrário: quando mais simples, melhor vai ser a arquitetura do código, desde que a arquitetura consiga atender os requisitos do projeto.

Aqui, cabe um exemplo muito legal: o do StackOverflow. Esse site que certamente você já visitou e usou se você trabalha com desenvolvimento possui uma arquitetura super simples. E nem por isso ele deixa de atender milhões de usuários espalhados pelo mundo. Não é porque o projeto é enorme que sua arquitetura precisa ser a mais complexa do mundo.

O StackOverflow é construído em cima de .NET, SQL Server e Redis. Para que você tenha idéia, nem mesmo frameworks ORM mirabolantes eles utilizam: eles apelam para o velho e eficiente ADO.NET (em algumas partes com o auxílio do Dapper). Se você é desenvolvedor .NET, sabe que aqui não temos nada maluco ou complexo do ponto de vista técnico. Só que funciona muito bem! A arquitetura é simples, direta e eficiente. Não foi necessário nenhum tipo de complicação para fazer o StackOverflow funcionar! =)

Se estiver curioso sobre a arquitetura do StackOverflow, você pode ver maiores detalhes neste link aqui.

Preciosismo do responsável pela arquitetura

Como geralmente não existe um “cargo” específico para arquiteto de software, geralmente o desenvolvedor com mais experiência e conhecimento acaba exercendo este papel. E isso é muito bom, porque ele terá uma oportunidade muito legal para repassar todo seu conhecimento e experiência para o restante da equipe ao definir a arquitetura dos projetos que a mesma vai desempenhar. O grande problema é quando essa pessoa se fecha em seus conhecimentos, se indispondo a ouvir opiniões da equipe ou a aprender coisas novas.

É importante sempre lembrarmos que a área de desenvolvimento de software é muito dinâmica. E isso logicamente ocorre também com arquitetura de software. É fácil percebermos isso: há pouco tempo atrás, era o paradigma procedural quem imperava. Aí, menos tempo atrás ainda, veio o paradigma orientado a objeto. Hoje, temos uma explosão do paradigma funcional, por causa da popularização do JavaScript e de outras linguagens funcionais, como o F#. As coisas estão sempre mudando. Novos conceitos estão sempre surgindo, e continuarão a surgir. Conceitos antigos caem em desuso, e continuarão caindo. Essa mutabilidade é que dá a graça e faz a área de desenvolvimento de software em geral ser tão desafiadora.

Quem assume o papel de arquiteto precisa estar antenado nestas mudanças. Na verdade, qualquer profissional de TI precisa sempre estar a par dessas novidades. Mas, no caso do arquiteto, isso cai mais na situação de que ele precisa ter consciência de que o que ele pensa e fala não é uma verdade absoluta, pois as coisas estão sempre mudando. Preciosismo em arquitetura de software nunca será bem-vindo.

É complicado falar de “certo” e “errado” em arquitetura de software

É importante salientar que este post não tem a menor intenção de ser um “juiz” e dizer que tudo que você faz hoje está “certo” ou “errado” com relação a arquitetura de software. Eu penso que, tratando-se de arquitetura, isso não existe. Têm-se o “melhor” ou “mais aplicável” e o “menos melhor” ou “menos aplicável”. E esse enquadramento pode depender de uma série de fatores externos, como o nível de conhecimento da equipe, plataforma a ser utilizada e até mesmo o tempo disponível para execução do projeto. É aí que entra o conhecimento e até mesmo um certo feeling por parte do responsável por definir a arquitetura do projeto de software em questão. Também é necessário lembrar que, mais importante que aplicar um conceito arquitetural todo rebuscado em um projeto, querendo ou não, o mais importante é entregá-lo. É para isso que existem os ciclos de refactoring.

Os pontos deste post tratam apenas de minha opinião pessoal. Posso estar certo ou errado… Você pode concordar comigo ou não… E é justamente isso que torna tão legal conversar e discutir sobre arquitetura de software. o/

Concorda com os pontos deste post? Discorda? Quer acrescentar alguma coisa? Tem uma opinião diferente sobre algum ponto? Ou ainda tem uma experiência que gostaria de compartilhar? “Bora” conversar aí embaixo nos comentários! 😀

Até o próximo post!

Nginx - Fundamentos
Curso de Nginx - Fundamentos
CONHEÇA O CURSO
Deixe seu comentário

Líder de Conteúdo/Inovação. Pós-graduado em Projeto e Desenvolvimento de Aplicações Web. Certificado Microsoft MCSD (Web).