Você está na página 1de 16

ARQUITETURA

DE SISTEMAS

Rodrigo Farias Herculano Mendes


Domain-driven design
Objetivos de aprendizagem
Ao final deste texto, você deve apresentar os seguintes aprendizados:

 Conceituar domain-driven design (DDD) e seus blocos.


 Analisar a incorporação do DDD no desenvolvimento de software.
 Identificar os aspectos da aplicação do DDD.

Introdução
Neste capítulo, você vai estudar os principais conceitos de domain-
driven design (DDD) e os principais blocos de construção que compõem
o conjunto de boas práticas de modelagem de softwares. Você vai
compreender a base de funcionamento do DDD e a sua aplicação
dentro de um contexto profissional de desenvolvimento de software,
verificando também as principais dificuldades encontradas durante esse
tipo de processo. Vale salientar que as práticas aqui empregadas são
especificamente voltadas para a concepção de domínio de software no
contexto do paradigma orientado a objetos (OO).

O que é domain-driven design?


Desenvolver um software não é uma tarefa simples. Para que tal feito seja
alcançado, é necessário que haja um esforço em conjunto dos interessados
na construção do software, no sentido de executar tarefas essenciais para a
concepção do mesmo. Essas tarefas são interdependentes e compõem o que
tradicionalmente chamamos de processo de desenvolvimento de software,
conforme leciona Sommerville (2007).
Uma das principais tarefas do desenvolvimento de software é a requisição
ou licitação de requisitos do domínio do sistema. Nesse ponto, as práticas
de modelagem de domínio são amplamente utilizadas, para a produção de
um modelo de domínio alinhado com as regras de negócio, ou seja, com os
requisitos de domínio do sistema. É comum o emprego de padrões de mode-
2 Domain-driven design

lagem de domínio, como o domain-driven design (DDD, ou projeto orientado


a domínio), para esse fim.
O DDD, como o próprio nome descreve, consiste em elaborar o desenho
da aplicação a ser desenvolvida, tendo como foco o domínio. Segundo Evans
(2004), o DDD é um padrão de modelagem de software com base no para-
digma orientado a objetos. Esse padrão busca reforçar conceitos e boas
práticas relacionadas à OO, visando a expressar a relação entre um contexto
ou domínio, um problema e uma solução para esse problema, de acordo com
as regras que definem um domínio específico.
Alguns apontam o DDD como o retorno da OO e suas boas práticas de
modelagem para software. Quando falamos de OO, logo nos vêm à cabeça
as características que circunscrevem esse paradigma de programação, como
classes, heranças, polimorfismo, encapsulamento, etc. Tucker e Noonan (2009)
descrevem que a essência da OO abrange outros aspectos, conforme descrito
a seguir.

 Alinhamento do código com o negócio: o contato dos desenvolvedores


com os especialistas do domínio é algo essencial quando se faz DDD,
uma vez que promove um entendimento único sobre as regras de negócio
do software em questão.
 Reutilização: os blocos de construção desenvolvidos facilitam o apro-
veitamento de um mesmo conceito de domínio ou um mesmo código
em vários momentos do desenvolvimento.
 Baixo acoplamento: em um modelo bem-feito, refinado e organizado, as
várias partes de um sistema interagem, sem que haja muita dependência
entre módulos ou classes de objetos de conceitos distintos.
 Independência da tecnologia: o DDD não foca em tecnologia, mas,
sim, em entender as regras de negócio e como elas devem estar re-
fletidas no código e no modelo de domínio. Isso não quer dizer que a
tecnologia usada não é importante — apenas significa que essa não é
uma preocupação do DDD.

Dentro da perspectiva OO, é possível empregar esse conjunto de caracte-


rísticas de maneira padronizada, ao ponto de a repetibilidade de tais carac-
terísticas se tornar uma conduta correta — o que, em um jargão comum do
desenvolvimento de software, chamamos de boas práticas de programação.
Então, nesse sentido, temos o casamento de valores perfeito para o desenvolvi-
mento de software, utilizando características do paradigma OO e os padrões
de modelagem do DDD, conforme aponta Evans (2004).
Domain-driven design 3

