Alura > Cursos de Programação > Cursos de Node.JS > Conteúdos de Node.JS > Primeiras aulas do curso DDD: fundamentos do design orientado a domínio

DDD: fundamentos do design orientado a domínio

Entendendo o desafio do negócio - Apresentação

Apresentando o instrutor e o curso

Olá, boas-vindas ao nosso curso de Domain Driven Design aqui na Alura. Eu sou Vinícius Albano, seu instrutor. Sou formado em Ciência da Computação e trabalho com desenvolvimento back-end, principalmente focado em Node.js nos últimos 10 anos. Sou fundador e gestor da comunidade Domain Driven Design Brasil.

Audiodescrição: Vinícius é um homem branco com cabelo cacheado castanho. Ele está vestindo um casaco verde e se encontra no estúdio da Alura, com uma iluminação roxa ao fundo.

Destacando o público-alvo e objetivos do curso

Se você é uma pessoa desenvolvedora, líder técnica ou até mesmo gerente de tecnologia que deseja se aprofundar nas questões de processo de desenvolvimento mais focadas no negócio, e quer aprender como resolver as dores dos clientes e entregar produtos que realmente agregam valor, este curso foi elaborado para você.

Neste curso, nós vamos aprender a identificar os principais desafios do ponto de vista do negócio. Vamos explorar os fundamentos do Domain Driven Design e suas principais ferramentas. Também aprenderemos sobre linguagem ubíqua, descoberta de domínios, subdomínios, contextos delimitados e os principais padrões táticos de desenvolvimento, além de como aplicá-los.

Explicando o escopo e pré-requisitos do curso

Vale ressaltar que este curso é um curso de fundamentos. Não desenvolveremos um projeto ao longo deste curso, mas ofereceremos uma visão completa sobre o panorama do Domain Driven Design (Design Orientado a Domínio), abordando os principais fundamentos, autores e técnicas. Isso não significa que não veremos casos práticos e aplicações para o dia a dia.

Para aproveitar ao máximo esta jornada, é recomendado que tenhamos alguns pré-requisitos. Primeiramente, é importante ter noções básicas de arquitetura e engenharia de software, compreendendo como funcionam as principais arquiteturas, padrões e nomenclaturas na comunidade de desenvolvimento de software. Além disso, é desejável possuir algum conhecimento básico sobre desenvolvimento de sistemas. Não é necessário saber realizar integrações avançadas ou adotar os padrões mais recentes de desenvolvimento.

Enfatizando a metodologia e atividades do curso

Este curso focará em como podemos aprender ao máximo com a equipe atual, com os profissionais com quem temos contato, adquirindo o conhecimento deles e transformando-o em um software robusto que atenda às nossas necessidades.

Além do conteúdo em vídeo, teremos diversas atividades que ajudarão a consolidar nosso conhecimento. Estamos confiantes de que isso contribuirá para nos tornarmos profissionais cada vez melhores.

Vamos prosseguir para os próximos vídeos. Nos encontramos lá!

Entendendo o desafio do negócio - O preço de não entender o negócio

Introduzindo o curso de Domain Driven Design

Sejam muito bem-vindos ao nosso curso de Fundamentos do Domain Driven Design (Design Orientado por Domínio). Estamos muito felizes em tê-los aqui conosco, aprendendo sobre DDD. Temos certeza de que isso revolucionará suas vidas como pessoas desenvolvedoras, ajudando em projetos pessoais, no trabalho, a criar projetos mais robustos e a elevar a senioridade profissional.

Antes de abordarmos os fundamentos do DDD e como aplicá-los na prática, é importante entendermos o contexto. Por que o DDD é tão importante? Por que é tão utilizado? Será que é apenas uma moda ou realmente faz diferença em nossos projetos? Para entender isso, vamos discutir um caso de uso real: o healthcare.gov, um projeto desenvolvido pelo governo dos EUA para matrículas de cidadãos americanos no sistema de saúde.

Analisando o caso do healthcare.gov

Vamos falar sobre o custo de não entender o domínio. O healthcare.gov é um exemplo emblemático, com um custo estimado inicialmente em 93 milhões de dólares, que após três anos de desenvolvimento ultrapassou 1,7 bilhões. Mais de 50 empresas e 500 desenvolvedores estiveram envolvidos, mas o projeto fracassou no dia do lançamento. Apenas seis pessoas conseguiram se cadastrar no sistema de saúde no primeiro dia, quando a expectativa era de milhares.

O healthcare.gov foi lançado em outubro de 2013, e, como mencionado, apenas seis pessoas conseguiram finalizar o cadastro, apesar de quatro milhões de visitantes no primeiro dia. Isso indica que problemas ocorreram. Como é possível ter quatro milhões de visitantes e apenas seis cadastros? Os testes mostraram que o sistema suportava apenas cerca de mil pessoas simultaneamente, quando deveria suportar entre 50 a 60 mil.

