Este artigo foi traduzido por máquina.

Práticas recomendadas

Uma introdução para design controlada por domínio

David Laribee

Este artigo discute:

  • Modelagem de linguagem universal
  • Limitado contextos e raízes agregadas
  • Usando o princípio de responsabilidade único
  • Repositórios e bancos de dados
Este artigo usa as seguintes tecnologias:
O Visual Studio

Conteúdo

O modelo Platonic
Falar a conversar
Contexto
Saber A proposição de valor
Um sistema de responsabilidades único
As entidades têm uma Identity e uma vida
Objetos de valor Descrever itens
Raízes agregadas combinar entidades
Domínio serviços modelo principal operações
Repositórios salvar e dispense raízes Aggregate
O Thing com bancos de dados
Introdução ao DDD

design controlada por domínio (DDD) é uma coleção dos princípios e padrões que ajudam os desenvolvedores a criar sistemas de objeto elegante. Ele foram aplicadas corretamente pode levar a abstrações de software chamadas modelos de domínio. Esses modelos encapsulam a lógica comercial complexo, fechando a lacuna entre realidade comercial e código.

Neste artigo, abordarei os conceitos básicos e padrões de design germane para DDD. Considere este artigo como uma introdução delicada a criação e a evolução de modelos de domínio rich. Para fornecer algum contexto à discussão, ESTOU usando um domínio comercial complexo com os quais estou familiarizado: gerenciamento de diretivas de seguro.

Se as idéias apresentadas aqui apelo para você, eu altamente recomendável que você aprofundar sua caixa de ferramentas, lendo o livro Domain-Driven Design: Tackling Complexity in the Heart of Software, por Eric Evans. Mais do que simplesmente a Introdução original para DDD, é conter um tesouro de informações por um dos designers de software mais experiente da indústria. Os padrões e principais filosofias de DDD que abordarei neste artigo são derivadas dos conceitos que são detalhados neste livro.

Contextos de corte pela necessidade de arquitetura

Contextos vinculados needn't ser organizados exclusivamente por área funcional de um aplicativo. Eles são muito úteis na divisão de um sistema para obter exemplos arquiteturais desejados. O exemplo clássico dessa abordagem é um aplicativo que tem um footprint transacional robusto e um portfólio de relatórios.

Geralmente é desejável em tais circunstâncias (o que podem ocorrer com bastante freqüência) quebrar o banco de dados relatórios do banco de dados transacional. Você deseja a liberdade para buscar o certo grau de normalização para desenvolvimento de relatórios confiáveis, e você deseja usar um mapeador de relacional do objeto para que você pode manter codificando lógica comercial transacional no paradigma orientado a objeto. Você pode usar uma tecnologia, como o Microsoft Message Queue (MSMQ) para publicar atualizações de dados provenientes do modelo e incorporá-las em depósitos de dados otimizados para fins de análise e emissão de relatórios.

Isso pode vir um choque a alguns, mas é possível para os administradores de banco de dados e desenvolvedores obter junto. Contextos vinculados oferecem uma amostra da Terra promised. Se você estiver interessado em contextos de limitado arquitetura, eu recomendo manter guias on Blog do Greg Young. Ele é bastante experiência com articular sobre essa abordagem e produz uma quantidade razoável de conteúdo no assunto.

O modelo Platonic

Desde que vamos começar simplesmente desativar aqui, faz sentido prático para definir o que QUERO dizer pelo modelo. Responder essa pergunta nos leva em uma jornada curta, metaphysical. Quem melhor que Platão para orientar nos?

Platão, que aluno mais famoso do Sócrates, proposta que coloca os conceitos, pessoas, e coisas que estamos intuit e percebem com nossa forma é simplesmente sombras da verdade. Ele apelidado essa idéia de uma coisa true um formulário.

Para explicar os formulários, Platão usado que é tornam-se conhecido como o allegory do cave. Neste allegory, há pessoas que estão vinculadas dentro de um cave profundidade, escuro. Esses cave pessoas são encadeadas de tal forma que eles só possam ver uma parede em branco do cave que recebe luz de abertura. Quando um animal orienta pela abertura, uma sombra é projetada na parede interna que o dwellers cave vê. Dwellers cave, esses sombras são a coisa real. Quando uma maioria orienta por, aponte para a sombra da maioria e exclaim, "executar para a capa!" Mas, na verdade, é apenas uma sombra do formulário real, a maioria propriamente dito.

Você pode relacionar teoria do Platão de formulários para DDD. Grande parte do seu guia ajuda a se aproximar o modelo ideal com o tempo. O caminho para o formulário que deseja descrever com seu código é espalhado sobre as mentes dos especialistas de domínio, o desejo de participantes e os requisitos de setores na qual estamos trabalhando. Esses são, em um sentido muito real, as sombras para imaginários cave dwellers do Platão.