Blocos ou arquitetura em camadas do DDD


Uma vez que a equipe de programação se decida por utilizar o DDD, é necessário
que, inicialmente, o software seja dividido por blocos de responsabilidades, de-
vendo-se isolar o modelo de domínio das demais partes que compõem o sistema,
conforme aponta Firmino (2014). Essa separação pode ser feita utilizando-se
uma arquitetura em camadas, que dividirá a aplicação em quatro blocos ou
camadas: interface do usuário, aplicação, domínio e infraestrutura (Figura 1).

Figura 1. Blocos de construção do DDD, utilizados


para separar o domínio do resto da aplicação.
Fonte: Adaptada de Cukier (2010).

Segundo Firmino (2014), as camadas têm as seguintes responsabilidades:

 Interface de usuário: essa camada tem a responsabilidade de prover


a comunicação do usuário com a base de dados do software, tanto
para receber comandos como para simplesmente verificar resultados
na tela da aplicação. O usuário não precisa necessariamente ser uma
4 Domain-driven design

pessoa, podendo até mesmo ser outro sistema (Web services, motores
de indexação, etc.).
 Aplicação: nessa camada, as operações de coordenação da aplicação
e de suporte a outras tarefas técnicas são o foco principal. Nesse ponto
do software, normalmente, é disparada a lógica de negócio que está em
outra camada, ou simplesmente uma consulta ou chamada de alguma
tarefa técnica do banco de dados da aplicação — ou seja, o início de
uma transação, a execução e o seu respectivo fim. É de total responsa-
bilidade da aplicação buscar qualquer dado que a camada de domínio
necessite para iniciar a operação.
 Domínio: a camada de domínio é a camada em que o DDD foca suas princi-
pais práticas e padrões. Normalmente, a camada de domínio é considerada o
núcleo, abrangendo as regras de negócio do software. É aqui que estão todas
as regras discutidas nas conversas entre o cliente que usará o software e a
equipe que o desenvolveu. Nesse ponto, o time de desenvolvimento utiliza
um linguajar específico sobre o domínio de negócio, usando linguagem
ubíqua (linguagem comum, com termos bem-definidos, que fazem parte
do domínio do negócio e que são usados por todas as pessoas que fazem
parte do processo de desenvolvimento do software). É essa camada que
dá valor à aplicação; ela interage com todas as camadas da aplicação,
recebe chamadas da camada de aplicação, devolve valores para a camada
de interface com o usuário (que podem também passar pela camada de
aplicação) e dispara requisições para a camada de infraestrutura.
 Infraestrutura: abrange tudo o que está relacionado aos eventos téc-
nicos do software, como banco de dados, bibliotecas, frameworks, per-
sistência de dados, conexões com bancos de dados, envio de mensagens
por redes, gravação e leitura de discos, etc. Esses detalhes técnicos estão
contidos na camada de infraestrutura e são separados dos interesses
do usuário final. Serve basicamente como uma camada isolante, para
separar o resto da aplicação desses detalhes.

Depois de dividir o sistema em blocos ou camadas, é possível focar na


camada de domínio. A arquitetura de camadas permite isolar o domínio das
demais camadas, para deixá-lo o mais puro possível. Essa prática é importante
porque tratar do domínio já é, por si só, uma tarefa complexa; isolar o domínio
possibilita que não seja necessário tratar de outras questões, como questões
técnicas ou de camada visual, durante o uso do DDD.
Além da reusabilidade de códigos de cada módulo ou componente desen-
volvido, a divisão da arquitetura do software em camadas facilita o processo
Domain-driven design 5

de manutenção do software. A tarefa de encontrar um bug sobre a lógica de


negócio, quando o domínio do software está isolado em uma camada única,
é mais simples. Desse modo, podemos observar que uma camada está com-
pletamente desassociada da outra, limitando a comunicação, que só se torna
possível por meio de classes abstratas e interfaces. A camada inferior nunca
dispara operações na camada superior.
É comum empresas de software observarem seu software como um ativo
valioso e promoverem o reúso, para aumentar seu retorno sobre investimentos,
conforme aponta Sommerville (2007). A reutilização de códigos é um artifício
que não deve ficar de fora da caixa de ferramentas de um desenvolvedor. Além
disso, o reúso de código é uma das premissas do DDD em escala significativa,
como na utilização disseminada das APIs Java, conforme aponta Braude (2005).

