Domain Logic

From what I understand, domain logic reflects intrinsic details of the problem domain. It is something that domain experts will tell you. Something that still exists without computers, e.g. a debit account’s balance is not allowed to go below its overdraft limit.

<aside> 💡 There are a lot of domains that didn’t exist without computers or do not have domain experts. Then how do we know what is intrinsic domain logic?

</aside>

What are the main building blocks of domain logic in tactical DDD? As per the Blue Book:

  1. Entity — a domain object with stable identity, whose state evolves over time. Comes equipped with methods to perform domain actions. Examples: Tweet, Order, Community, UserProfile, etc.

  2. Value Object — a domain object that represent one value or a set of cohesive values. Does not have identity. Two instances should be considered equal iff their components are equal. Value object can also have methods. Examples: Money, Address (as part of UserProfile), NutritionInformation, PostContent, etc.

  3. Aggregate — an entity consisting of value objects and other entities (e.g. Order with a set of OrderItems). It serves as a consistency boundary — all operations with its components have to go through its root entity and it should be persisted atomically as a whole. So it’s advised to keep them as small as possible, and sometimes to delegate some invariants to infrastructure.

    <aside> 💡 In modern Scala using opaque types everywhere is so widespread that you will always end up with the value objects as a part of your entity. So it makes sense to call every entity that is not a part of any other entity an aggregate.

    </aside>

  4. Factory — a component that encapsulates an aggregate creation logic. Checks invariants that are not possible to express using value objects.

  5. Domain Service — a place where you put logic that does not naturally belong to other domain objects. The interface of a domain service should be expressed in domain terms. They say that the need for a domain service might be a sign of a missing entity.

  6. Repository — a component with a collection-like interface for storing and retrieving aggregates. You can think of it as a real world filing system, where companies keep their offline documents.

  7. ACL or Anti-Corruption Layer — a service-like component responsible for translation between domain terms and terms of some external system.

    <aside> 💡 Could a repository be considered an ACL for a database?

    </aside>

Nice! Now that we have all these components, let’s see what we can do with them. But also where do we do that? And I think this is how the notion of application service service was born.

Application Service

The responsibility of an application service is coordination of calls to domain and infrastructure components in order to execute a scenario. It could be seen as a facade for the underlying complexity.

There are two approaches to implement an application service. One is to provide an interface to run multiple scenarios. Another is often called command-handler, i.e. it is tailored to handle exactly one scenario. I never used the latter so I’m curious in exploring it first.