Além disso, você geralmente é restringidos pelos idiomas e as considerações de tempo e orçamento na tentativa de acessar que o formulário de programação. Não é muita um alongue para dizer a que essas limitações são o equivalente de dwellers cave só poder ver a parede interna de sombras.

Modelos de boas apresentam um número de atributos independentes da sua implementação. O fato da questão é a incompatibilidade entre o modelo que está na cabeça de todos e o modelo que você está efetuando código é a primeira coisa que um Modelador domínio aspiring deve compreender.

O software que você cria não é o modelo de true. É apenas uma manifestação — uma sombra, se você — do aplicativo formulário você propus a atingir. Embora isso seja uma imitação da solução perfeita, você pode tentar colocar esse código mais perto o formulário true longo do tempo.

DDD, essa noção é chamada projeto controlado por modelos. A compreensão do modelo do é evoluiu em seu código. Designers controladas por domínio em vez disso seriam se não com reams de documentação ou ativado ferramentas de diagramação. Que eles buscam, em vez disso, a imbue seu senso de Noções básicas sobre domínio diretamente em seu código.

A idéia do código captura o modelo é principais para DDD. Mantendo o seu software voltada para o problema à mão e restrita para solucionar esse problema, você acaba com software receptivos para novas idéias e momentos de enlightenment. Eu gosto que Gustavo Evans chama: manipulando dados de conhecimento em modelos. Quando você aprender algo importante sobre o domínio, você saberá direita onde ir.

Falar a conversar

Vamos examinar algumas das técnicas que DDD fornece para alcançar esse objetivo. Grande parte de seu trabalho como um desenvolvedor está funcionando com não-coders para entender o que deve fornecer. Se você estiver trabalhando em uma organização com qualquer tipo de processo, você provavelmente terá requisitos expressa como um texto de usuário, tarefa ou caso de uso. Qualquer tipo de requisitos ou especificação for exibida, é geralmente concluída?

Normalmente requisitos são um pouco murky ou expresso em um alto nível de compreensão. No decorrer da projetar e implementar uma solução, é útil quando os desenvolvedores têm acesso às pessoas que apresentar alguns especialistas no domínio pretendido. Isso é exatamente o ponto de textos do usuário, que normalmente são expressos conforme a um modelo como este: como uma [função], eu quero [recurso] então que [Benefícios].

Vamos dar um exemplo do domínio de gerenciamento de apólice: como um emissor, eu quero controle de aprovação sobre uma diretiva para que eu possa gravar exposições seguras e rejeitar as arriscado.

Há qualquer pessoa que entende o que isso significa? Eu sei que não quando vi escrito e priorizados. Como pode possivelmente entendeu tudo o que precisará ir para entregar o software de suporte dessa descrição abstratas?

Textos de usuário, feitos corretamente, são um convite para ter uma conversa com o autor — o usuário. Isso significa que quando você passar para trabalhar no recurso de diretiva de aprovação/Negar, você o ideal é que deve ter acesso a um emissor. Underwriters, para leigos, são especialistas de domínio (que pelo menos boa é) que determinar se uma determinada categoria de exposição é segura para uma concessionária de chamadas cobrir.

Quando você começar a discutir o recurso com o emissor (ou qualquer pessoa pode ser a especialista de domínio do projeto), pagamento especialmente fechar atenção a terminologia que usa o emissor. Esses especialistas de domínio usam terminologia de empresa ou -padrão da indústria. DDD, este vocabulário é chamado a linguagem universal. Como os desenvolvedores, que você deseja entender este vocabulário e não apenas usá-la quando falamos com especialistas do domínio mas consulte também a mesma terminologia refletida no seu código. Se os termos "código de classe" ou conjuntos de taxa ou "exposição" com freqüência é usada em conversa, deve esperar encontrar nomes de classe correspondentes no código.

Isso é um padrão bastante fundamental para DDD. Blush, a linguagem universal parece uma coisa óbvia e chances são uma boa que número você é já praticar isso intuitivamente. No entanto, é essencial que os desenvolvedores usar a linguagem de negócios no código consciously e como uma regra disciplinada. Isso reduz a desconexão entre vocabulário de negócios e jargão tecnológica. Como se torna subordinada para a qual e você ficar mais próximo a razão para o trabalho: oferecer valor comercial.

Contexto

Os desenvolvedores são, de certa forma, organizadores. Você sling código (espera-se com intenção) em abstrações que solucionar problemas. Ferramentas como padrões de design, arquiteturas em camadas e princípios orientados a objeto fornecer uma estrutura para aplicar ordem ao evermore sistemas complicados.

