O Castelo de Cartas
“A complex system that works is invariably found to have evolved from a simple system that worked. A complex system designed from scratch never works and cannot be patched up to make it work. You have to start over with a working simple system.”
-Gall's s Law
A realidade é que não criamos nada do zero.
Temos que usar ferramentas e sistemas criados por outras pessoas para fazer acontecer.
Ninguém faz seu próprio computador, sistema operacional ou browser. Temos que usar sistemas já prontos para fazer acontecer. O contrário é impossível.
Precisamos usar abstrações.
Abstrações no sentido de usar uma tecnologia para facilitar o surgimento de outra.
Isso faz com que qualquer aplicação usável hoje em dia tenha uma grande pirâmide de dependências e tecnologias abaixo dela.
Um grande castelo de cartas.
O problema é que isso exige confiança.
Você precisa confiar que a infraestrutura, tecnologia, dependências são estáveis o suficiente.
De forma simplificada - em uma aplicação que roda em cima do Spring Boot - há algo do tipo:
A estabilidade inicial da aplicação - sem envolver nenhuma variável externa - depende que:
- O Spring funcione
- O próprio Java e suas dependências funcionem
- A JVM funcione
- O Sistema operacional funcione
Imagine que queria desenvolver um sistema para controlar o estoque de uma loja - usando o Spring Boot mesmo.
Isso faz com que existam coisas que rodam fora do seu contexto inicial - longe de onde está criando o sistema de estoque.
E aí surge uma questão - é possível que problemas surjam fora de onde está trabalhando.
Se lembra da confiança? Ela é bastante necessária.
E como é possível desenvolver - pelo menos um pouco - de confiança? Somente descendo as camadas de abstração e tendo uma noção da stack em que tudo roda - do castelo de cartas.
Não me lembro exatamente de onde - mas uma vez li que é interessante ter ideia de pelo menos 3 camadas de abstração abaixo da qual você está trabalhando.
Creio que varia de contexto a contexto - mas de 3 a 4 parece ser um bom parâmetro.
No exemplo - seria descer até o nível de entender como Java funciona.
De bônus, seria legal descer mais um pouco e ter uma noção de como a JVM atua.
Rapidamente - com um sistema rodando no mundo real acima de tudo isso - uma lei invariável aparece:
A entropia.
1 - A entropia é inevitável
"Entropy is the supreme law of the Universe, which illustrates that systems tend toward disorder, chaos, and destruction on all planes of existence unless energy is put into the system."
-Dan Koe
Independente da estabilidade ou planejamento que dedique ao sistema - a entropia vai agir.
Versões irão mudar e depedências irão quebrar, é o ciclo contínuo.
Acontece que quanto mais confiança existe na stack - mais fácil é navegar.
E a entropia não age somente nas dependências - mas no seu sistema como um todo. É necessário constantemente exercer uma energia sob o sistema para garantir sua estabilidade.
Documentação, housekeeping de dependências, entre outros.
... E está tudo bem. É assim que o jogo funciona.
Ter uma leve ideia sobre o castelo de cartas em que sua aplicação roda já é uma grande ajuda.
2 - Não há Bala de Prata
Não há muita escapatória. Software é uma coisa complexa.
Como disse Fred Brooks em seu artigo "No Silver Bullet":
"The essence of a software entity is a construct of interlocking concepts: data sets, relationships among data items, algorithms, and invocations of functions. This essence is abstract, in that the conceptual construct is the same under many different representations. It is nonetheless highly precise and richly detailed.
I believe the hard part of building software to be the specification, design, and testing of this conceptual construct, not the labor of representing it and testing the fidelity of the representation. We still make syntax errors, to be sure; but they are fuzz compared to the conceptual errors in most systems."
Em outras palavras - a essência de um sistema é complexa.
Trabalhamos com ideias abstratas - muitas vezes que não são reais.
Pois é - se parar para pensar - o software é invisível.
Não há forma física - é uma junção de lógica, algoritmos e coisas conceitualizadas mentalmente.
Você não consegue tocar ou ver. Pode até diagramar - mas representações estáticas não fazem total juz à realidade. O comportamento real só aparece quando a aplicação é executada - e quando o mundo real age em cima.
Isso faz com que as coisas naturalmente sejam complicadas.
Porém, é possível previnir - em partes - alguns dos problemas.
3 - Housekeeping
Além de entender de 3 a 4 níveis de abstração, é necessário manter as dependências sob controle - na medida do possível.
Isso inclui uma rotina de atualizações - além de planejar onde e como incluir as dependências.
Por exemplo - na sua aplicação de estoque de loja, o módulo que verifica e mantém os dados de quantos produtos restam na prateleira é de alta importância - logo - acoplar ele com uma dependência que você não confia muito pode ser uma má ideia.
Algo como injeção de dependências pode ajudar aqui.
Agora - digamos que queira desenvolver uma interface para mostrar a descrição de cada produto no estoque - para controle interno - adicionar uma dependência que gerencia a listagem dos produtos pode não ser tão arriscado.
Vai de caso a caso.
E sempre se lembre que dependências muitas das vezes trazem outras dependências - as chamadas transitive dependencies.
Sempre que adicionar uma biblioteca, se lembre que:
... Essa mesma biblioteca pode depender de outra biblioteca, que depende de outra, e outra... E assim por diante.
Isso é um prato cheio para a entropia.
Afinal, imagina o tanto de versões e código não previsto adicionado a cada atualização. É complicado.
De qualquer jeito - vale lembrar:
- Entenda de 3 a 4 níveis de abstração abaixo do que você está atualmente.
- Faça housekeeping das dependências do projeto - constantemente.
- Desacople as dependências em pontos cruciais da aplicação.
- Cuidado com as transitive dependencies - dependências de dependências.
- Planeje - mapeie quais dependências você acredita que são um risco.
-Rapozo