4 Aralık 2020 Cuma

Domain Driven Design - Aggregates - Oluşum

Neden Gereki
Amaç big ball of mud olarak tabir edilen devasa bir sınıf ilişki ve hiyerarşisinden kaçınmak.

Giriş
Oluşum (Aggregate veya Root Aggregate)  bir Bounded Context içinde bulunur. Birbirleri ile ilintili nesnelerin bir araya gelerek oluşturdukları anlamlı daha büyük parçadır.  Şeklen şöyle. Burada 4 farklı bounded context içindeki oluşum hiyerarşisi görülebilir.


Aggregate mantıksal bir yapıdır, fiziksel bir karşılığı olmak zorunda değildir. Açıklaması şöyle
Aggregate is a logical concept. At the root of aggregate, there is an Entity!
Açıklaması şöyle.
Aggregates are a collection of objects to calm the complexity by reducing the connected objects into a single unit that are bound together by a root entity. It's a cluster of associated objects that we treat as a single unit.
Eric Evans'ın kitabından alıntı
An AGGREGATE is a cluster of associated objects that we treat as a unit for the purpose of data changes. Each AGGREGATE has a root and a boundary. The boundary defines what is inside the AGGREGATE. The root is a single, specific ENTITY contained in the AGGREGATE.
Diğer Oluşuma Erişim
Bir oluşum diğer oluşuma pointer tutamaz. Bunu yaparsak Object Graph tekrar yumak gibi olur. Onun yerine RefId ya da bir çeşit anahtar değer tutar. Şeklen şöyle


Invariants - İş Kuralları
Açıklaması şöyle. Yani invariant her zaman tutarlı ve geçerli olan değiştirilemez kural demek
Invariants/consistency rules/business rules applied within an Aggregate will be enforced with each transaction's completion, like adding product to the cart, removing the product from the cart, etc. Example — Cart total price should match the sum of all the product prices in the cart.
Açıklaması şöyle
Now, is time to explain one of the most DDD important concepts when it comes to aggregate design, the invariants ( also known as business invariants or true invariants ):

> An invariant is a business rule that must always be consistent.
> Vaughn Vernon, Implementing Domain Driven Design, p.355

This simple definition give us a strong statement, no matter what happens in our system, an invariant is a business rule that will always hold, it can not be broken, therefore:

- Models can not be created if invariants are not ensured
- Models can not be changed if any invariant is broken
- Consistency must be preserved in a concurrent environment
Oluşum Örnekleri
Bazı örnekler aşağıda

Örnek - Sinema
Şeklen şöyle


Örnek - Customer
Elimizde şu nesneler olsun
Customer
Customer Home Address
Order
Order Line: where it has count of each product
Shipping Address
Product
Product Category
Product
Açıklaması şöyle
Given the requirements above, we group the entities with Customer, Order, Product as the Aggregate Roots. This also means that all database queries should only query against these aggregate root entities. e.g) You shouldn't create a SQL query selecting on Address table; Address should only be accessed by traversing through Customer or Order entity.
Açıklaması şöyle
In other words, we should only have CustomerRepositoryOrderRepository, ProductRepository (Do not cheat by defining custom queries inside the repositories "select"ing on a different entity than the aggregate root entity the repository was meant for.)
Örnek - Cart Aggregate
Açıklaması şöyle
In the Shopping cart bounded context, Cart is Aggregate, and at the root of it, there is the Cart Entity.

Aggregate is a cluster of associated objects that we treat as a unit for data changes. The aggregate root is at the top and is the only entity through which Aggregate can be accessed and has the global identifier.

Other Objects inside aggregate can have local identifiers and are NOT accessible outside aggregate directly. Aggregate root controls access to them from the outside world.
Örnek - User Aggregate
Şöyle yaparız. Burada aggregate aslında çok iş yapmıyor, sadece User nesnesini doldurup kaydediyor.
public class UserAggregate {
  private UserWriteRepository writeRepository = ...;

public User handleCreateUserCommand(CreateUserCommand command) {
  User user = new User(command.getUserId(),command.getFirstName(),command.getLastName());
    writeRepository.addUser(user.getUserid(), user);
    return user;
  }

  public User handleUpdateUserCommand(UpdateUserCommand command) {
    User user = writeRepository.getUser(command.getUserId());
    user.setAddresses(command.getAddresses());
    user.setContacts(command.getContacts());
    writeRepository.addUser(user.getUserid(), user);
    return user;
  }
}
Aggregate Yaratmak
Aggregate zengin bir nesne olduğu için yaratması da çok kolay olmayabilir. Bunun için Builder örüntüsüne başvurulabilir.

Spring Repository 
Açıklaması şöyle
Spring Repository should only be defined for Aggregate Root Entities




Hiç yorum yok:

Yorum Gönder