Executando verificação de segurança...
2

Construindo softwares melhores: O poder de criar abstrações efetivas

Image description

A primeira vez que ouvi falar de abstração foi nas aulas de programação na faculdade. Estávamos estudando os quatro pilares da programação orientada a objetos: Abstração, Encapsulamento, Polimorfismo e Herança.

Fiquei fascinado pela ideia de modelar o mundo real no software que estávamos construindo. Era um conceito novo para mim e foi preciso muita prática para me acostumar a pensar dessa forma.

No entanto, meu entendimento de abstração foi evoluindo. É mais do que apenas replicar o mundo real em software, como aprendemos em nossas aulas de programação orientada a objetos. A abstração pode ser aplicada em diferentes níveis e, embora possa parecer complexa à primeira vista, não precisa ser assim.

Neste artigo, explicarei como a abstração se aplica ao design de código e como ela pode ajudá-lo a compreender melhor o mundo da tecnologia. Ao usar abstrações eficazes, você pode criar softwares melhores, mais fácil de manter e entender.

Os níveis de abstrações

Image description

Como engenheiros de software, é essencial lidar adequadamente com a abstração para diferentes cenários. Precisamos ajustar nossa comunicação e foco com base no contexto em que estamos.

Ao nos reunirmos com os stakeholders, não podemos usar a mesma linguagem técnica que usamos com nosso time de engenharia. Nesses momentos, o objetivo principal é compreender o negócio, o domínio e a estratégia da forma mais completa possível.

Por outro lado, ao discutir soluções, infraestrutura e arquitetura com a equipe, devemos evitar focar em códigos ou detalhes de linguagens de programação. São conversas de alto nível destinadas a determinar as melhores formas de gerenciar nossos microsserviços e aplicações.

Portanto, há vários níveis de abstração a considerar, e devemos adaptar as nossas perguntas e pensamentos ao contexto certo, no momento certo, com as pessoas certas. Reconhecer esses níveis de abstração me ajudou a compreender o poder do contexto.

Mas e as soluções de baixo nível? Como podemos identificar as abstrações nos software que estamos construindo e como ela funciona?

Abstração é vida

Image description

Ao projetar software, lidamos com casos de uso que representam ações do usuário em nosso sistema. A abstração é essencial. Ao definir a responsabilidade de uma abstração, nós a moldamos com base no contexto e no propósito que estabelecemos.

Criar uma nova abstração é como dar vida a algo. Precisamos definir claramente sua responsabilidade e propósito. É por isso que gosto particularmente de trabalhar com interfaces. Eles nos permitem definir contratos claros para nossas abstrações, garantindo que cada parte do sistema tenha uma função específica e interaja com outras.

Trabalhando com interfaces

Image description

Uma interface bem definida atua como um contrato para nossa abstração. É como dar vida a algo e dizer: “Seu propósito é apenas fazer isso e que isso seja bem feito”. Não precisamos nos preocupar com os detalhes de como isso será feito, a interface fornece um contrato estável que define o que é a abstração e o que ela oferece.

Esta abordagem está alinhada com o “D” dos princípios SOLID: o Princípio de Inversão de Dependência (DIP). O DIP afirma que devemos depender de abstrações e não de implementações concretas. Seguindo este princípio, criamos sistemas flexíveis e de fácil manutenção que podem se adaptar às mudanças com mais facilidade.

Uma combinação de peças

Image description

No design de software, penso nas interfaces como peças de um quebra-cabeça. Cada peça tem um contrato e uma finalidade bem definida, o que nos permite utilizá-las precisamente onde for necessário.

Trabalhar com interfaces proporciona estabilidade ao fazer alterações no código. Não importa o quanto uma classe concreta mude, desde que ela cumpra o contrato, os consumidores daquela interface permanecem inalterados.

O uso de interfaces para definir abstrações também oferece suporte a TDD. Com a abordagem mockista, posso mockar o comportamento de abstrações externas e focar no comportamento esperado da abstração atual que estou construindo. Isso garante que cada peça do quebra-cabeça se encaixe perfeitamente e funcione conforme planejado.

De quem é a responsabilidade ?

Image description

Ao criar casos de uso, muitas vezes tendemos a centralizar todos os comportamentos e regras de negócios em um único serviço ou caso de uso. No entanto, um caso de uso bem projetado é, na verdade, uma combinação de múltiplas abstrações trabalhando juntas.

Exemplo:

Em um software financeiro, considere um caso de uso que gera uma fatura.
O fluxo pode ser assim:

  1. Verifica se o usuário tem permissão
  2. Obtém a fatura
  3. Calcular o imposto
  4. Gera a fatura

Não é ideal para este caso de uso lidar com todas as regras de negócios. Em vez disso, deveria delegar responsabilidades específicas às abstrações criadas para essas regras de negócio.
Construir softwares de qualidade requer perguntas de qualidade.

Para criar casos de uso coesos, precisamos fazer as perguntas certas:

  • De quem é essa responsabilidade?
  • Quantos motivos esse caso de uso tem para mudar?
  • Será que eu deveria criar uma abstração para lidar com esta regra de negócio específica?
  • Esta regra de negócio está dentro do escopo da abstração que estou construindo?
  • Isso está coeso?
  • Alguém sem muito contexto pode entender este caso de uso?

Uma possível solução:

  1. Depender de uma abstração que lida com regras de negócio de permissão
  2. Obter o valor da fatura
  3. Depender de uma abstração que lida com regras de negócio de cálculo de impostos
  4. Depender de uma abstração que gere a fatura no formato requerido

Conclusão

A magia dessa abordagem é que ela nos permite ver as coisas de diferentes perspectivas e em vários níveis de abstração. Compreender em que nível de abstração e contexto estamos nos ajuda a estabelecer uma melhor comunicação e uma compreensão mais clara dos problemas e oportunidades dentro do negócio.

Um bom design começa com as perguntas certas e o objetivo final é a simplicidade. Criar design de softwares é um processo contínuo.
Há sempre espaço para melhorias. Podemos refinar continuamente nossos projetos aprendendo com nossos erros e através das nossas práticas.

Referências

Carregando publicação patrocinada...