DDD estende sua caixa de ferramentas organizacional e usa entre padrões de indústria conhecido. O que eu gosto mais sobre os padrões organizacionais que DDD dispõe é que há soluções para cada nível de detalhe em um sistema. Contextos vinculados guiá-lo em direção a pensar em software como um portfólio de modelos. Módulos ajudam organizar um modelo único maior em partes menores. Posteriormente, abordarei raízes agregadas como uma técnica para organizar colaborações pequenas entre algumas classes altamente relacionadas.

Em maioria dos sistemas existe são grained curso áreas de responsabilidade. DDD chama esse nível superior de organização um contexto limitado.

Os operadores ' compensação apólices de seguro precisará se preocupar com elementos, como:

  • Quoting e vendas
  • Fluxo de trabalho gerais de diretiva (renovações, demissões)
  • Auditoria de estimativa de folha de pagamento
  • Trimestre self-estimates
  • Definir e gerenciar taxas
  • A emissão de comissões para agências e corretores
  • Os clientes de cobrança
  • Contabilidade geral
  • Determinando as exposições aceitáveis (emissão)

Uau. Isso é muita coisa! Você pode incorporar tudo isso em um sistema único e monolítico, mas fazer tão leva você para baixo de um caminho foggy amorphous. As pessoas estão falando sobre duas coisas totalmente diferentes quando eles bate-papo sobre uma diretiva no contexto de um fluxo de trabalho geral versus uma diretiva no contexto de auditoria de folha de pagamento. Se você usar a mesma classe de diretiva, você está fattening o perfil dessa classe e obter um longo caminho das práticas recomendadas testadas e aprovadas, como uma responsabilidade principal (SRP).

Guia de sistemas que falham ao isolar e isolá limitado contextos com freqüência em um estilo de arquitetura (amusingly) chamado A grande bola de Mud. Em 1999, Brian pés e Joseph Yoder definidos o estilo de arquitetura (ou anti-architectural estilo, como a ocorrência pode ser) no seu documento clássico o mesmo nome "Bola grande de Mud").

DDD desloca você identificar contextos e restringindo seu esforço de modelagem em contextos específicos. Você pode usar um diagrama simples, chamado de um mapa de contexto, para explorar os limites de nosso sistema. Eu já enumerados os contextos envolvidos em um sistema de gerenciamento apólice completos, e Figura 1 leva isso de uma descrição textual a um mapa de contexto de gráfico (parcial).

fig01.gif

Figura 1 do mapa de contexto para contexto vinculado

Você notou algumas relações de chave entre a vários contextos de limitado? Isso é valioso inteligência porque você pode iniciar fazendo negócios informados e decisões de arquiteturais, como o design de empacotamento e implantação; escolha da tecnologia usado para empacotar mensagens entre modelos; e, talvez o mais importante, onde você escolher definir etapas do projeto e implantar talento, tempo e esforço.

Um último mas muito importante pensar sobre limitado contextos: cada contexto possui sua própria linguagem de todos os lugares. É importante diferenciar a noção de uma diretiva no subsistema de auditoria e a diretiva no fluxo de trabalho principal porque eles são coisas diferentes. Embora eles podem ter a mesma identidade, os objetos de valor e entidades filhas (mais informações sobre esses daqui a pouco) geralmente são radicalmente diferentes. Como você está modelagem no contexto, também quer o idioma para fornecer precisão dentro desse contexto de modo que você pode ter comunicação produtiva com especialistas de domínio e em suas equipes.

Algumas áreas dentro de grupo de modelos melhor juntos que outras pessoas. Módulos são formas de organizar esses grupos em um contexto específico, servindo como mini-limites onde você deseja interromper e pensar sobre associações com outros módulos. Também são outra técnica de organização que conduz você longe "no Small de Mud". Bem, módulos são fáceis de criar; no Microsoft .NET Framework são simplesmente espaços para nome. Mas a arte de identificação módulos envolve gastar um pouco tempo com o seu código. Finalmente você pode ver algumas coisas que surgem como um mini-model em um modelo, o momento você pode considerar dividir as coisas em espaços para nome.

Teasing modelos separados em módulos coesos tem um efeito interessante no seu IDE. Ou seja, desde então, você precisa usar vários usando instruções para incluir módulos explicitamente, você obter uma experiência de IntelliSense muito limpeza. Eles também oferecem uma maneira de olhando as associações entre blocos maiores conceituais de seu sistema com uma ferramenta de análise estática, como NDepend.