A reutilização de código no desenvolvimento de software tem sido apontada como um


fator de grande economia de tempo, impactando diretamente no custo da aplicação.
Por meio dela, desenvolvedores de outro projeto podem se beneficiar do reúso do
seu código, em vez de ter que reinventá-lo.

Incorporando o DDD no desenvolvimento


de software
Para que um software atenda completamente aos requisitos de domínio, é
estritamente necessário que os stakehoders, ou seja, todos os interessados no
desenvolvimento do software, utilizem uma linguagem única, de modo que
todos possam entender as características intrínsecas daquele domínio. Essa
linguagem é conhecida como linguagem ubíqua e consiste em um linguajar
comum, com termos bem-definidos, que fazem parte do domínio do negócio
e que são usados por todas as pessoas que fazem parte do processo de desen-
volvimento de software, conforme leciona Evans (2004).
É comum que os termos utilizados nas conversas do cotidiano dos especia-
listas do domínio (vendedores, professores, frentistas, ou seja, o usuário final
do software) sejam entendidos também por parte do time de desenvolvimento.
Todos devem usar os mesmos termos, tanto na linguagem falada quanto no
código. Por exemplo, durante uma conversa com o cliente sobre o domínio das
6 Domain-driven design

ações de um caixa de pagamento da loja, podem ser utilizados os seguintes


termos: “Temos que emitir a fatura para o cliente antes da data limite”. Muito
provavelmente, teremos uma classe para a entidade Cliente, outra classe para
a entidade Fatura, além de um serviço que possibilite o uso de um método
emitir, delimitado por algum atributo com o nome de data-limite.
É possível que um determinado conceito do domínio possua várias palavras
que o representem; por exemplo, Fatura pode ser chamado de Nota Fiscal. É
necessário readequar tanto a linguagem falada e escrita quanto o código-fonte
que foi escrito para desenvolver o domínio em questão. Dessa maneira, faz-se
necessário que as equipes de desenvolvimento estejam em sintonia em relação
ao termo utilizado para Fatura/Nota Fiscal, e ambos devem possuir a mesma
concepção e o mesmo significado quanto à sua funcionalidade.
É extremamente necessário utilizar a linguagem ubíqua para criar um
modelo de domínio por meio do DDD. A ideia por trás do DDD é que a ex-
pressão do modelo abstrato do software deve ser uma representação perfeita
do seu domínio e de suas regras de negócio. Tudo o que existe no negócio
deve aparecer no modelo, e somente aparece no modelo aquilo que está no
negócio, conforme aponta Evans (2004).
Em um time de desenvolvimento de software, é comum que especialistas
de domínio, desenvolvedores, arquitetos de software e testadores trabalhem
de maneira integrada para a construção do software. Isso agiliza o processo
de desenvolvimento, diminuindo o tempo de produção do software e seu
time to Market (jargão utilizado na computação para indicar o tempo para
o lançamento de um produto de software no mercado). O DDD preconiza o
desenvolvimento ágil do modelo abstrato, e esse modelo deve ser feito em
conjunto com os stakeholders, conforme leciona Sommerville (2007).
Se arquitetos e especialistas de negócio criarem o modelo sem a participação
dos desenvolvedores, é provável que o modelo criado não possa ser implementado
ou, simplesmente, utilize tecnologia inadequada. Segundo Sommerville (2007),
o contrário dessas ações também pode levar a um modelo não implementável,
pois, se desenvolvedores codificarem sem se basear em um modelo consistente,
provavelmente desenvolverão um software que simplesmente não serve para
o domínio. Em DDD, uma parte das pessoas que modelam o domínio deve
necessariamente ser composta por pessoas que “colocam a mão no código”
(os chamados hands-on modelers).
O processo de amadurecimento de um software desenvolvido com os
conceitos do DDD deve ser constante. O modelo guiará o desenvolvimento do
código, e, ao mesmo tempo, o código ajudará a refinar o modelo de domínio
e suas regras de negócio. O contato no dia a dia com o código trará uma
Domain-driven design 7