Identificando problemas de domínio

Pode-se pensar que houve muitos problemas técnicos, com tantas empresas e desenvolvedores envolvidos, mas o principal problema foi de domínio. Após meses de investigação, constatou-se que o problema não era a tecnologia ou a falta de experiência dos desenvolvedores, mas sim o entendimento do domínio. As pessoas envolvidas não compreendiam bem o sistema de saúde dos EUA ou o processo de cadastramento dos cidadãos. Houve um desalinhamento entre o funcionamento esperado do sistema e o que foi implementado, faltando entendimento do negócio. Isso gerou problemas técnicos, como falhas de integração entre sistemas e comunicação inadequada entre equipes, mas a principal causa foi o desalinhamento sobre o negócio.

Explorando débitos técnicos e de domínio

Com isso, podemos discutir a diferença entre débito técnico e débito de domínio. Vamos falar sobre débito técnico. Como pessoas desenvolvedoras, já devemos estar familiarizados com isso. Sob pressão para entregar projetos, muitas vezes abdicamos de detalhes para cumprir prazos, acumulando débitos técnicos. Exemplos incluem testes insuficientes, código duplicado, acoplamento excessivo e performance ruim. Esses problemas são comuns, mas há questões mais graves relacionadas ao domínio.

O primeiro débito de domínio que discutiremos é a modelagem inconsistente. Ao longo do curso, falaremos sobre modelos e como traduzi-los para software. É importante entender que o modelo é uma abstração de um conceito da realidade. No caso do healthcare.gov, o domínio é saúde, um sistema de cadastro de cidadãos. Provavelmente teríamos conceitos como plano de saúde, paciente, tratamento e formas de pagamento. Esses conceitos têm atributos, regras e relações, mas ao abstraí-los para o software, criamos um modelo. O modelo é uma abstração do conceito real para o sistema, focando no que é importante para o software resolver. Não precisamos de todas as informações de um cidadão americano, apenas das relevantes para o sistema de saúde.

Compreendendo a modelagem e as regras de negócio

Quando realizamos uma modelagem incorreta, significa que nosso modelo não possui informações suficientes para resolver o problema do nosso domínio. No caso do healthcare.gov, se fizermos uma modelagem incorreta de paciente ou de plano de saúde, isso indica que as entidades do nosso sistema não estão resolvendo o problema que nossos stakeholders esperam solucionar.

Um problema de débito de domínio é a má compreensão das regras de negócio. Isso ocorre quando, mesmo que a entidade tenha sido modelada corretamente, as regras de negócio não foram bem entendidas. As interações entre as entidades não são bem compreendidas, e as pessoas desenvolvedoras do projeto não entendem como funciona o sistema de inscrição dos estados americanos no sistema de saúde. Sem uma compreensão clara das regras de negócio, não conseguimos traduzir isso para o software, o que gera débitos técnicos.

Alinhando a linguagem e representando processos

Outro exemplo é a linguagem inconsistente. É crucial que haja um alinhamento de linguagem entre o time de negócios, os stakeholders externos e as pessoas desenvolvedoras. Se uma pessoa desenvolvedora fala "usuário", um stakeholder externo fala "cliente" e uma equipe de negócios fala "paciente", há um desalinhamento semântico. Se diferentes equipes de desenvolvimento consultam especialistas de negócios distintos e cada uma modela de acordo com uma perspectiva diferente, isso cria um débito técnico, pois não houve uma tradução correta dos requisitos. Termos diferentes para a mesma coisa resultam em modelos diferentes, e casos de uso distintos podem ser modelados de acordo com regras e nomes diferentes, gerando problemas na integração entre os times e sistemas do projeto.

Por fim, temos processos mal representados. Isso ocorre quando não compreendemos completamente os casos de uso, do início ao fim. No caso do healthcare.gov, por exemplo, uma pessoa pode começar preenchendo um formulário, o que parece simples, mas envolve três ou quatro sistemas diferentes. É necessário entender de onde os dados vêm, se o formulário é uma etapa única ou várias, e quais são as entidades de negócio responsáveis por cada etapa do cadastro. Sem uma visão abrangente do sistema de saúde, podemos modelar incorretamente o processo como um todo. Precisamos entender o início, o meio e o fim do processo, como as partes interagem, para traduzir corretamente para a parte técnica e integrar os diferentes sistemas. Quando stakeholders usam termos diferentes, devemos traduzir, por exemplo, de "paciente" para "cliente", dependendo do contexto.

Avaliando o impacto dos débitos de domínio

