-2

I have a service with Hexagonal architecture that is responsible for creating leads in the system. In this service I don't have the users, I have to call an external service.

In the lead create request that I receive through API, I don't have the user_id (creator), I have the user email.

My question is, where I should do this call?

a) In the controller call to the external service to get the user, and pass it to the application service responsible for creating the lead. In this case, should I call again to the external service to check if the given ID exists?

b) In the controller, pass the email and in the application service call external service with the user email, to get the user.

I prefer the first one as I'm not compromising the application service with what I'm receiving in API.

What do you think?

Carlos
  • 1

2 Answers2

2

I assume since you attached the domain-driven-design tag that you're adhering to DDD tactical patterns, and by this I mean that you have a DDD lead-related entity that you're trying to create here.

It is useful to expand on a couple of points here.

First, to address your question, in hexagonal architecture, the "ports and adapters" pattern is very common-place, to the point of being almost synonymous. In ports and adapters, for input, you'd have a port which accepts the external request and translates it to the internally understood ubiquitous language before passing it in the domain/business logic code. In such a pattern, the API controller can very well be considered a port, and it could translate the request into an internal value object (VO henceforth) by retrieving the data that VO needs, and exposes in its creation contract. This implies that the controller would fetch all data necessary to populate a valid VO to represent the necessary domain object (a lead source, customer, whatever you have).

One consideration, that I'd like to raise though, is that this implies an absence of data necessary for this service to fulfill its responsibilities. Depending on the situation, this may not be a problem, but if these are distributed services, you're tying the availability of this service with the availability of the other service (which owns users). You have a couple of options here:

  1. A possibly better option (but not always depending on the consistency requirements) may be to observe events and hold a local cached copy of the data that you'll need, or potentially re-evaluating service boundaries.
  2. Another (probably better option if you can do this), is change the contract of your API to require any and all necessary data that is needed to do this operation.
Savvas Kleanthous
  • 2,695
  • 17
  • 18
1

Because dependencies flow inwards in Hexagonal Architecture, the controller should be dependent upon:

  • User Identity App Service Interface
  • Lead App Service Interface

As the orchestrator, the controller should perform the following functions:

  • Identify the User
  • Create the Lead

There is no need to compromise the Lead App Service with dependencies from other "interfaces". Since the Lead App Service defines that it needs User Id, it should be up to the controller to orchestrate the process of retrieving the User Id from the User Identity App Service with the context information it has available to it.

Aaron Hawkins
  • 2,611
  • 1
  • 20
  • 24