Reputation: 1039
I'm reading Implementing Domain Driven Design by Vaughn Vernon. In one of the examples he shows a Forum being created in the Collaboration bounded context. Before it's created, a Creator value object is instantiated. The information for the Creator object comes from a different bounded context. A HTTP request is made to a REST API to retrieve a User from the Identity and Access bounded context. It is then translated to a Creator object.
private Forum startNewForum(
Tenant aTenant,
String aCreatorId,
String aModeratorId,
String aSubject,
String aDescription,
String anExclusiveOwner) {
Creator creator =
this.collaboratorService().creatorFrom(aTenant, aCreatorId);
Moderator moderator =
this.collaboratorService().moderatorFrom(aTenant, aModeratorId);
Forum newForum =
new Forum(
aTenant,
this.forumRepository().nextIdentity(),
creator,
moderator,
aSubject,
aDescription,
anExclusiveOwner);
this.forumRepository().save(newForum);
return newForum;
}
UserInRoleAdapter makes a call to a REST API in another bounded context and translates that into a Creator object.
public class TranslatingCollaboratorService implements CollaboratorService {
private UserInRoleAdapter userInRoleAdapter;
...
@Override
public Creator creatorFrom(Tenant aTenant, String anIdentity) {
Creator creator =
this.userInRoleAdapter()
.toCollaborator(
aTenant,
anIdentity,
"Creator",
Creator.class);
return creator;
}
...
}
JSON retrieved from REST API is used to instantiate a Creator object.
private T extends <Collaborator> T newCollaborator(String aUsername,
String aFirstName,
String aLastName,
String aEmailAddress,
Class<T> aCollaboratorClass)
throws Exception {
Constructor<T> ctor =
aCollaboratorClass.getConstructor(
String.class, String.class, String.class);
T collaborator =
ctor.newInstance(
aUsername,
(aFirstName + " " + aLastName).trim(),
aEmailAddress);
return collaborator;
}
Is this call to the REST API equivalent to calling an application service method in the other bounded context directly? Or how is it different? Is calling application services directly in other bounded contexts and then translating the result allowed? Is having a REST API for communicating directly between bounded contexts common?
EDIT: My question is similar to this one but I just want a bit more information. In that question it is said that it is preferable to use events and keep local copies of data over calling an application method in another bounded context. If these application methods are put behind REST interfaces, is it still preferable to use events. Is it always frowned upon to call application methods of other bounded contexts directly or should it just be used as least as possible?
Upvotes: 3
Views: 3323
Reputation: 4199
Bounded Context boundaries have nothing to do with message propagation way. It's up to the architects to decide how to organize application, whether to decompose it into microservices, etc. It's important to be explicit and strict about the interface. REST or RPC or direct call, you name it, is just a transport.
Of course, almost by definition concepts inside the bounded context are more tightly coupled, than external things, which usually makes it possible to make a separate service, but I doubt DDD insists on any specific way. The book in question mentions for instance Open Host Service pattern among others in "Mapping Three Contexts" saying: "We generally think of Open Host Service as a remote procedure call (RPC) API, but it can be implemented using message exchange.", which can be just book's author opinion.
I think, sometimes (and it is also brought up in the book), Anticorruption Layer (of Collaboration Context) is used for effective decoupling, because, in book example, Creator is Collaboration Context concept, and User comes from another service, and only some aspects are needed for Collaboration (the book describes it at length, I do not want to repeat).
The only problem with direct call I see is that when doing direct calls making adapters "out if thin air" may feel "overkill" for some, and User may end up being used. With REST it's psychologically easier to translate external context's concept into what is consumed in the context in question.
While not directly relevant, the following question/answers may provide you more insights: Rest API and DDD .
Using concrete message-passing technique is orthogonal to applying DDD methodology. It's more into specific situation and desired system characteristics, and may also be a matter of opinion. For example, whether to save (cache?) information from another Bounded Context is up to the software designer. Not from the DDD books, but resolution of the CAP theorem for the distributed system you build depends on requirements, there is no generic answer possible to guide you.
In the same author's another book - "Domain-Driven Design Distilled", Chapter 4. Strategic Design with Context Mapping, you can find some clarifications, to cite: "You may be wondering what specific kind of interface would be supplied to allow you to integrate with a given Bounded Context. That depends on what the team that owns the Bounded Context provides. It could be RPC via SOAP, or RESTful interfaces with resources, or it could be a messaging interface using queues or Publish-Subscribe. In the least favorable of situations you may be forced to use database or file system integration, but let’s hope that doesn’t happen..."
Upvotes: 6