Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Who is responsible for the process with API requests in Domain Layer of DDD(Domain Driven Design)

I'm a beginner in DDD.

I have no idea who is responsible for the process with API request.
I have no idea who is responsible for the function depending indirectly on Infrastructure Layer.
Such as the function with Web API request.

For example I'm creating online shopping system and the system supports order cancel.

I think I have 2 class candidates in domain layer to implement order cancellation function. A: Domain Service B: Domain Object

But I can't judge which is better.

I worry that Design "A" is too procedural and it looks anemic.
I also worry that Design "B" makes domain object too knowledgeable and dependent. (Because I think object should be as simple as possible)

Design Candidate A

// Simple but anemic
class Order {
    id: number;
    date: Date;
    state: OrderState;

    constructor(
        ...
    ) {
        ...
    }
}

// Procedural
class OrderService {
    private readonly orderRepository: OrderRepository;

    constructor(
        orderRepository: OrderRepository
    ) {
        ...
    }

    cancel(orderId: number): void {
        orderRepository.update(orderId, { state: OrderSate.Cancelled });
    }
}

Design Candidate B

// knowledgeable and dependent
class Order {
    id: number;
    date: Date;
    state: OrderState;

    private readonly orderRepository: OrderRepository;

    constructor(
        orderRepository: OrderRepository,
        ...
    ) {
        ...
    }

    cancel(): void {
        orderRepository.update(this.id, { state: OrderSate.Cancelled });
    }
}

The model I thought

like image 317
komei7174 Avatar asked Sep 05 '25 20:09

komei7174


1 Answers

I'm a beginner in DDD. I have no idea who is responsible for the process with API request.

The business logic belongs in the domain model, the orchestration belongs in the application.

Thus, the logic in your application would normally look something like...

Order order = orderRepository.get(orderId);
order.cancel();

The Order model is responsible for knowing how to manipulate its own in-memory data structure when Order::cancel is invoked. The OrderRepository is responsible for persistence. The application drives the invocation of the other two elements.

Part of the confusion is that the concept "service" is overloaded. In DDD, "domain service" refers to a pattern that is part of the domain model (just like value objects and entities are domain model patterns).

Update 20190120

But who updates the database in the server? Your code seems that database in server has't been updated yet if order.cancel() update only own memory. This is my thinking.

That's a really important question, isn't it? :)

When Eric Evans first described the repository pattern in his book, he deliberately choose a repository pattern with collection semantics and suggested that transaction management should be an application concern.

In pseudo code:

beginTransaction();
Order order = orderRepository.get(orderId);
order.cancel();
commitTransaction();

The notion being that the underlying mapper can review the repository and discover which entities are "dirty", and thereby generate the appropriate calls to your persistent store.

More recently, you are more likely to see repositories with storage, rather than collection, semantics

beginTransaction();
Order order = orderRepository.get(orderId);
order.cancel();
orderRepository.save(order);
commitTransaction();

The basic mechanics are the same, but we've eliminated some of the magic of how the changes are shared.

like image 178
VoiceOfUnreason Avatar answered Sep 11 '25 04:09

VoiceOfUnreason