O objetivo desta palestra é mostrar como é possível evoluir e reescrever partes de uma aplicação legada com mais 5 anos em produção utilizando técnicas de uma parte Domain Driven Design conhecida como Strategic Design. É uma aplicação web escrita em Python e Django que suporta a operação de um grupo focado em medicina do trabalho, com clínicas espalhadas pelo país.
Nesta palestra vamos mostrar uma abordagem que pode ajudar times que precisam lidar com aplicações legadas grandes e complexas no caminho da modernização.
4. Sistema para um empresa de medicina do trabalho
realizar atendimentos de medicina ocupacional por
todo o Brasil e fornecer uma análise inteligente
sobre o perfil dos colaboradores de uma empresa.
5. Mas como todo projeto, no
início, tudo é muito
simples…
10. •bugs e mais bugs
•altera uma parte, quebra outra
•bug em uma parte, sistema fora do ar
•demora nas entregas
•pressão do cliente para entregar mais
os problemas começaram…
16. • lógica de domínio espalhada em
Controllers, Models e Services
• models espelhando exatamente o
modelo de dados
• foco no framework e não no domínio
do problema
22. Strategic Design
…modeling and design decisions that
apply to large parts of the system. Such
decisions affect the entire project and
have to be decided at team level.
“Domain Driven Design, Chapter 14 - Maintaining Model Integrity", pág: 335
Eric Evans - Blue Book
23. Strategic Design
…modeling and design decisions that
apply to large parts of the system. Such
decisions affect the entire project and
have to be decided at team level.
“Domain Driven Design, Chapter 14 - Maintaining Model Integrity", pág: 335
Eric Evans - Blue Book
26. Not all of a large system will be
well designed.
Eric Evans on Strategic Design presentations
https://www.infoq.com/presentations/strategic-design-evans
27. Total unification of the domain
model for a large system will
not feasible or cost-effective
“Domain Driven Design, Chapter 14 - Maintaining Model Integrity", pág: 332
Eric Evans - Blue Book
30. Bounded Context
…delimits the applicability of a particular
model so that team members have a clear
and shared understanding of what has to
be consistent and how it relates to other
contexts.
“Domain Driven Design, Chapter 14 - Maintaining Model Integrity", pág: 336
Eric Evans - Blue Book
31. Bounded Context
…delimits the applicability of a particular
model so that team members have a clear
and shared understanding of what has to
be consistent and how it relates to other
contexts.
“Domain Driven Design, Chapter 14 - Maintaining Model Integrity", pág: 336
Eric Evans - Blue Book
32. Bounded Context
…delimits the applicability of a particular
model so that team members have a clear
and shared understanding of what has to
be consistent and how it relates to other
contexts.
“Domain Driven Design, Chapter 14 - Maintaining Model Integrity", pág: 336
Eric Evans - Blue Book
38. Paciente
Atendimento
+ qual nome, nascimento…?
+ qual dia do agendamento?
+ qual empresa pertence?
+ qual é a função que exerce?
Paciente
Gestor de Periódicos
+ qual é o proximo exame?
+ quantos dias faltam para vencer?
Paciente
Financeiro
+ qual custo dos exames feitos?
+ alguma condição de desconto?
É responsabilidade de cada
contexto modelar os dados
da melhor maneira, de
acordo com a as suas
responsabilidades.
41. Bounded Context
Domain LayerApplication Layer
use case
use case
use case
Repository
Entity
Value Object
Infrastructure Layer
Entity
DAO
Logger
Service
Module
45. Todas as regras de negócio são
programadas aqui. Normalmente são
objetos python puros, sem relação com
persistência ou infra-estrutura
Expostas
através de
casos de uso
48. …An alternative route is to gradually
create a new system around the edges of
the old, letting it grow slowly over several
years until the old system is strangled.
www.martinfowler.com/bliki/StranglerApplication.html
53. O isolamento do legado se dá através de indireções nos objetos da fronteira. Nesta
visão de alto nível, é possível ver como uma funcionalidade é anexada ao código do
Legado. A ideia básica é o novo módulo definir um conjunto de interfaces/conectores
para troca de informações.
Em uma abordagem de lib, estes
conectores se materializam em um
conjunto de interfaces que devem ser
implementadas pela Lib.
fronteira do sistema
Inicialmente, os novos contextos são
projetos novos, que devem funcionar
como Libs. Deve ser possível extrair a lib
para rodar em um runtime diferente
sem muitas dificuldades.
54. O que fazer quando é
preciso usar dados do
legado no módulo novo?
56. Um módulo ou contexto novo define um conjunto de interfaces
que serão implementadas diretamente no legado.
interfaces definidas pelo módulo
o contexto “Atendimento” depende de dados
que estão definidos no legado. Neste caso, o
módulo que necessita dos dados, define o
contrato de comunicação e o legado
implementa este contrato, reutilizando
objetos existentes ou escrevendo código
novo. O importante é que a definição das
interfaces é feita de acordo com as
intenções do módulo novo e não com os
detalhes do código legado
57. O que fazer se o legado
precisar de dados do
módulo novo?
59. A solução mais comum para este caso é o uso de eventos. O módulo
publica um conjunto de eventos e o legado assina estes eventos.
no lado do Legado, dentro da ACL, são definido
casos de uso que serão estimulados pelos
handlers de tratamento dos eventos.
o caso de uso PatientCheckin, durante
sua execução, publica o eventos
“PatientCheckedIn”. Este evento
contem os dados necessários para
comunicação com o legado,
normalmente serializado em um
JSON ou usando um Hash.
61. Este exemplo, mostra com a arquitetura permite separar os componentes
em runtimes diferentes, inclusive com banco de dados próprio.
aqui, a lib foi incluída em uma aplicação web e isolada
através de uma Anti-Corruption Layer (ACL). A
vantagem de se usar uma ACL é o isolamento do código
já criado. As alterações necessárias na lib são muito
pequenas e a própria ACL pode tratar os problemas de
comunicação com o legado, logar, lançar exceções, etc.
do lado do legado, a própria api já
funciona como uma ACL.
Normalmente esta api vai ser
implementada com Http puro,
usando formatos simples como
JSON para troca de dados
62. Chamadas diretas na api do legado ou através de uma
arquitetura event-driven.
Broker de mensagens, por exemplo:
JMS, ActiveMQ, RabbitMQ, etc
conjunto de EventHandlers
interessados nas mensagens