visão apurada aos desenvolvedores a respeito do domínio; diante dessa visão


privilegiada, os desenvolvedores podem e devem, constantemente, alterar
(refatorar) o código, buscando melhorias. O processo de refatoração deve
ser constante e não exclusivamente no código; é primordial que o modelo de
domínio desenhado seja refatorado, para manter ambos, modelo e código do
domínio, alinhados com as regras de negócio do cliente, conforme aponta
Braude (2005).

Refatoração é o processo de alteração de um sistema de software, de modo que o


comportamento externo do código não mude, mas que sua estrutura interna seja
melhorada. É uma maneira disciplinada de aperfeiçoar o código, que minimiza a
chance de falhas. Em essência, quando você usa refatoração, você está melhorando
o projeto do código depois de ele ter sido escrito, conforme leciona Braude (2005).

Após o processo de modelagem usando os blocos de construção conceitual


do DDD, um modelo de dados é gerado. Nesse modelo, as regras de negócio
do software devem refletir sobre seu domínio. Mesmo com o amadurecimento
do modelo, a tarefa de refatoração do software deve continuar sendo
executada, visando a um modelo cada vez mais aperfeiçoado e que reflita
exatamente as características definidas pelo domínio de negócio, conforme
orienta Braude (2005).
É comum que alguns conceitos que circunscrevem o domínio estejam
implícitos no código-fonte do software. Nesses casos, a tarefa do desenvolvedor
é identificar tais conceitos e torná-los explícitos. Segundo Evans (2004),
o DDD fornece alguns padrões que podem ajudar na tarefa de explicitar
conceitos implícitos no código-fonte. Esses padrões facilitam a compreensão
dos conceitos sobre o modelo, conforme descrito a seguir.

Interface de intenção revelada


Ao adotar esse padrão no código, o desenvolvedor passa a utilizar nomes em
métodos ou classes que dizem exatamente “o que” essas classes ou métodos
fazem, mas não “como” elas fazem. Dizer “como” no nome do método quebra
o encapsulamento, uma vez que quem chama o código saberá detalhes de
implementação. Por exemplo, um vendedor em uma loja de sapatos pode
8 Domain-driven design

querer imprimir a nota fiscal após o pagamento do produto, para que o


cliente receba uma cópia física impressa ou virtual. Conforme mostra a
Figura 2, apenas observando o nome do método “emitir”, na classe Emitir,
não é possível saber o que esse método faz. O que ele emite: uma nota fiscal,
um recibo? O que ele faz com a “Nota” que ele recebe como parâmetro?
É preciso analisar a implementação para saber o que está acontecendo, de
fato, nesse método.

Figura 2. Listagem de código sem o padrão de interface de intenção revelada.

Para tornar o código da classe Emitir mais claro, utiliza-se o padrão de


interface de intenção revelada. O código deve ser alterado para expressar mais
detalhes do que fazer, e não de como fazer (Figura 3).

Figura 3. Listagem de código com o padrão de interface de intenção revelada.


Domain-driven design 9

Funções sem efeitos colaterais


A adoção desse padrão visa a tentar deixar o código com o maior número
possível de métodos que não alterem o estado dos objetos, possibilitando
esse tipo de operação (alteração de estado) apenas por meio da execução de
comandos.

Asserções
A adoção desse padrão significa que, para qualquer comando que altere estados
de objetos, deve-se criar testes de unidade que rodem automaticamente. Pode-se
também colocar asserções no código, que validem os comandos após a sua
chamada no código-fonte, seguidas de alterações do estado, que são esperadas
como resposta às asserções descritas.
Os padrões oferecidos pelo DDD refatoram o modelo, de maneira a refinar
o domínio do software, sempre primando pelo alinhamento do modelo à rea-
lidade em que o software será implantado. Nesse sentido, o uso dos padrões
fornecidos pelo DDD é de suma importância durante todo o processo de
desenvolvimento do domínio do software, ou seja, da modelagem do domínio
até a sua concepção por vias de fato, traduzidas em linhas de código.