Débitos de domínio são um grande problema, pois débitos técnicos podem ser resolvidos com identificação de bugs, implementação de testes, resolução de problemas de banco de dados e refatoração. No entanto, débitos de domínio indicam que o software está resolvendo o problema errado. Se não estamos alinhados com o time de negócios e não entendemos o domínio do sistema, provavelmente implementaremos tudo errado, o que é muito mais custoso para corrigir. Será necessário realinhar os times, redescobrir o domínio e remodelar o sistema, o que é dispendioso.

O débito de domínio se traduz em débito técnico quando há falha de entendimento do negócio, erro conceitual ou modelo gerado de forma equivocada. Com um modelo errado, a implementação será incorreta, e os testes validarão coisas erradas. Quando o usuário interagir com o sistema, haverá falhas e bugs devido à falta de compreensão do negócio. Isso se torna um problema técnico, pois a implementação não foi correta, gerando insatisfação do usuário e retrabalho para os times de desenvolvimento e negócios.

Concluindo com a importância do alinhamento inicial

Um desalinhamento no início do projeto gera débitos técnicos e problemas que precisam ser corrigidos ao longo do tempo, sobrecarregando o time de desenvolvimento, atrasando lançamentos e estourando o orçamento. O débito de domínio é extremamente custoso, pois gera retrabalho completo do projeto. Quando débitos de domínio se acumulam, criam um problema chamado "grande bola de lama", que discutiremos na próxima aula. A maioria dos sistemas que falham é devido a essa questão. Estimamos que um débito de domínio seja 10 vezes mais caro que um débito técnico, pois também gera débitos técnicos e retrabalho no sistema. Vamos explorar o conceito de "grande bola de lama" e como resolvê-lo em breve.

Entendendo o desafio do negócio - Entendendo o conceito de "grande bola de lama"

Discutindo a importância do entendimento do negócio

Agora que entendemos a importância de compreender o negócio e os problemas que surgem quando não o fazemos, como prejuízos e retrabalho, vamos discutir um conceito interessante que ocorre na ausência de entendimento de software, além da acumulação de débitos de domínio e débitos técnicos.

Ao observarmos uma imagem com diversos fios interlaçados, percebemos que cada fio segue em direções diferentes, tornando difícil entender o que está acontecendo. Isso é semelhante ao funcionamento dos softwares quando acumulamos débitos técnicos e de domínio. Diversas funcionalidades se entrelaçam, perdendo a estrutura de relação entre elas. Inicialmente, um sistema pode estar bem organizado, mas, com a pressão por entregas e a falta de entendimento do domínio, perdemos a separação entre os componentes e camadas do sistema, resultando em dificuldades de manutenção. Essa imagem representa bem um sistema legado, com código desorganizado, gerando bugs e confusão, paralisando o desenvolvimento de novas funcionalidades.

Identificando sinais de alerta em sistemas desorganizados

Vamos entender como identificar o início desse problema para evitar que nossos sistemas reais cheguem a essa situação caótica. Alguns sinais de alerta são importantes para observarmos em nossas organizações e projetos. O primeiro sinal é quando ninguém entende o sistema como um todo. Se uma parte do sistema se torna difícil de compreender, devemos acender um alerta. Será que o sistema está complexo demais? Devemos considerar refatorações, isolar responsabilidades ou refinar nosso entendimento do domínio para simplificar modelos e regras de negócio. Quando ninguém conhece bem o funcionamento do sistema, é provável que haja responsabilidades misturadas, exigindo simplificação.

Outro alerta é quando uma mudança simples afeta todo o sistema. Isso ocorre quando alteramos algo no front-end e quebramos relações com o banco de dados ou outras áreas não relacionadas. Isso indica alto acoplamento e falta de distinção entre áreas, sugerindo a necessidade de separação em camadas ou sistemas distintos. Modificações em um lado não devem quebrar o outro, e uma modelagem inadequada pode gerar problemas.

Explorando as consequências de um sistema desorganizado

Um sintoma comum é quando apenas uma pessoa, como o João, entende o funcionamento de uma parte do sistema. Isso é problemático, pois, se essa pessoa sair, a empresa enfrentará dificuldades para desenvolver novos recursos e transferir conhecimento para outras áreas. Outro sinal é a necessidade de reescrever tudo do zero, indicando um código desorganizado e difícil de manter. Isso sugere que o domínio foi mal modelado, exigindo redescoberta e reestruturação das regras de negócio para separar áreas.

Esses sintomas são importantes para observarmos. Entendemos agora algumas consequências para o negócio quando o software se torna desorganizado. O primeiro impacto é o aumento dos custos de produção e atrasos na entrega. A desorganização impede a compreensão das regras de negócio e o desenvolvimento, gerando atrasos e custos elevados. Além disso, há impacto no time. Se uma pessoa chave, como o João, sair, o conhecimento se perde. O onboarding de novas pessoas desenvolvedoras também é afetado pela complexidade do sistema, dificultando a integração de novos membros à equipe.

Analisando a queda na velocidade de desenvolvimento

