0

I am developing a middleware application where the application workflow is:

  1. handles rest requests
  2. performs some business logic
  3. calls another rest service

I would like to use DDD to model the business logic as it is very expressive.

But as the application mainly serves as a gateway or facade, the aggregate root ends up needing a dependency on a rest client to perform its operation like the following simplified example:

aggregateRoot(restClient) {

    operation1(data) {
        // business logic
        restClient.operation1(data);
    }

    operation2(data) {
        // business logic
        restClient.operation2(data);
    }

    operation3(data) {
        restClient.operation1(data);
        // business logic
        restClient.operation3(data);
    }
}

From what I have read, it is not considered good practice to have such dependency. Is it?

What could be a better model in this situation?

Regards

1 Answer 1

0

From what I have read, it is not considered good practice to have such dependency. Is it?

No, that sort of dependency is usually frowned upon

What could be a better model in this situation?

There are two other patterns that show up fairly regularly.

The key insight is that most domain models have a dependency on information, but don't particularly care where that information is or how to get it. I/O is not a domain concern, but an application concern; still code that we have to write, but normally located in a different part of our design.

The pattern you'll see discussed most often is that of a DOMAIN SERVICE; as described by Eric Evans in chapter 5 of his book, a domain service is a stateless element in the domain model that can be used to interact with data that is somewhere else.

In some cases, this means that the entire domain service is just an interface, and the implementation is provided by the application code. In other cases, the domain service will have domain logic within it (it's part of the domain code) but will also define some data interface that will be implemented by the application.

In effect, the REST client is still there, and still being invoked by the domain model; there's just an extra level of indirection so that hides the decision to use an REST client. You've got it right when you can change the REST client, or change from using a REST client to some other I/O client, without disturbing the domain code.

An alternative, but less common approach, is to design the interface of your aggregates such that all of the I/O can be done in the application code, and information is passed to the domain model (rather than passing the capability to get the information).

In this style, you would still have a REST client (and possibly an abstraction around it), but you would invoke it from your application code (ie, the same layer where you are talking to the REPOSITORY), and pass VALUE OBJECTS between your domain code and application code.

Cory Benfield 2016 shows a good example of this style.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.