Apresentando uma alteração organizacional ao seu modelo deve solicitar a participar de alguns pragmatic, custo-benefício pensar. Quando você usa módulos (ou espaços para nome) para dividir seu modelo, você realmente deseja pergunta se você estiver lidando com um contexto separado. O custo de cleaving fora outro contexto é geralmente muito maior: agora você tem dois modelos, provavelmente em dois assemblies, que você precisa se conectar com serviços de aplicativo, controladores e assim por diante.

Camadas anti-Corruption

Uma camada Anti-Corruption (ACL) é outro padrão DDD que incentiva a criar gatekeepers que funcionam para impedir que os conceitos de fora do domínio vazamento no seu modelo. Elas mantêm o modelo de limpeza.

Em seu núcleo, repositórios são, na verdade, um tipo de ACL. Elas mantêm SQL ou construções de mapeamento relacional do objeto (ORM) fora do seu modelo.

As ACLs são uma ótima técnica para introduzir que Michael Feathers chama, em seu livro Working Effectively With Legacy Code, uma fenda. Uma fenda é uma área onde você pode começar a cleave off algum código herdado e começar a apresentar changes.Finding seams, juntamente com isolamento de domínio principal, podem ser extremamente importantes ao usar técnicas DDD para o refactor e reforçar as partes de valor mais altos de seu código.

Saber A proposição de valor

A maioria das lojas de desenvolvimento tem poucas tanto businesspeople experiente desenvolvedores superior que são capazes de isolar, que descreve um problema e criar uma solução orientada a objeto elegante, passível de manutenção. Para obter o bang maior buck do seu cliente, você deseja para ter certeza de que entender o domínio principal do seu aplicativo. O domínio principal é o contexto limitado que traz o valor a maioria dos aplicar DDD.

No sistema qualquer determinada empresa, existe algumas áreas que são mais importantes do que outras pessoas. As áreas mais importantes tendem a se enquadram em alinhamento com as competências principal do cliente. É raro que uma empresa será executado software personalizado Contabilidade geral. Mas, se essa empresa está em seguro (ir com meu exemplo anterior) e sua oferta de dinheiro-fazendo está gerenciando pools de risco onde responsabilidade é difundida entre todos os membros, eles tinham melhor ser darned bons na rejeição incorretos de riscos e identificar as tendências. Ou talvez você tenha um cliente que é um processador de declarações médicos e sua estratégia é flank seus concorrentes no preço Automatizando pagamentos para ampliam os esforços de sua força de trabalho payor da lista.

Seja qual for o setor, sua empresa ou cliente tem alguns borda no mercado e desta borda é normalmente onde você encontrar o software personalizado. Esse software personalizado é onde você provavelmente localizar e modelo do domínio principal.

Pode medimos nossos investimentos em valor em outra dimensão, isto é onde nós investir nosso capital intelectual em atinja excelência técnica. Os desenvolvedores muito muitas vezes sênior são o tipo de pessoas que obter obsessed com novas tecnologias. Uma certa quantidade de isso é esperado — o setor innovates um ritmo contínuos e fornecedores são levou para liberar freqüentemente novas ofertas de tecnologia para satisfazer as demandas de seus clientes e permanecer competitiva. O desafio, como CONSIGO vê-lo, é para os desenvolvedores sênior mestre os princípios fundamentais e padrões que contribuem com valor para o coração de um sistema. É tentador obter empacotada backup em uma nova estrutura ou plataforma, mas precisamos Lembre-se a produzir de fornecedores motivo dessas opções é por isso é apenas pode confiar que funcionem.

Um sistema de responsabilidades único

Já mencionei que DDD fornece uma linguagem padrão para estruturar modelos domínio rich. Implementando esses padrões, obter um certo nível de obrigatória a adesão ao SRP gratuitamente e é certamente valioso.

O SRP encoraja obter a finalidade de principal de uma interface ou classe. Ele orienta você na direção Alta coesão — algo muito bom, como ela torna o código mais fácil de descobrir, reutilizar e manter.

DDD identifica determinados tipos de classe responsabilidades em uma coleção principal de padrões. Abordarei alguns das mais principais agora mas, vale a pena mencionar que há muitos padrões descritos por Eric Evans no livro original variando de nível de classe a arquitetura. Para fins de apresentação, irá permanecer no nível de classe abrangendo entidades, objetos de valor agregados raízes, serviços de domínio e repositórios. Como esta é uma introdução, abordarei apenas a responsabilidade de cada padrão com um ou dois exemplos de código ou dicas.

As entidades têm uma Identity e uma vida

Uma entidade é "algo" em seu sistema. Geralmente é útil pensar sobre eles em termos de nomes: pessoas, lugares e, bem, as coisas.

