Dev. de Software

Muito mais do que simplemente codar e codar e codar, desenvolver software é uma arte que envolve um gama de conhecimentos e habilidades.

Nesta seção, vamos abordar alguns dos principais conceitos, metodologias, padrões e boas práticas que podem nos ajudar na construção de um software com mais qualidade, mais robusto e mais fácil de manter.

Como muitos desses conceitos se misturam e se complementam, não há uma ordem específica para a leitura dos posts desta seção. Vou manter essa categoria aberta para ir adicionando novos posts conforme eu for vendo a necessidade de abordar algum assunto, seja ele com a pretensão de servir como um guia para mim mesmo, seja para compartilhar algum conhecimento que eu tenha adquirido.

Vou reforçar aqui que não sou nenhum especialista em desenvolvimento de software, mas sou um entusiasta que gosta de aprender e criar soluções com qualidade.

Subsections of Dev. de Software

Domain Driven Design

O que é DDD?

O domain driven design é uma abordagem, ou melhor dizendo, uma filosofia que vai manter você focado no domínio do problema que está tentando resolver, e não nas tecnologias que você vai utilizar para resolver esse problema.

Estamos acostumados a pensar em desenvolvimento de software como uma atividade única e exclusivamente técnica, e por diversas vezes a primeira coisa que fazemos é pegar nossa linguagem preferida, e a partir da concepção do banco de dados começar a criação do software, mas perceba, temos o problema sendo concentrado em dados e não no domínio.

Dependendo do domínio e quão complexo ele é, essa abordagem tende em um futuro bem próximo ser um tiro no pé, por vezes tornando o software difícil de manter, difícil de escalar e difícil de evoluir.

Mas afinal o que de fato é DDD?

Atacar o software no coração da aplicação

A grande proposta do DDD é promover uma mudança de paradigma no desenvolvimento de software, principalmente em sua fase de concepção.

Quando estamos falando de DDD estamos falando de conceitos e não de código. Estamos falando na criação de um software guiado pelo domínio do negócio, aliás o próprio nome já diz isso, Domain Driven Design, ou seja, Design guiado pelo domínio.

Como o próprio Eric Evans, criador do DDD, diz em seu livro:

O objetivo do DDD é criar um modelo de domínio rico e expressivo que capture as complexidades do negócio e que seja refletido no código do software."

Em suas palavras fica evidente a existência de uma separação entre o domínio do negócio e o código do software, em outras palavras, complexidade do négocio e complexidade de software.

Note

Iniciar o desenvolvimento atacando a complexidade do negócio, buscando a compreensão plena do problema que se quer resolver, limitando o escopo desse problema e definindo uma linguagem ubíqua que seja compreendida por todos os envolvidos no projeto, é o primeiro passo para o sucesso de um projeto.

Ainda sobre essa separação grande parte do complexidade de um software não vem da tecnologia, mas sim da comunicação, separação de contextos e do entendimento pleno do negócio analisado por vários ângulos.

Como o DDD pode me ajudar?

Em primeiro lugar vale deixar claro que DDD vai entregar grande valor para projetos de softwares complexos.

Grandes projetos de software envolvem muitas áreas, muitas pessoas, muitas regras de negócio e em muitos contextos diferentes, e é justamente nesse cenário que o DDD vai te ajudar a manter o foco no que realmente importa, o negócio.

Dito isso, o DDD vai te ajudar a:

  • Entender com profundidade o domínio e subdomínios do negócio
  • Criar uma linguagem ubíqua que seja compreendida por todos os envolvidos no projeto
  • Criar um design estratégico utilizando os conceitos de bounded context, context map e subdomínios
  • Criar um design tático utilizando os conceitos de entidades, agregados, objetos de valor e serviços de domínio
  • Clareza no que diz respeito a complexidade do negócio e complexidade de software

Domínio, Subdomínio e Contextos (Bounded Context)

Domínio vs Subdomínio

Podemos dizer que o domínio é o core do negócio, é o coração da aplicação, é o que realmente importa, é o que gera valor para o negócio e subdomínios são pequenas partes dentro do domínio que dão suporte ao domínio principal, onde cada uma delas tem seu grau de importância.

A figura abaixo ilustra bem essa relação: domain-vs-subdomain domain-vs-subdomain

É importante destacar que a exploração do domínio pode levar tempo e requer uma abordagem iterativa. A medida que você aprofunda seu conhecimento e compreensão, você é capaz de identificar as partes cruciais do domínio, capturar regras de negócio e entender os desafios específicos de cada subdomínio.

Aqui nesta fase Eric Evans deixa claro a necessidade do uso de uma linguagem ubíqua, ou seja, uma linguagem que seja compreendida pela equipe tecnica e pelos especialistas do negócio e é essa linguagem que deve ser utilizada em todo o projeto e inclusive ser refletida no código.

Se o especialista do domínio chama um determinado conceito de uma forma, então esse conceito deve ser representado no código da mesma forma.

Espaço do problema vs Espaço da solução

problem-vs-solution problem-vs-solution

Espaço do problema é o espaço onde o domínio do negócio é explorado, onde as regras de negócio são capturadas e onde a linguagem ubíqua é criada.

Espaço da solução é o espaço onde o domínio é implementado, onde o código é escrito e onde a linguagem ubíqua é refletida.

Em conjunto essas duas áreas formam o que Eric Evans chama de Bounded Context, ou seja, um contexto delimitado, onde o domínio é explorado e onde o domínio é implementado, ou seja, subprodutos são criados.

