Na hora de projetar sistemas de software, a recomendação é fazer a coisa mais simples que possa funcionar. Essa abordagem pode ser aplicada em diversas situações, desde a correção de bugs até a manutenção de sistemas existentes e a arquitetura de novos projetos.
Engenheiros costumam buscar criar sistemas ideais, bem estruturados e escaláveis. No entanto, o autor acredita que essa estratégia é equivocada. Em vez disso, é fundamental entender profundamente o sistema atual e, a partir daí, optar pela solução mais simples.
A simplicidade, muitas vezes, pode parecer decepcionante. A construção de sistemas envolve diversos componentes, como servidores de aplicativos, proxies e bancos de dados, e é natural que engenheiros menos experientes queiram utilizar todas essas ferramentas. Contudo, a verdadeira maestria muitas vezes reside em saber quando utilizar menos. A analogia com filmes de artes marciais ilustra bem essa ideia: o novato é um turbilhão de movimentos, enquanto o mestre é mais contido e eficiente.
Um bom exemplo de design de software simples é o Unicorn, que entrega garantias essenciais em um servidor web utilizando primitivos do Unix. Da mesma forma, a API REST padrão do Rails é uma implementação que atende às necessidades de um aplicativo CRUD de maneira descomplicada. Embora esses exemplos não possam ser considerados impressionantes em termos de software, são notáveis em termos de design por seguirem o princípio da simplicidade.
Ao desenvolver uma aplicação em Golang, por exemplo, a implementação de um limite de taxa pode inicialmente sugerir a necessidade de um armazenamento persistente, como o Redis. Porém, antes de criar uma nova infraestrutura, é válido considerar se é possível manter esses dados na memória e avaliar se a perda de dados em uma reinicialização da aplicação é realmente um problema.
Entretanto, sempre optar pela simplicidade pode trazer três grandes desvantagens. Primeiro, ao não antecipar requisitos futuros, um sistema pode se tornar inflexível. Segundo, a definição de "simples" é subjetiva; e, por último, sistemas devem ser projetados para escalar, não apenas para funcionar no momento.
A ideia de que "fazer a coisa mais simples que pode funcionar" possa levar a sistemas bagunçados é um receio válido. Muitos projetos são marcados por gambiarras que, embora pareçam soluções fáceis, adicionam complexidade ao código. Encontrar a solução mais adequada requer uma compreensão abrangente do sistema.
Definir o que é simplicidade é um desafio, pois engenheiros frequentemente discordam sobre o que constitui um código simples. Um sistema considerado simples é aquele que possui menos "peças móveis" e interfaces claras entre seus componentes. Por exemplo, processos do Unix são mais simples que threads, pois não compartilham memória, resultando em uma arquitetura menos conectada.
Embora a opção de limitar a taxa de requisições na memória possa parecer mais simples, o uso do Redis pode oferecer garantias mais robustas em um ambiente distribuído. A escolha entre essas abordagens depende das necessidades específicas e do contexto em que se está operando.
É comum que engenheiros se preocupem com a escalabilidade desde o início do projeto. No entanto, o autor defende que essa obsessão pode resultar em engenharia irresponsável. Com frequência, é impossível prever como um sistema se comportará sob uma carga muito maior, e muitas vezes é mais eficaz preparar-se para um aumento moderado de tráfego.
Na prática, o desenvolvimento de software pode seguir dois caminhos: antecipar requisitos futuros e projetar o sistema ideal ou focar nas necessidades atuais e optar pela solução mais simples. Essa última abordagem é mais realista e prática.
Por fim, simplificar o design é crucial, especialmente à medida que a complexidade das interações entre funcionalidades aumenta. Uma arquitetura simples torna-se ainda mais valiosa quando as demandas de complexidade estão se esgotando.
Confira os últimos vídeos publicados no canal