fbpx
Abstrações duplicadas, quem nunca?
Publicado em: terça-feira, 20 de out de 2020

Quando uma abstração está exercendo seu papel, seu código tende a cada vez parecer mais simples. Ao olhar desatento pode parecer até simplista. O problema é que essa simplicidade ao mesmo tempo que aumenta a produtividade, produz ansiedade e afeta quem depende de complexidade para programar.

No post anterior, Abstrações e seu ciclo evolutivo, eu abordei uma ideia que até cheguei a colocar em prática, mas não tive tempo usando-a para tirar conclusões mais elaboradas sobre o que acontece no dia-a-dia. Mas dessa vez eu vou falar sobre algo que tive de lidar em ~2013.

Qual era o problema?

Eu havia trazido o Oragon para dentro do projeto principal que estava construindo e que chamei de iMusica Enterprise. Diferente da proposta do que defendo em Abstrações e seu ciclo evolutivo, nesse projeto eu havia um fork e trouxe para dentro da iMusica. Vale lembrar que o Oragon é meu, naquela época era resultado de mais de 10 criando abstrações e mais abstrações que facilitavam o dia-a-dia. Mas, como aquilo era novo para aquele time, eu resolvi trazer o código como meio de tornar esse mindset de abstrair a complexidade algo cotidiano.

Ahhh como eu era inocente!

Eu estava inspirado a criar um novo monolito, dessa vez bem modelado e consistente. Um passo prévio para a identificação da delimitação dos contextos, visando mais à frente em alguns anos, quebrar o projeto em coisas menores. Não estava claro se seria microsserviço ou não, mas na prática eu nem entendia o que microsserviço era de fato.

Aliás, em MonolithFirst @ Fowler, artigo comentado de 2016, eu encontro amparo para a minha própria intuição que apontava que não tinha tinha consciência e maturidade para decidir sobre onde quebrar o projeto, por conta de não conhecer o domínio o suficiente para isso. E por isso criar um monolito desenhado para ser quebrado posteriormente.

De qualquer forma o que estava claro era que merecia, futuramente, quebrar o projeto. Mas nem o grafo de dependências estava muito claro para ninguém que estava lá há anos, muito menos para mim com meses.

O que dava para enxergar desde os primeiros dias, era o óbvio:

Precisava de uma nova base de código que fosse modelada “da forma certa”, já que até então o que existia era uma colcha de retalhos em que se buscou fazer da forma que dava, em vez de fazer o que precisava ser feito. Um arroz com feijão bem feito, só!

Incorporar não foi suficiente

Eu achava que trazendo o código do Oragon para esse projeto, eu estaria facilitando o dia-a-dia do time, porque na minha cabeça, uma vez que o código estivesse embarcado na mesma solution, magicamente se alguém quisesse entender e estudá-lo, seria prático de ler, prático de debugar, prático de entender o fluxo. Quem não quisesse, ok, você tinha exemplos suficientes de como usar. Então você poderia ser usuário da arquitetura e se quisesse, poderia ser colaborador também! Eu estava completamente equivocado. Lembro de apenas 2 ou 3 pessoas terem algum interesse em como as coisas funcionavam.

Mas uma terceira pessoa queria a todo custo participar daquela complexidade. Queria construir uma nova abstração. Mas o problema era que não havia fundamento algum, exatamente porque não só havia uma abstração para aquela finalidade, como a tal abstração estava com um bom nível de maturidade, resistindo intacta à novas demandas, resistindo aos novos requisitos que chegaram nos meses anteriores.

E aí me veio à cabeça algumas questões:

  • Estava claro que o motivador era o interesse em fazer algo complexo e desafiador
    • Isso é natural de um problem solver
    • Isso é perfeitamente aceitável e esperado de um bom dev
  • Mas criaria um problema para a arquitetura
    • Não havia um bom motivo para a criação daquela nova abstração
    • Outra abstração, madura, pré-existente deveria ser usada ou refatorada para atender á nova demanda/requisito.
  • Eu, como líder e gestor precisava criar uma regra que ao mesmo tempo:
    • Permitisse que qualquer um criasse novas abstrações na medida em que fossem necessárias
    • Mas quando uma nova abstração esbarrasse no escopo da anterior, seria necessário garantir:
      • Que a anterior fosse substituída pela nova
      • Que não gerasse quebras para quem já dependia daquela abstração
    • De forma a encorajar quem sabe o que quer e sabe o que está fazendo
    • E ao mesmo tempo desencorajar a criação de abstrações duplicadas, ou com perda de features.