Bounded Context

Em um sistema complexo, diferentes partes do negócio podem ter conceitos, terminologias e regras diferentes. Essas diferenças podem levar a ambiguidades e conflitos se não forem tratadas adequadamente e é aqui que os Bounded Contexts entram em cena.

Em poucas palavras podemos dizer que um Bounded Context deixa claro quais são os limites para determinado subdomínio e a linguagem comum usada dentro desse contexto confirma se realmente estamos dentro de um contexto delimitado.

Um contexto sempre vai nos mostrar qual área da empresa e qual problema estamos resolvendo.

A figura abaixo ilustra bem esse conceito:

bounded-context bounded-context

A seta que liga os dois subdomínios expressa que Bounded Contexts podem interagir uns com os outros, estabelecendo comunicação por meio de interfaces bem definidas. Isso permite que diferentes partes do sistema sejam independentes em termos de desenvolvimento, evolução e manutenção.

Conseguiu imaginar como seria manter e evoluir um sistema que lida com uma única entidade para representar um cliente em contextos diferentes?

Em resumo, Bounded Contexts são unidades de delimitação no DDD que definem fronteiras lógicas em um sistema de software, permitindo a criação de modelos de domínio/subdomínio específicos e coesos.

Visão estratégica

Para finalizar esse breve resumo sobre DDD, vamos falar sobre visão estratégica. Podemos definir visão estratégica como a visão macro do projeto, ou seja, a visão que vai nos mostrar como o projeto vai se comportar como um todo.

A figura abaixo ilustra bem essa visão macro:

strategic-picture strategic-picture

Esta figura nos mostra o conceito de Context Map, que é um diagrama ou uma representação visual que ilustra como os Bounded Contexts se relacionam uns com os outros. Ele ajuda a documentar e comunicar a visão geral do sistema, destacando os limites entre os contextos e as estratégias de comunicação entre eles.

A principal finalidade do Context Map é fornecer uma visão clara das integrações, alinhamentos e colaborações entre os Bounded Contexts, a fim de evitar conflitos e ambiguidades na implementação do software.

Em resumo o que podemos inferir da imagem acima é que:

  • O domínio possuí 4 contextos (Core business -> Vendas de ingressos online)
  • Fica fácil definir os times e as responsabilidades de cada um
  • U (upstream) -> Vai ditar as regras de como as coisas vão funcionar no momentos da implementação
  • D (downstream) -> Vai se adaptar as regras elaboradas pelo U
  • Conformista -> Vai ter que conformar e usar da forma como foi criada (Quanto mais conformista, mais amarado você vai ficar)
  • ACL (Anti-Corruption Layer) -> Funciona como um adaptador, pois no exemplo acima onde estamos em uma relação conformista com o gateway de pagamento, se um dia precisarmos trocar o gateway alteramos somento o código da camada de ACL.

Disclaimer

Parte desse resumo incluindo as imagens usadas vieram do módulo de DDD do curso Fullcycle, que por sinal é um excelente curso e que eu recomendo fortemente se sente que precisa elevar o seu nível de conhecimento em microserviços.

É isso, espero que tenha gostado e até a próxima!

Subsections of Domain Driven Design

Estrutura de pastas

A estrutura que sigo compartilhando é a que eu julgo ser a mais simples e eficiente para a maioria dos projetos que eu desenvolvo, isso não significa que seja a melhor ou a pior, apenas que eu gosto assim. Gosto da visão de um sistema modular e nesse sentido cada modulo tem a sua própria estrutura.

Claro vale lembrar, estou seguindo DDD.

Overview

Como ilustração vamos utilizar um projeto backend com fastapi para você entender como eu estruturo os projetos.

src - Onde fica todo o código fonte do projeto.

core - Aqui esta o coração da minha aplicação organizada em módulos.

fastapi - Aqui fica o código relacionado a tecnologia que estou utilizando (que neste caso é fastapi)

__seedwork - Aqui fica o código que é compartilhado entre os módulos (Esse é um conceito criado por Martin Fowler)

tests - Aqui ficam os testes de integração e unitários

Como exemplo vamos utilizar apenar um módulo para ilustrar

├── src
│   ├── core
│   │   ├── __seedwork
│   │   │   ├── application
│   │   │   ├── domain
│   │   │   ├── infrastructure
│   │   │   ├── tests
│   │   ├── products
│   │   │   ├── application
│   │   │   │   ├── dto.py
│   │   │   │   ├── use_cases.py
│   │   │   ├── domain
│   │   │   │   ├── entities.py
│   │   │   │   ├── repositories.py
│   │   │   │   ├── validators.py
│   │   │   ├── infrastructure
│   │   │   │   ├── fastapi
│   │   │   ├── tests
│   │   │   │   ├── integration
│   │   │   │   │  ├── application
│   │   │   │   │  ├── domain
│   │   │   │   │  ├── infrastructure
│   │   │   │   ├── unit
│   │   │   │   │  ├── application
│   │   │   │   │  ├── domain
│   │   │   │   │  ├── infrastructure
│   │   │   ├── domain
│   │   │   ├── infrastructure
│   ├── fastapi
│   │   ├── ...

Sei que aparentemente parece uma estrutura redundante, mas acredite, ela é muito útil quando esta lidando com um projeto maior pois as coisas estarão perto de onde precisa estar.

É isso, espero que tenha gostado, se tiver alguma sugestão ou dúvida, pode me chamar no linkedin.