Entidades têm uma identidade e um ciclo de vida. Por exemplo, se eu quiser acessar um cliente específico em meu sistema, pode pedir para ela por um número. Quando eu concluir uma ordem comercial, ele é, em seguida, inativo para meu sistema e pode ir para o armazenamento a longo prazo (o sistema relatórios histórico).

Pense em entidades como unidades de comportamento em vez de unidades de dados. Tente colocar a lógica nas entidades que possuem-los. A maioria das vezes há uma entidade que deve receber alguma operação que você está tentando adicionar ao seu modelo, ou uma nova entidade está começando a ser criado ou extraídos. Mais código anêmica, você encontrará muita de classes de serviço ou gerente que valida a entidades de fora. Em geral, muito prefiro fazer isso de dentro da entidade — você obter todos os benefícios associados com o princípio fundamental do encapsulamento, e você está fazendo suas entidades comportamento.

Alguns desenvolvedores estão incomodados fazendo dependências em suas entidades. Obviamente, você precisará criar associações entre as várias entidades no sistema. Por exemplo, talvez seja necessário obter uma entidade de produto da entidade de diretiva para que você possa determinar padrões adequados na diretiva. Onde as pessoas parecem se enquadram abaixo é quando você precisa alguns fora de serviço para executar o comportamento intrínseco a uma entidade.

Para um, não estou alterado pela necessidade de envolver outros e não-entidade classes, e deve tentar evitar levantar o comportamento central fora do Meu entidade. Você sempre deve se lembrar que as entidades são unidades intrinsecamente comportamentais. Muitas vezes esse comportamento será implementado como um tipo de máquina de estado — quando você invocar um comando em uma entidade, ele é responsável por alterar seu estado interno — mas, às vezes, é necessário obter dados adicionais ou impor efeitos colaterais após o mundo exterior. Meu técnica preferida para realizar isso é fornecer a dependência para o método do comando:

public class Policy {
  public void Renew(IAuditNotifier notifier) {
    // do a bunch of internal state-related things,
    // some validation, etc.
    ...
    // now notify the audit system that there's
    // a new policy period that needs auditing
    notifier.ScheduleAuditFor(this);
  }
}

A vantagem dessa abordagem é que você não precisa um inversão de recipiente de controle (IOC) para criar uma entidade para você. Outra abordagem perfeitamente aceitável, em minha opinião, seria usar um localizador de serviço para resolver o IAuditNotifier dentro do método. Essa técnica tem a vantagem de manter a interface limpa, mas eu encontrar que a estratégia de ex-informa muito mais sobre Meus dependências em um nível mais alto.

Objetos de valor Descrever itens

Objetos de valor são descritores ou propriedades importantes do domínio que é de modelagem. Ao contrário de entidades, eles não têm uma identidade; eles simplesmente descrevem as coisas que é necessário identidades. Você está alterando uma entidade chamada "trinta - cinco dólares" ou são incrementar o saldo de uma conta?

Parte a beleza de objetos de valor é que eles descrevem as propriedades de entidades de maneira muito mais elegante e revelar intenção. Dinheiro, um objeto de valor comum, é muito melhor como um parâmetro de função em uma transferência de fundos API que um número decimal. Quando você especial em um método de interface ou da entidade, você sabe o que você está lidando com imediatamente.

Objetos de valor são imutáveis. Eles estarão incapaz de alteração quando eles são criados. Por que é importante que eles sejam imutável? Com objetos de valor, você está procurando funções lado efeito livre, mas outro conceito emprestado por DDD. Quando você adiciona r$ 20,00 r$ 20,00, você está alterando r$ 20,00? Não, você está criando um novo descritor de dinheiro de r $ 40,00. Em C# você pode usar a palavra-chave de somente leitura em campos públicos para impor Imutabilidade e funções do lado efeito livre, conforme mostrado na Figura 2 .

A Figura 2 usando somente leitura para aplicar Imutabilidade

public class Money {
  public readonly Currency Currency;
  public readonly decimal Amount;

  public Money(decimal amount, Currency currency) {
    Amount = amount;
    Currency = currency;
  }

  public Money AddFunds(Money fundsToAdd) {
    // because the money we're adding might
    // be in a different currency, we'll service 
    // locate a money exchange Domain Service.
    var exchange = ServiceLocator.Find<IMoneyExchange>();
    var normalizedMoney = exchange.CurrentValueFor(fundsToAdd,         this.Currency);
    var newAmount = this.Amount + normalizedMoney.Amount;
    return new Money(newAmount, this.Currency);
  }
}

public enum Currency {
  USD,
  GBP,
  EUR,
  JPY
}

Raízes agregadas combinar entidades

Uma raiz agregada é um tipo especial de entidade que os consumidores se referem a diretamente. Identificar raízes agregadas permite que você evite over-coupling os objetos que constituem o modelo, impondo algumas regras simples. Você deve observar que raízes agregadas proteger seus subentidades zealously.

A regra maior para ter em mente é que raízes agregadas são o único tipo de entidade ao qual seu software pode conter uma referência. Isso ajuda a evitar A grande bola de Mud porque você agora tem uma restrição que impede a criação de um sistema fortemente fraco em que tudo o que tem uma associação para tudo.

Vamos supor que eu tenho uma entidade chamada diretiva. Bem, as diretivas obter renovadas em um termo anual, isso provavelmente não existe uma entidade chamada período. Como um período não pode existir sem uma diretiva e você pode agir em períodos por meio da diretiva, diretiva é considerada uma raiz agregada e período é um filho do mesmo.

Eu gosto de Meus raízes agregadas apenas descobrir para mim. Considere este código do consumidor acessando uma raiz de agregados de diretiva:

Policy.CurrentPeriod().Renew() 

ESTOU tentando renovar uma apólice, lembre-se o diagrama de classe do domínio principal de gerenciamento de diretiva de seguro. Observe como eu estou dotting minha forma o comportamento que desejo chamar?

Há algumas de problemas com essa abordagem. Primeiro, eu estou violando claramente o direito de Demeter. Um método M de um objeto O deve chamar somente os métodos dos seguintes tipos de objetos: propriamente dito, seus parâmetros, quaisquer objetos que ele cria ou cria uma instância ou seus objetos de componente direta.

Não É profundidade dotting tipo de conveniente? O IntelliSense é um dos recursos mais interessantes, mais úteis do Visual Studio e outros IDEs moderno, mas quando você inicia dotting sua maneira a função desejada, na verdade, para chamar, você está apresentando desnecessários união no sistema. No exemplo anterior, estou agora depende da classe de diretiva e a classe de período.

Para mais ler, Brad Appleton tem um excelente artigo disponível em seu site que explica as implicações mais profundas, theories, tooling e caveats ao redor o Lei dos Demeter.

O cliche "morte por mil cortes" é uma boa descrição do pesadelo potencial de manutenção de um sistema muito fraco. Quando você cria referências desnecessárias completo sobre o local, você também criar um modelo rígido em que as alterações em um local resultar em uma cascata de alterações completo sobre o código do consumidor. Você pode fazer o mesmo objetivo com, mais estou interessado, um pouco mais expressivo de código:

Policy.Renew()

Ver como a agregação apenas figuras-out? Internamente possa localizar o período atual e se ou não há já um período de renovação e outra que você precisa para fazer.

Acho que, quando estou testes Meus raízes agregados usando uma técnica como Behavior-Driven desenvolvimento (BDD) da unidade, meus testes tendência para o paradigma mais caixa-preta e teste de estado. Raízes agregadas e entidades geralmente acabam como máquinas de estado e o comportamento corresponde adequadamente. EU terminar com validação de estado, adição e subtração. Há um pouco de comportamento acontecendo no exemplo de renovação na Figura 3 e é muito clara como você pode expressar isso em um estilo BDD de teste.

A Figura 3 teste Aggregate raízes

public class 
  When_renewing_an_active_policy_that_needs_renewal {

  Policy ThePolicy;
  DateTime OriginalEndingOn;

  [SetUp]
  public void Context() {
    ThePolicy = new Policy(new DateTime(1/1/2009));
    var somePayroll = new CompanyPayroll();
    ThePolicy.Covers(somePayroll);
    ThePolicy.Write();
    OriginalEndingOn = ThePolicy.EndingOn;
  }

  [Test]
  public void Should_create_a_new_period() { 
    ThePolicy.EndingOn.ShouldEqual(OriginalEndingOn.AddYears(1));
  }
}

Domínio serviços modelo principal operações

Às vezes, você tem operações ou processos que não têm uma identidade ou o ciclo de vida em seu domínio. Serviços de domínio oferecem uma ferramenta para esses conceitos de modelagem. Elas são normalmente sem monitoração de estado e altamente coeso, geralmente fornecendo um único método público e, às vezes, uma sobrecarga para atuar em conjuntos.

Gosto de usar os serviços por algumas razões. Quando há um número de dependências envolvidos em um comportamento e não CONSIGO encontrar um local natural de uma entidade para colocar esse comportamento, usarei um serviço. Quando Meus linguagem universal fala sobre um processo ou operação como um conceito de ordem do primeiro, será pergunta se um serviço faz sentido como um ponto central de orquestração para o modelo.

Você pode usar um serviço de domínio no caso de renovação. Este é um estilo alternativo. Em vez de método inserindo um IAuditNotifier diretamente para o método do método de renovar a entidade de diretiva, você pode escolher extrair um serviço de domínio para manipular a resolução de dependência para nós; é mais natural para nós resolver um serviço de domínio de um recipiente de IOC que uma entidade. Essa estratégia faz sentido muito mais para mim quando há várias dependências, mas eu apresentarei a alternativa assim mesmo.

Este é um exemplo curto de um serviço de domínio:

public class PolicyRenewalProcesor {
  private readonly IAuditNotifier _notifier;

  public PolicyRenewalProcessor(IAuditNotifier notifier) {
    _notifier = notifier;
  }
  public void Renew(Policy policy) {
    policy.Renew();
    _notifier.ScheduleAuditFor(policy);
  }
}

O serviço de palavra é um termo altamente sobrecarregado no mundo do desenvolvedor. Às vezes, acho do serviço como na arquitetura orientada por serviços (SOA). Outras vezes que penso serviços como pouco classes que não representa uma determinada pessoa, lugar ou coisa no meu aplicativo, mas que tendem a abranger processos. Serviços de domínio normalmente estão nessa categoria último. Eles tendem a ser nomeado após verbos ou atividades comerciais que apresentem especialistas de domínio para a linguagem universal.

Serviços de aplicativos, por outro lado, estão uma ótima maneira de apresentar uma arquitetura em camadas. Elas podem ser usadas para mapear dados dentro do modelo de domínio para uma forma necessários para um aplicativo de cliente. Por exemplo, talvez você precisa exibir dados tabulares em um DataGrid, mas você deseja manter um gráfico de objeto granular e irregulares em seu modelo.

Serviços de aplicativo também são muito úteis para integração de vários modelos — por exemplo, convertendo entre o fluxo de diretiva de auditoria e principais diretiva trabalho. Da mesma forma, eu uso-los para trazer as dependências de infra-estrutura para a combinação. Imagine um cenário comum onde você deseja expor o modelo de domínio com o WCF (Windows Communication Foundation). EU seria usar um serviço de aplicativo decorado com os atributos WCF para fazer isso acontecer em vez de deixar vazamento do WCF em meu modelo de domínio puro.

Serviços de aplicativo tendem a ser muito amplo e superficial, embodying funcionalidade coesa. Considere a interface e implementação parcial que você vê no código na Figura 4 como um bom exemplo de um serviço de aplicativo.

Serviço de aplicativo simples 4 A de Figura

public IPolicyService {
  void Renew(PolicyRenewalDTO renewal);
  void Terminate(PolicyTerminationDTO termination);
  void Write(QuoteDTO quote);
}

public PolicyService : Service {
  private readonly ILogger _logger;
  public PolicyService(ILogger logger, IPolicyRepository policies) {
    _logger = logger;
    _policies = policies;
  }

  public void Renew(PolicyRenewalDTO renewal) {
    var policy = _policies.Find(renewal.PolicyID);
    policy.Renew();
    var logMessage = string.Format(
      "Policy {0} was successfully renewed by {1}.", 
      Policy.Number, renewal.RequestedBy);
    _logger.Log(logMessage);
  }
}

Repositórios salvar e dispense raízes Aggregate

Onde você Ir para recuperar entidades? Como você armazena-los? Essas perguntas são respondidas por padrão o repositório. Repositórios representam uma coleção de memória, e o aprenda algo mais convencional é que você terminar com um repositório por raiz agregada.

Repositórios são um bom candidato para uma classe super ou que Martin Fowler se refere a como o padrão de camada supertipo. Usando classes genéricas para derivar uma interface de repositório base o exemplo anterior é uma simples questão:

public interface IRepository<T>
  where T : IEntity
{
  Find<T>(int id);
  Find<T>(Query<T> query);
  Save(T entity);
  Delete(T entity);
}

Repositórios impedir conceitos do banco de dados ou persistência, como instruções SQL ou procedimentos armazenados, commingling com seu modelo e o está distraindo você da missão à mão: captura o domínio.Essa separação de código de modelo de infra-estrutura é um atributo boa.Consulte a barra de lateral camadas de Anti-Corruption para uma discussão mais detalhada.

Neste ponto, você provavelmente observou que eu não estou falando sobre raízes como agregadas, suas entidades subordinadas, e os objetos de depreciação associados, na verdade, obter persistidos no disco.Isso é intencional.Salvar os dados necessários para executar o comportamento em seu modelo é uma preocupação ortogonal ao próprio modelo.Persistência é infra-estrutura.

Uma pesquisa dessas tecnologias está muito além do escopo de uma introdução ao DDD.Basta você dizer, há um número de opções adequadas e maduros para armazenar dados de seu modelo de estruturas de mapeamento relacional do objeto (ORM) para orientação de documento bancos de dados para dados de "roll-seu-proprietário" mappers cenários simples.

DDD recursos

O site oficial do DDD

Dan Norte em How to estrutura usuário Stories

A bola grande de Mud estilo arquitetura

Blog do Greg Young em CodeBetter

Robert C.Papel do Martin em uma responsabilidade principal

Brad Appleton no direito de Demeter

Martin Fowler descreve o padrão de supertipo camada

Robert C.Martin on the S.O.L.I.D.Princípios

O Thing com bancos de dados

Por esse ponto, tenho certeza você já pensou, " Este é todo bem e boa, Dave.Mas onde salvar meus entidades?" Sim, você precisará lidar com esse detalhe importante, mas como ou onde você manter seus modelos principalmente é tangential para uma visão geral sobre DDD.

Um número de desenvolvedores ou administradores de banco de dados tornará a afirmação de que o banco de dados é o modelo.Em muitos casos, isso é parcialmente verdade.Bancos de dados, quando altamente normalizada e visualizado com uma ferramenta de diagramação, podem transmitir muito sobre as informações e as relações em seu domínio.

Dados de modelagem como uma técnica principal deixa algo a ser desejado, no entanto.Quando você deseja compreender os comportamentos inerentes no mesmo domínio, técnicas de somente de dados, como diagramas de relação de entidade (ERDs) ou modelos de entidade-relação e diagramas de classe dividir.Você precisa ver partes do aplicativo na animação e como tipos de colaboração para executar trabalho.

Quando eu estou modelagem, geralmente alcançar para diagramas de seqüência em um quadro de comunicações como uma ferramenta de comunicação.Essa abordagem captura muita a essência de comunicação de um design comportamento ou o problema sem a cerimônia de UML (Unified Modeling Language) ou arquitetura controlado por modelos.Gosto evitar desnecessária cerimônia, especialmente quando vou para apagar os diagramas que coloco no cavalete de apresentação.Eu não se preocupe aproximadamente 100 % adesão UML em meus diagramas, preferência ao caixas simples, setas e pistas de nadar você esboçar rapidamente.

Se você já não usar diagramas de seqüência da sua equipe, eu recomendo a técnica de aprendizado.EU tenha observado o efeito poderoso tenham sobre como os membros da equipe acha que a problemas ao redor do SRP, arquitetura em camadas, design de comportamento sobre modelagem de dados e arquitetura a pensar em geral.

Introdução ao DDD

Se tornando proficient com objeto-orientada a programação não é nenhuma tarefa trivial.Eu acredito competência é dentro do reach do mais profissional os desenvolvedores, mas ele aceita dedicação, aprendizado de catálogo e prática, prática e mais prática.Isso também ajuda se você adotar uma atitude de craftsmanship e aprendizado contínua.

Como começar?Simplificando: faça sua lição de casa.Saiba mais sobre itens como oS.O.L.I.D.Princípiose estudo livro dos Eric Evans.O investimento de tempo mais formarão para si mesma.InfoQ produziu uma versão menor do livro DDD que apresenta alguns conceitos-chave.Se você estiver em um orçamento financeiro ou temporal ou simplesmente em modo de investigação, recomendo inicial existe.Depois que você recebe uma situação sólida, perambular sobre oYahoo!DDD grupopara ver quais as questões seu colega designers estão enfrentando dificuldades com e envolver na conversa.

DDD não é um novo doctrine ou metodologia.É um conjunto de estratégias time-tested.Quando você receber pronto para praticar, tente adaptar essas filosofias, técnicas e padrões que faz mais sentido na sua situação.Alguns elementos da DDD aplicam mais universalmente que outras pessoas.Noções básicas sobre o motivo de existência do seu domínio principal descobrindo e usando a linguagem universal e identificando os contextos em que nós estiver modelagem são forma mais importantes que nailing esse repositório perfeitamente opaco e tamanho.

Quando você estiver criando suas soluções, crie um valor.Se os designers produzem arte e os desenvolvedores são um tipo de designer, em seguida, nosso médio deve ser valor comercial.Valor consciousness trumps considerações, como cumprimento dos dogma e escolha da tecnologia de persistência, tão importante que às vezes parecem essas opções.

Dave Laribee coaches a equipe de desenvolvimento do produto em VersionOne.Ele é palestrante assíduo em eventos de desenvolvedor locais e nacionais e foi concedido MVP da Microsoft em arquitetura para 2007 e 2008.Ele escreve na rede CodeBetter blog emthebeelog.com.