Acesse o link a seguir e saiba mais sobre refatoração.

https://qrgo.page.link/qf8G3

Aspectos da aplicação do DDD e de seus blocos


de construção
O desenvolvimento de software com base nos conceitos do DDD apresenta
claramente aspectos vinculados ao padrão de modelagem. A Figura 4 traz um
diagrama genérico, que apresenta os principais aspectos de uma modelagem
totalmente voltada para especificar o domínio de software.
10 Domain-driven design

Figura 4. Mapa de navegação da modelagem do DDD.


Fonte: Adaptada de Evans (2004).

Para um melhor entendimento dos elementos presentes no diagrama, veja


abaixo a descrição de cada um deles.

 Entidades: todo objeto que carrega em seu código um conjunto de


características que definem sua identidade e de comportamentos
específicos da modelagem de cada domínio de software recebe a
nomenclatura de entidade. As entidades devem ser mantidas em uma
linha de continuidade, muito embora seu ciclo de vida possa vir a
se alterar tanto em forma como em conteúdo. Em outras palavras,
entidade é tudo aquilo que é importante para a concepção geral do
domínio do software e para que ele possua uma identidade alinhada às
regras do domínio de negócio; por exemplo, as características de um
cliente, se ele é um cliente convencional ou um cliente VIP, etc. Por
exemplo, um cliente pode realizar um cadastro de seu cartão de crédito
no software, pode colocar algum objeto de seu interesse no carrinho
de compras e pode efetuar o pagamento de sua compra conforme a
forma de pagamento escolhida no momento do cadastro, conforme
exemplifica Evans (2004).
Domain-driven design 11

 Objetos de valor: esse aspecto de modelagem do DDD nada mais é


do que uma descrição do domínio — não possui nenhuma identidade
conceitual ou descreve uma característica, apenas carrega valores;
porém, não possui distinção de identidade. Os objetos são as realizações
das entidades em tempo de execução, ou seja, são instanciados para
representar o design de domínio do sistema. Tecnicamente, são apenas
instâncias de entidades, que carregam atributos que são imutáveis — a
partir do momento que são instanciadas ou criadas, as mesmas não
podem ser alteradas. Não existe a necessidade de serem mantidas em
um banco de dados, pois o seu uso é local, para que sua utilização seja
mais rápida. Por exemplo, para somar o valor de todos os produtos
inseridos no carrinho de compras, na tela de pagamento destinada ao
cliente, os valores de cada produto não devem ser modificados durante
toda a realização da operação, conforme leciona Evans (2004).
 Serviços: os serviços são operações que são oferecidas por meio de
interfaces e/ou classes abstratas via codificação e que podem ser facilmente
encontradas isoladas do domínio do software. Nesse ponto, as classes
carregam o conhecimento específico e necessário para implementar, por
vias de fato, as regras de negócio do domínio do software. No entanto,
não pertencem a uma entidade específica, muito menos a um objeto de
valor. Os serviços em si não guardam estado algum. Em outras palavras,
toda chamada a um serviço, com uma mesma pré-condição, deve retornar
sempre o mesmo resultado. Normalmente, os serviços são omitidos da
visão do usuário, sendo acessados unicamente por trás de uma interface
do usuário, conforme aponta Evans (2004).
 Módulos: os módulos são entendidos como pacotes que encapsulam; em
outras palavras, são componentes que carregam o arcabouço necessário
para um conjunto de características específicas. Por exemplo, o módulo
de vendas armazena todos os aspectos relacionados à venda, o módulo
do cliente armazena aspectos do cliente, e assim por diante, para cada
especificidade definida no design do software. Os módulos ilustram
duas visões do modelo: eles podem verificar as particularidades do
modelo, sem que sejam ofuscados pelo todo, ou, então, podem examinar
as ligações entre os módulos, em visões que desprezam particularidades
internas. Eles devem aparecer como sendo uma fração expressiva do
modelo na camada de domínio, pela qual descrevem a história do
domínio em uma escala maior. Os módulos devem progredir de acordo
com o resto do modelo; ou seja, é necessário refatorar os módulos ao
mesmo tempo que o modelo e o código, conforme aponta Evans (2004).
12 Domain-driven design

 Agregados: agregados ou agregações delimitam o próprio modelo,