Se tivermos um código ou uma aplicação mais bem estruturada, com áreas segregadas e modelos de negócios mais concisos, torna-se muito mais fácil explicar para uma nova pessoa do time qual é a responsabilidade de cada área e o significado de cada funcionalidade. Assim, essa pessoa consegue começar a contribuir para o time de forma mais rápida. No entanto, se o sistema estiver desorganizado, isso se torna muito difícil.

Um exemplo que podemos observar é a queda na velocidade de desenvolvimento. No início de um projeto, quando a separação está bem feita, o desenvolvimento é acelerado. Conseguimos entregar uma nova funcionalidade em uma ou duas semanas. Porém, à medida que a estrutura do sistema se perde e tudo se torna interligado sem uma divisão clara, a manutenção se torna cada vez mais difícil. Uma nova funcionalidade que antes era entregue em uma semana pode começar a levar duas, três semanas, um mês ou até mais. Em alguns casos, pode se tornar tão complicado que nem conseguimos iniciar o desenvolvimento dessa nova funcionalidade, pois ninguém entende exatamente onde ela deveria se encaixar. Isso representa um grande problema.

Compreendendo a insatisfação do cliente e o conceito de "grande bola de lama"

Outra consequência significativa é a insatisfação do cliente. Se não conseguimos mais entregar funcionalidades e atender aos propósitos do cliente, ele provavelmente buscará outro prestador de serviço ou abandonará o projeto, optando por soluções manuais em vez de um software. Essas consequências são bastante graves.

Compreendendo alguns sintomas e consequências, vamos formalizar esse problema. Esse emaranhado de fios, essa desordem no software, quando tudo está misturado, é conhecido como código espaguete, um antipadrão ou anti-arquitetura de software chamado de "grande bola de lama". Formalmente, isso significa um sistema sem arquitetura coerente, com alto acoplamento, regras espalhadas e nomes genéricos. Como mencionado anteriormente, ninguém tem uma boa noção de como o sistema funciona. Tudo está misturado, com regras de negócio espalhadas por todo lado. Ao modificar uma parte, outra pode ser afetada. Os nomes são genéricos, pois não houve uma modelagem de domínio coerente traduzida para o software. Tudo é abstrato, dificultando a extração de conhecimento dos nomes das classes e métodos. Isso resulta na "grande bola de lama".

Identificando sintomas e causas da "grande bola de lama"

Os sintomas incluem classes gigantes, nomes genéricos e dependências circulares, onde A depende de B, que depende de C, e C depende de A. Essas referências circulares tornam a manutenção do sistema desafiadora sem causar problemas. Além disso, há métodos que fazem tudo, como um controller que valida a entrada, chama regras de negócio, acessa o banco de dados, valida a saída e formata dados, tudo em um só lugar, dificultando a extração de responsabilidades.

A causa disso pode ser atribuída à falta de alinhamento técnico, ausência de separação e não adoção de uma arquitetura limpa e código limpo. Isso gera a "grande bola de lama", mas o principal fator que perpetua essa situação é a falta de alinhamento do domínio. Débitos técnicos podem ser resolvidos com arquitetura em camadas, testes e modularização do código. No entanto, sem entendimento do domínio, as regras de negócio e termos não estarão bem modelados, resultando em partes do sistema misturadas.

Explorando a complexidade essencial e a mistura de conceitos

Por exemplo, uma classe "paciente" pode conter dados de login, pagamento e outros relacionados ao sistema de saúde. Ou pior, tudo pode estar em uma classe "usuário", extremamente genérica, com dados de diversos contextos da aplicação. Sem entendimento do negócio, estamos fadados a criar uma "grande bola de lama", com sistemas acoplados devido à falta de separação de contextos distintos do negócio.

O grande problema é misturar conceitos técnicos com contextos de negócio. Misturamos questões de banco de dados, arquitetura de APIs e complexidades do negócio, onde termos distintos são usados para a mesma coisa. Uma pessoa pode ser um paciente e também um cliente em outra área do sistema. Essa mistura gera um grande problema, conhecido como complexidade essencial, que é a complexidade do modelo de domínio em relação à complexidade de arquitetura e tecnologia.

Na próxima aula, discutiremos mais sobre isso. Para concluir, a "grande bola de lama", esse antipadrão arquitetural onde tudo está misturado, é um sintoma de algo mais profundo: a mistura entre o que é difícil de ser feito, mas deve estar no sistema, e o que é complexo por acidente. Em breve, falaremos mais sobre isso.

Sobre o curso DDD: fundamentos do design orientado a domínio

O curso DDD: fundamentos do design orientado a domínio possui 387 minutos de vídeos, em um total de 72 atividades. Gostou? Conheça nossos outros cursos de Node.JS em Programação, ou leia nossos artigos de Programação.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Node.JS acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas