Projeto de unidade eficiente. Simulação de unidade única

Este artigo é uma sinopse da Parte I do Projeto de Agregação Eficaz: Modelagem de um único agregado .





Combinar entidades e objetos de valor em um agregado com limites de consistência cuidadosamente planejados pode parecer simples, mas de todos os padrões DDD táticos, o agregado é um dos mais complexos.





Será útil começar com algumas perguntas gerais. Um agregado é apenas uma maneira de combinar objetos intimamente relacionados com uma raiz comum (raiz agregada)? Em caso afirmativo, existe algum tipo de limitação no número de objetos que podem estar no gráfico? Uma vez que um agregado pode se referir a outro, é possível navegar pelos agregados usando esses links e alterar os dados dos objetos incluídos em um determinado agregado? E qual é o invariante e o limite de consistência ? A resposta à última pergunta influencia amplamente o restante das respostas.





Existem muitas maneiras de modelar uma montagem incorretamente. Podemos projetar uma unidade muito grande. Por outro lado, podemos dividir todos os agregados de forma que, como resultado, os invariantes verdadeiros sejam violados. Como veremos, é imperativo evitar esses extremos e, em vez disso, prestar atenção às regras de negócios.





Desenvolvimento de aplicativos ProjectOvation

Vamos dar uma olhada em agregados com um exemplo. Nossa empresa fictícia está desenvolvendo um aplicativo de suporte a projetos baseado na metodologia Scrum. O aplicativo segue o modelo tradicional de gerenciamento de projetos Scrum, ou seja, há um produto (produto), um product owner (product owner), equipes (equipe), itens do backlog (itens do backlog), lançamentos planejados (lançamentos planejados), sprints ( corrida). A terminologia Scrum constitui o ponto de partida de uma linguagem onipresente. Toda organização que compra uma assinatura se registra como inquilino, outro termo para nossa linguagem comum .





. , DDD . , , DDD . , . , .





? . , . . :





  • , .





  • .





  • .





  • .





  • .





  • .





. , .





:

« » . , , . :





  • , .





  • , .





  • , .





  • , .





Product . , Product, BacklogItem, Release, Sprint , . . UML- .





public class Product extends ConcurrencySafeEntity {

    private Set<BacklogItem> backlogItems;
    private String description;
    private String name;
    private ProductId productId;
    private Set<Release> releases;
    private Set<Sprint> sprints;
    private TenantId tenantId;
    ...

}

      
      



Figura:  1. O produto é modelado como um conjunto muito grande.
. 1. Product .

, - . , .  , . , , . () , .





:





  • , , Product c 1 .





  • BacklogItem . 2.





  • Release , , Product 1.





. .





. , . . .





. ? , -. , . , .





:

, 2. . ProductId, Product-.





Figura:  2. O produto e os conceitos relacionados são modelados como agregados separados.
. 2. Product .

Product. :





public class Product ... {
    	...
      public void planBacklogItem(
        String aSummary, String aCategory,
        BacklogItemType aType, StoryPoints aStoryPoints) {
      		...
      }
    	...
      public void scheduleRelease(
        String aName, String aDescription,
        Date aBegins, Date anEnds) {
      		...
      }

      public void scheduleSprint(
        String aName, String aGoals,
        Date aBegins, Date anEnds) {
        	...
      }
      ...
}

      
      



. Product, , – void. :





public class Product ... {
    	...
      public BacklogItem planBacklogItem(
        String aSummary, String aCategory,
        BacklogItemType aType, StoryPoints aStoryPoints) {
      		...
      }
  
      public Release scheduleRelease(
        String aName, String aDescription,
        Date aBegins, Date anEnds) {
        	...
      }

      public Sprint scheduleSprint(
        String aName, String aGoals,
        Date aBegins, Date anEnds) {
        	...
      }
      ...
}

      
      



. . , , :





public class ProductBacklogItemService ... {
     ...
     @Transactional
     public void planProductBacklogItem(
           String aTenantId, String aProductId,
           String aSummary, String aCategory,
           String aBacklogItemType, String aStoryPoints) {

           Product product =
                   productRepository.productOfId(
                                 new TenantId(aTenantId),
                                new ProductId(aProductId));

           BacklogItem plannedBacklogItem =
                  product.planBacklogItem(
                            aSummary,
                            aCategory,
                            BacklogItemType.valueOf(aBacklogItemType),
                            StoryPoints.valueOf(aStoryPoints));
          
          backlogItemRepository.add(plannedBacklogItem);
      }
      ...
}

      
      



, . BacklogItem, Release Sprint .





. , , . , , , - . , , .





, . , .





— -, . . , . . . :





c = a + b

, , = 2 b = 3, 5. , 5, . , , .





AggregateType1 {
    int a; int b; int c;
    operations...
}

      
      



, , , - , . , , . , .





. , , . – , , , , . .





( ) . .





, , , . , . . . , , .





: ? , , . , , , , , . - , .





, , ? , (lazy loading). , . , , . , . , , . , .





, 3. 0..* . . , . . , , . .





Figura:  3. Modelo do produto.  Várias coleções grandes são carregadas durante muitas operações simples.
. 3. Product. .

. , , .





, , «». , , , . , (root entity), / (object value).





, (, ) ? : , . , Product name description. , . , , . -, .





, , , . , , . , , , . , . . - , .





. , . , . , . Order OrderItem . , - , . , .





, , . . , , , .





, . , - . , . , . , , .





, -, , - , . 4. , , , . . , . , , , -.





Figura:  4. Mostra o acesso simultâneo aos dados entre três usuários.  Eles tentam acessar as mesmas duas instâncias de agregados, resultando em um grande número de falhas de transação.
. 4. . , .

, , . , , . ?





, , , , . - (eventual consistency) . , , , . , , . . , .








All Articles