Cuidado com rigidez em software
Você precisa ter muito cuidado com rigidez.
Veja só.
Começa quando queremos resolver algum problema.
Passamos semanas, meses - desenhando e planejando a solução perfeita.
Páginas e páginas de documentação, de ideias.
E aí acontece!
Chegamos na arquitetura imbatível - usando as melhores técnicas, melhores práticas.
Bonito, não?
... Até começarmos a implementar.
Pessoas reais começam a usar sua solução.
E as pessoas são exigentes.
Novos requisitos, pedidos.
O desenho perfeito começa a mudar - só que a solução já está no ar e funcionando.
Como vou mudar o motor de um carro que está andando?
O castelo de cartas começa a cair.
E agora?
... Agora precisamos de uma solução nova - reescrever tudo.
E de novo, depois de novo.
E assim vai.
...
O problema é que tentamos congelar um mundo dinâmico.
Temos a impressão que conseguimos pegar uma "foto" momentânea da realidade e usar ela como base para resolver um problema real.
Toneladas de papelada e documentação, código, em cima de uma foto.
Isso é perigoso - muito. E caro.
Um frame de algo que é na realidade um filme - com atores, plot - e tudo mais.
E pior - é um frame do filme mais aleatório que existe.
A realidade.
Em um mundo perfeito é possível seguir uma visão matemática, geométrica, onde a ação e reação fazem sentido subjetivo e são calculáveis.
E essa é a visão clássica.
É, também - a visão mais natural de ensinar. É a forma que qualquer engenharia funciona.
... E faz sentido. Se eu somo 3 com 3, eu tenho 6, não? É assim que funciona.
Porém - com software - criamos uma camada em cima da realidade, uma abstração em cima de algo real e dinâmico - com suas próprias regras.
É imprevisível.
Logo, é necessário adotar uma visão de artesão.
Um artesão adapta, flexibiliza. Aprende pelo uso.
Usa sua criatividade para se adaptar ao contexto.
Quase como um poeta, um escritor.
Ele cria e adapta palavras e coisas em um mundo imaginário, desacoplado da realidade. Sem muitos limites.
Deixa eu te contar uma história.
Wittgenstein
Era uma vez um filósofo chamado Wittgenstein.
Tinha uma ideia simples:
A linguagem é como um mapa lógico do mundo.
Cada palavra aponta para uma coisa.
Cada frase espelha um fato do mundo real.
Se organizarmos bem as palavras, com lógica e precisãom poderíamos descrever tudo o que existe.
Direto, não?
Assim, escreveu seu primeiro livro - Tractatus Logico-Philosophicus.
Lá ele diz:
"O significado de uma palavra é o objeto que ela representa." (Tratactus 2.1)
Ou seja: As palavras seriam como etiquetas coladas nas coisas do mundo.
- 🌳 "Árvore" → aponta pra uma árvore.
- 💡 "Ideia" → aponta pra uma ideia.
- 🎲 "Dado" → aponta pro objeto com lados numerados.
A linguagem funciona como um espelho lógico da realidade.
Se a estrutura da frase combina com a estrutura do fato, ela é verdadeira.
... E se algo não é verdadeiro, não faz sentido falar sobre.
Com isso, ele achava que tinha solucionado todos os problemas da filosofia.
Largou a filosofia e foi fazer várias coisas:
-
Foi Jardineiro num monastério
-
Foi professor primário em vilarejos da Áustria
-
Ajudante de arquitetura...
Mas... Algo faltava.
❓ E as coisas que não podemos ver?
❓ E o que não pode ser medido, contado ou demonstrado?
❓ Onde ficam a ética, a estética, o mistério?
... É tudo falso - e não devemos falar sobre?
Foi aí que Wittgenstein começou a se questionar.
Via crianças brincando.
Médicos conversando.
Pessoas negociando.
Todos usando palavras com múltiplos significados, que mudavam conforme a situação.
Como manter uma estrutura rígida de linguagem com tudo isso?
Começou a perceber que a linguagem não era feita de etiquetas fixas.
Era feita de jogos, contextos, acordos invisíveis.
E aí, entendeu: "O significado de uma palavra é o seu uso na linguagem."
A linguagem, para ele, virou algo orgânico.
Não mais um espelho lógico…
Mas uma ferramenta social.
E aí entra o que ele chama de "jogos de linguagem".
Palavras são como peças num jogo.
O que elas significam depende das regras do jogo em que aparecem.
E cada grupo — família, time, empresa, cultura — joga com regras diferentes.
Em resumo - no início, Wittgenstein tinha criado um modelo rígido - fechado.
Com o passar dos anos e experiência, viu que as coisas eram flexíveis.
Ele viu que usar um modelo rígido - matemático, geométrico, era furada.
E disso conseguimos extrair muita sabedoria.
Software como um Jogo
Eu proponho que você comece a ver software como um jogo.
Dependendo da situação e do contexto, regras diferentes se aplicam.
As coisas precisam ser flexíveis.
Um exemplo - no estilo Wittgenstein do Tractatus.
Digamos que você identificou um problema:
Não existe um e-commerce que cobre entregas em sua região.
Aí você começa a escrever uma solução.
Temos que ter um carrinho, sistema de autenticação, etc.
Beleza.
Temos compradores e vendedores, certo?
Logo, o comprador...
class Comprador {id: string;nome: string;enderecoEntrega: Endereco;historicoDePedidos: Pedido[];}
Suficiente.
E aí você sobe seu sistema com essa entidade.
Meses depois, o mesmo usuário quer ser vendedor.
E agora?
Ele também teria que seguir a seguinte entidade:
class Vendedor {id: string;loja: Loja;produtos: Produto[];relatorios: RelatorioDeVenda[];}
... Uma solução rápida seria criar uma superclasse, no estilo de
class Usuario {id: string;nome: string;tipo: 'COMPRADOR' | 'VENDEDOR';enderecoEntrega?: Endereco;produtos?: Produto[];historicoDePedidos?: Pedido[];relatorios?: RelatorioDeVenda[];}
O problema é que isso termina com um padrão de condicionais no sistema inteiro.
if (usuario.tipo === 'VENDEDOR') {mostrarPainelDeEstoque(usuario.produtos);}
... Fica difícil de flexibilizar.
E agora, se depois de um tempo, tivermos um tipo novo, como 'Administrador'? Como proceder?
Fica complicado.
Uma solução que podemos usar é composition
.
Algo no estilo:
class UsuarioBase {id: string;nome: string;email: string;}class PerfilComprador {enderecoEntrega: Endereco;historicoDePedidos: Pedido[];}class PerfilVendedor {loja: Loja;produtos: Produto[];relatorios: RelatorioDeVenda[];}// Composição explícitaclass UsuarioContextual {base: UsuarioBase;comprador?: PerfilComprador;vendedor?: PerfilVendedor;}
Veja como UsuarioBase
serve como uma "identidade" base.
Podemos facilmente compor diferentes perfis dessa maneira.
O jogo fica dinâmico, desse jeito.
Também perceba como o jogo do domínio do e-commerce é dinâmico - e complicado.
É impossível prever o futuro e saber tudo que precisamos, portanto é necessário planejar e flexibilizar de antemão.
Independente do contexto - estaríamos prontos, de uma forma que o segundo Wittgenstein estaria orgulhoso.
Agora - é necessário saber equilibrar.
Se o seu contexto de problema não prevê múltiplos tipos de usuários, ter um UsuarioBase
acaba virando overengineering, uma abstração não necessária.
E aí entra a questão de ser um artesão. Saber identificar, planejar e adaptar.
Mas já tendo essa ideia da composição em mente, já lhe abre portas.
De base:
-
Mapeie os papéis reais do usuário no seu sistema.
-
Evite tentar criar um modelo universal.
-
Use código como linguagem — não como geometria. Isto é, use composição.
-
Antes de codar, pergunte: "Qual jogo de linguagem estou modelando?"
Isso muda tudo.
-Rapozo