determinando uma propriedade e limites claros e bem-definidos,
impedindo um emaranhado caótico de objetos. Esse fator é essencial
para preservar a integridade em todas as fases do ciclo de vida. O
agregado é tido como um conjunto de objetos associados, que são
considerados como uma unidade, com o objetivo de efetuar alterações
sobre os dados que, mais tarde, serão armazenados. Cada agregado
contém uma raiz e um limite. O que está no interior do agregado é o
limite. A raiz consiste em uma entidade única e específica contida no
agregado. A raiz é o único elemento pelo qual objetos externos são
autorizados a fazer referências; entretanto, os objetos que pertencem
àquele limite podem efetuar referências uns aos outros, conforme aponta
Evans (2004).
 Fábricas: assim como uma interface de um objeto deve encapsular sua
implementação, deixando que o cliente use o comportamento do objeto
sem ter conhecimento da maneira como ele funciona, uma fábrica deve
encapsular o conhecimento para construir um objeto complexo ou um
agregado, a partir de um conjunto de objetos. Para que isso seja possível,
é preciso gerar uma interface que reflete as intenções do cliente e uma
visão abstrata do objeto construído. A fábrica, quando utilizada de
forma correta, auxilia a manter o DDD em seu curso. A saber, a fábrica
não faz parte do modelo, porém, ela pertence ao domínio, conforme
leciona Evans (2004).
 Repositórios: nada mais são do que um conjunto de classes responsáveis
pelo gerenciamento do ciclo de vida dos objetos, sendo entidades, objetos
de valor e agregados. Eles concentram operações de criação, alteração
e remoção dos objetos. Objetos são requisitados pelos clientes por meio
dos repositórios, empregando-se métodos de consulta que selecionam
objetos de acordo com critérios descritos pelo cliente, sendo esses
critérios, na maioria das vezes, o valor de certos atributos, conforme
orienta Evans (2004).

Este capítulo abordou os conceitos básicos do DDD; porém, salienta-se que


esses conceitos não são aprofundados. Seria interessante realizar pesquisas
sobre a aplicação do DDD em um problema real. Também é importante
realizar buscas relacionadas aos conceitos aqui discutidos, especialmente
em repositórios de códigos abertos de projetos desenvolvidos e documentados,
com o intuito de aprofundar seus conhecimentos.
Domain-driven design 13

Acesse o link a seguir e saiba mais sobre reúso de código.

https://qrgo.page.link/832fE

BRAUDE, E. J. Projeto de software: da programação à arquitetura: uma abordagem


baseada em Java. Porto Alegre: Bookman, 2005.
CUKIER, D. DDD — introdução a Domain-driven Design. Agile and Art, 2010. Disponí-
vel em: http://www.agileandart.com/2010/07/16/ddd-introducao-a-domain-driven-
-design/. Acesso em: 1 jul. 2019.
EVANS, E. Domain-driven design: tackling complexity in the heart of software. Boston:
Addison Wesley Professional, 2004.
FIRMINO, G. L. B.; ZANELATO, A. P. A. Desenvolvimento de camadas utilizando DDD.
Etic, v. 10, n. 10, 2014.
SOMMERVILLE, I. Engenharia de software. 8. ed. São Paulo: Pearson, 2007.
TUCKER, A.; NOONAN, R. Linguagens de programação: princípios e paradigmas. Porto
Alegre: AMGH, 2009.

Leituras recomendadas
BARBOSA, A. M. S. et al. Website empresarial com arquitetura MVC utilizando DDD
e angularjs. RE3C — Revista Eletrônica Científica de Ciência da Computação, v. 11, n. 1,
2016. Disponível em: http://revistas.unifenas.br/index.php/RE3C/article/view/167/112.
Acesso: 1 jul. 2019.
BOOCH, G. Object-oriented analysis and design with applications. 2. ed. Massachusetts:
Addison Wesley Longman, 1998.

Você também pode gostar