Se eu pudesse resumir, a intenção era garantir que cada um soubesse o que precisa ser feito e o que é considerado correto. Se uma abstração que está funcionando precisa ser refatorada, ela será. Não importa se ela é usada em 1 lugar ou em 100. Sem mimimi, sem ressentimento. Vamos alterar coisas que estão funcionando e partes do sistema que já estavam testadas para garantir que a base de código não fosse corrompida com abstrações dúbias, que confundem mais do que resolvem problemas.

Eu chamo isso de:

Fazer o que precisa ser feito.

Em um projeto em que toda ou pelo menos a maior parte da complexidade arquitetural é delegada à mecanismos e abstrações, o código de negócio parece algo ridiculamente simples e muitas até parece burro. Embora a frase da imagem abaixo se faça presente:

Como lidar com a necessidade de fazer coisas mais complexas e de fato entregar desafios para serem resolvidos?

Minha resposta para essa pergunta é simples. Nesse período eu criei esse conjunto de regras, que desde então regem essa forma de encarar as abstrações:

  1. Toda complexidade deve ser abstraída em projeto(s) de arquitetura/infraestrutura.
  2. Sendo totalmente genéricas
  3. Sem nenhuma dependência direta com o projeto
  4. Nascendo lado-a-lado com o projeto, podendo estar na mesma solution, como meio de facilitar e promoter o refactoring, até alcançar um nível de maturidade para que seja promovida/isolada.
  5. Nunca 2 abstrações para a mesma finalidade podem coexistir no mesmo projeto.
  6. Se há questões com a implementação atual, priorize corrigir ou evoluir a abstração atual.
  7. Se for o caso de criar uma nova abstração, o item 5 deve ser levado em conta, portanto é escopo obrigatório da nova abstração, substituir a anterior, isso implica em refatorar se necessário, as partes que dependiam da abstração anterior.

Esse conjunto de 7 itens trazem alguns benefícios:

  • As abstrações são evoluídas ao invés de duplicadas.
  • Para recriar uma abstração, é preciso entender primeiro a versão anterior em sua plenitude.
  • Ao refatorar ou recriar a abstração, toda a base de código é atualizada para usar a nova versão.
  • Não há meios de se produzir duplicidade de abstrações.
  • O ímpeto de buscar problemas para resolver continua sendo endereçado, mas de forma coordenada ao invés de aleatório. Todos se beneficiam daquela implementação.
  • A separação clara de responsabilidades demanda uma modelagem mais eficiente, que gera a capacidade da abstração ser promovida de local para regional e posteriormente para global.
  • A busca por complexidade não fundamentada é desencorajada.
  • A busca por trazer complexidade para o código de negócio é desencorajada.

O impacto dessa decisão:

  • Ter de pensar em todos o cenários de uma abstração, é de alguma forma, burocratizar o processo.
  • O medo de refatorar aquilo que não foi feito pelo própria desenvolvedor gera desconforto.
  • A vontade de sair fazendo, de qualquer jeito, continua sendo um problema, como se fosse um vício. Isso produz negação à essa estratégia.
  • Modelar mecanismos que não dependam diretamente do core da aplicação é um desafio, pois por mais que se fale muito de SOLID, na prática SOLID é muito menos usado do que deveria.

O Cloud Native .NET é meu principal projeto.

Onde empenho energia para ajudar, acompanhar, direcionar Desenvolvedores, Líderes Técnicos e jovens Arquitetos na jornada Cloud Native.

Conduzo entregando a maior e mais completa stack de tecnologias do mercado.

Ao trabalhar com desenvolvedores experientes, eu consigo usar seu aprendizado com .NET, banco de dados, e arquitetura para encurtar a jornada.

Ao restringir à desenvolvedores .NET eu consigo usar do contexto de tecnologias e problemas do seu dia-a-dia, coisas que você conhece hoje, como WCF, WebForms, IIS e MVC, por exemplo, para mostrar a comparação entre o que você conhece e o que está sendo apresentado.

É assim que construímos fundamentos sólidos, digerindo a complexidade com didática, tornando o complexo, simples.

É assim que conseguimos tornar uma jornada densa, em um pacote de ~4 meses.

Eu não acredito que um desenvolvedor possa entender uma tecnologia sem compreender seus fundamentos. Ele no máximo consegue ser produtivo, mas isso não faz desse desenvolvedor um bom tomador de decisões técnicas.

É preciso entender os fundamentos para conseguir tomar boas decisões.

0 comentários

Enviar um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.

Luiz Carlos Faria

Mensagem do Autor

Espero que goste desse post. Não deixe de comentar e falar o que achou.

Se acha que esse post pode ajudar alguém que você conheça, compartilhe!

 

Lives

Fique de olho nas lives

Fique de olho nas lives no meu canal do Youtube, no Canal .NET e nos Grupos do Facebook e Instagram.

Aceleradores

Existem diversas formas de viabilizar o suporte ao teu projeto. Seja com os treinamentos, consultoria, mentorias em grupo.