Domain-Driven Design
-
Upload
comunidade-netponto -
Category
Technology
-
view
2.086 -
download
1
description
Transcript of Domain-Driven Design
Domain Driven DesignJoão Nicolau Oliveira
http://netponto.org16ª Reunião Presencial - 11/12/2010
João Oliveira- Licenciado na Faculdade de Ciências de Lisboa- 12 anos de experiência em TI- Adepto das metodologias ágeis- Release Manager na Solutions Factory
C#ASP.Net
WPFWCFDNN
jQuery
DelphiJava
Zope
Citação...
«Domain modeling is not a matter of making as “realistic” a model as possible. It is more like moviemaking, loosely representing reality to a particular purpose.»
Eric Evans
Agenda
• O que é? Quando usar? Como?• Ubiquous Language, Bounded Contexts,
Integração Contínua, Context Map, Persistence Ignorance
• Command and Query Responsability Segregation• Patterns: Value Object, Entity, Aggregate, Factory,
Repository, Unit Of Work, Specification
Também disponível em vídeo...
Assista!http://www.vimeo.com/21488644
O que é DDD?– Focalização no domínio• Um domínio é um âmbito. • É definido por um conjunto de características que descrevem
uma família de problemas para os quais procuramos uma solução.• A análise do domínio identifica, captura e organiza
informação para que seja reutilizável aquando da criação de novos sistemas.
O que é o modelo do domínio?
O que é o modelo do domínio?
É uma representação
O que é DDD?– Focalizar no modelo• Elaborar uma representação abstracta do domínio que nos
ajude a cumprir o propósito
– Linguagem omnipresente• Os peritos do domínio e os programadores partilham uma
linguagem comum
– É Object-Oriented e combina bem com outras metodologias ágeis• TDD, BDD, … Reduz complexidade/facilita manutenção.
Quando usar?– Projectos em que os desenhadores do modelo estão
dispostos a “pôr as mãos na massa”– Colaboração efectiva entre peritos do domínio e os
developers– Abertura para explorar e experimentar (os primeiros
modelos não são satisfatórios)– Contexto explicito e bem definido– Apenas adequando para o núcleo do domínio
Modelar - Como?
• Processo de melhoria, ajuste, adaptação, aprendizagem, experimentação
Modelos Emergentes
Linguagem Omnipresente
Linguagem Omnipresente
Peritos de Domínio
Só nos entendemos se falarmos a mesma língua
Linguagem Omnipresente
Peritos de Domínio Programadores
Só nos entendemos se falarmos a mesma língua
Linguagem Omnipresente
Peritos de Domínio Programadores
Só nos entendemos se falarmos a mesma língua
Linguagem Omnipresente
Peritos de Domínio Programadores
Só nos entendemos se falarmos a mesma língua
Linguagem Omnipresente
Peritos de Domínio Programadores
Só nos entendemos se falarmos a mesma língua
“Alhos”
Linguagem Omnipresente
Peritos de Domínio Programadores
Tradução complexa
Só nos entendemos se falarmos a mesma língua
“Alhos”
Linguagem Omnipresente
Peritos de Domínio Programadores
Tradução complexa
“Bugalhos?”
Só nos entendemos se falarmos a mesma língua
“Alhos”
Linguagem Omnipresente
Peritos de Domínio Programadores
Só nos entendemos se falarmos a mesma língua
“Alhos”
MODELO
Linguagem Omnipresente
Peritos de Domínio Programadores
Só nos entendemos se falarmos a mesma língua
“Alhos”
MODELO
Linguagem Omnipresente
Peritos de Domínio Programadores
Só nos entendemos se falarmos a mesma língua
“Alhos”
MODELO
Linguagem Omnipresente
Peritos de Domínio Programadores
Só nos entendemos se falarmos a mesma língua
“Alhos”
Linguagem Omnipresente
• O nosso Modelo sustenta a nossa linguagem
Experts de Domínio Programadores
Negócio
Código
MODELO
Uma mesma linguagem para tudo
Nomes => ClassesVerbos => métodos, serviços, …Uma entidade empregadora coloca um anúncio de emprego:Classes: Job, JobBoardAcções: JobBoard.PostJob(Job)
O código também deve reflectir a linguagem.Exemplo:
Bounded Context
• Em projectos grandes temos vários modelos em jogo
• É importante circunscrever o contexto ao qual o modelo se aplica– Explicitar fronteiras relativamente às diferentes
equipas envolvidas, espaços físicos e repositórios de código e de dados
– Preocupar-se apenas em garantir consistência dentro dessas fronteiras
Continuous Integration
• Quanto maior é a equipa, maior é a tendência para fragmentar o modelo:– Instituir um processo de integração contínua que faça
merging do código e dos artefactos– Testes automatizados que detectem os erros ASAP
Context Map
• Os contextos de outros modelos podem ser vagos e estar em permanente mudança– Identificar todos os modelos em jogo (inclusivé
subsistemas não object-oriented)– Dar nomes a esses contextos e fazer com que esses
nomes se tornem parte da nossa linguagem ubíqua– Identificar os pontos de contacto e desenhar
tradutores.
Persistence Ignorance
Ignorar a Persistência– Porquê?• Não queremos um modelo data-driven• Queremos liberdade na escolha do mecanismo de
persistência dos nossos dados• Facilitar os nossos testes unitários e a abordagem TDD
– Como?• Adoptar frameworks de acesso a dados “DDD-friendly”• Rejeitar ORMs estilo Active Objects • Usar ORMs pouco intrusivos (Ex: NHibernate, EF4)• Tirar partido dos Repositórios e Agregados
Arquitectura DDD
Infrastructure
Domain Data Access
Application / Services
UI
Arquitectura DDD– Infrastructure• Funcionalidades genéricas que suportam as camadas
superiores• Componentes de UI• Utilitários
– Domain• Lógica e regras • Estado do negócio• É o núcleo/coração da aplicação
Arquitectura DDD– Application• Orquestrador, Serviços, Tarefas de negócio• Interacção com outros sistemas• Esta camada deve ser fina• Não deve ter regras nem conhecimentos do negócio• Não guarda o estado do negócio• Pode guardar estado do progresso de uma tarefa
– User Interface• Mostrar informação ao utilizador• Interpretar comandos
Single Responsability Principle
Gerar PDF ImprimirUma classe deve ter apenas uma razão para sofrer mudanças.
Se tivermos 2 razões para mudar então deveremos separar em duas classes distintas.
Martin, Robert C. (2002). Agile Software Development, Principles, Patterns, and Practices
Command and Query Responsibility Segregation
Diagrama de Mark Nijhof
AuditoriaBI
Agilidade
PerformanceSimplicidade
Commands Queries
CQRS – Divisão de tarefas e rentabilidade
Diagrama de Mark Nijhof
Equipa de baixo custo produz código sem exigências de qualidade.Ideal para outsourcing.
Equipa especializadaem UI
Equipa pequenaaltamente
qualificada
Command and Query Responsibility Segregation
• UI: Orientados à tarefa• Comandos: –Mudam o estado do domínio
• Event Store: –Armazena literalmente os eventos
• Query Store: Uma tabela por View (UI)– Exposta via SOA web services, WCF, WCF RIA
Os blocos de código
Patterns
Entidades
– São objectos definidos pela sua identidade (identificadores únicos)–A sua forma ou conteúdo podem mudar, mas a
identidade tem de ser preservada ao longo do ciclo de vida
Entidade
Entidades
– São ainda definidos por:• Responsabilidades• Estrutura• Comportamentos
–A persistência nunca é responsabilidade da entidade (não usar entidades com métodos CRUD)
Exemplo:
Cargo.csIEntity.cs
Value Objects
– Imutáveis–Uma mesma instância pode ser usada em várias
entidades– Se queremos um valor diferente então criamos
uma nova instância– Exemplos: Moradas, Dinheiro, Códigos e até
identificadores de entidades
Exemplo:
IValueObject.csItinerary.cs Leg.cs
Agregados
Raíz do Agregado
Fronteira
Agregados
É um agrupamento de objectos associados com os quais lidamos como se se tratassem de uma só unidade.–Dão consistência ao modelo–Definem relações de pertença–Definem fronteiras– Salvaguardam as invariantes (regras)
Agregados
–Qualquer mudança de estado tem de garantir sempre as invariantes do agregado.– Fronteira• Separa o interior do exterior
–Raiz• É sempre uma Entidade• Responsável por garantir as invariantes• Pode ser livremente referenciada do exterior
Agregados
–Os membros• Podem ser Entidades e Value Objects• Estas entidades apenas precisam de identidade
“local”• Os objectos exteriores não devem ver estes
membros fora do contexto da entidade raiz
Nested Aggregates
–Quando o membro do agregado referencia a raiz de outro agregado– Evitar encadeamentos com demasiada
profundidade– Exemplo de encadeamento:• Agregado Job Board (membros: Job)• Agregado Job (membros: Skill, Applicant)• Agregado Applicant (membros: ApplicantSkill)
Exemplo:
Cargo.cs Itinerary.cs Leg.cs Delivery.csRouteSpecification.cs
Agregado Cargo
Factory
–Criar (e reconstruir) os objectos e agregados mais complexos– Encapsular a estrutura interna–Para objectos simples usar somente o
construtor é suficiente–Deve ser uma operação atómica–Garantir todas as invariantes
Factory
–Diferentes tipos:• Standalone Factory• Factory Method– Util em aggregates– Situações em que temos um objecto com grande relação
de proximidade sobre o outro
• Abstract Factory• Builder (para fluent interfaces)
Factory
– E as invariantes onde pertencem?• Pode-se delegar a validação ao próprio produto• Em agregados pode ser melhor ter as regras
também na própria factory (porque tipicamente estão dispersas por vários objectos)
–Regras do membro Identificador de uma entidade ou dum Value Object têm existir na Factory
Exemplo:
Utilizamos internal no método construtor de Car para obrigar o projecto cliente a utilizar sempre a Factory na instanciação da classe Car.
Repositório e Unit Of Work• Repositório–Abstrai o acesso aos dados– Funciona como uma colecção de objectos em
memória: Add, Remove, Get, Count• Unit Of Work–Registar as alterações ao estado dos objectos–Gerir as transacções: Commit, Rollback• ISession (NHibernate), DataContext (LinqToSQL)
Citação...
«Leave transaction control to the client. (…) Transaction management will be simpler if the REPOSITORY keeps its hands off.»
Eric Evans
Repositório
–Um por cada Agregado–O agregado é sempre devolvido válido e
completo–Abstrair a implementação• Facilitar os testes unitários• Maior liberdade para mudar a implementação• Facilitar optimizações de performance• Implementar mecanismos de caching
Exemplo:
IUnitOfWork.csUnitOfWorkFactory.cs IRepository.cs IGenericRepository.cs
UnitOfWork.cs GenericRepository.csImplementação NHibernate
Exemplo:
IUnitOfWork.csUnitOfWorkFactory.cs IRepository.cs IGenericRepository.cs
UnitOfWork.cs GenericRepository.csImplementação NHibernate
Exemplo:
IUnitOfWork.csUnitOfWorkFactory.cs IRepository.cs IGenericRepository.cs
UnitOfWork.cs GenericRepository.csImplementação NHibernate
Repository Per Aggregate– GetById(int id)– GetByName(string name)– GetByCityAndState(City city, State state)– Add(Person person)– Count(), Sum()
• Uma classe Repositório por cada Agregado• Dá-nos mais trabalho do que o repositório
genérico mas permite-nos afinar melhor as queries
Generic Repository
• Uma classe genérica para todos os Agregados– GetById<TId>(TId id)– Query<T>(Expression<Func<T, bool>> query)– Insert<T>(T entity)– Delete<T>(T entity)
• Ex: new Repository<Person, int>(…)– GetById (20)– Query (p => p.Idade > 20)
Tipo Entidade
Tipo Identificador
IQueryable com Paginação
IQueryable com Paginação
IQueryable com Paginação
IQueryable com Paginação
Specification• Pode ser usada para:– Validar um objecto e verificar se cumpre certos requisitos ou se
está preparado para um dado propósito– Seleccionar um objecto de uma colecção– Especificar as características de um objecto que vai ser
instanciado
• Podemos passar ao repositório com a especificação dos critérios de pesquisa traduzidos para a linguagem de acesso aos dados (SQL/Linq/NHibernate).
Exemplo:
ISpecification.cs AbstractSpecification.cs
NotSpecification.csOrSpecification.cs
RouteSpecification.cs
Resumo
– Entidade (Tem identidade)–Value Object (Imutável)–Aggregate (Garante consistência)– Factory (Facilita início do ciclo de vida)–Repository (Faz gestão da persistência)– Specification (Definir requisitos/características)
Dúvidas?
ReferênciasDomain-Driven Design: Tackling Complexity in the Heart of Software Eric Evans
Applying Domain-Driven Design and Patterns Jimmy Nilsson
ReferênciasDomain Driven Design Community
– http://domaindrivendesign.org/
Apresentação Domain driven Design - Catapult Systems– http://www.slideshare.net/panesofglass/domain-driven-design
Unit Of Work - Martin Fowler– http://martinfowler.com/eaaCatalog/unitOfWork.html
Repositories and IQueryable, the paging case– http://thinkbeforecoding.com/post/2009/01/19/Repositories-and-IQueryabl
e-the-paging-case
CQRS: Recording of an online class – Greg Young– http://cqrsinfo.com/video/
ReferênciasDDDSample (em Java)
– http://dddsample.sourceforge.net/
ndddsample (C# Domain Driven Design sample application)– http://code.google.com/p/ndddsample/
DDDSample .Net– http://dddsamplenet.codeplex.com/
Rhino Commons, Ayende Rahien– http://ayende.com/blog/archive/2007/06/08/rhino-commons-repositorylttgt
-and-unit-of-work.aspx
Obrigado!
João [email protected]://blog.nicolauoliveira.comhttp://www.facebook.com/joaonoliveirahttp://pt.linkedin.com/in/jnicolau