Search code examples
domain-driven-designrepository-pattern

Transformation logic for import entities from an external repository to a domain entity


I have an entity in my domain called 'Service.' For simplicity, let's assume it has just two value objects:

ServiceId (uuid) ClientId (uuid)

I can access this entity through its own repository ('ServiceRepository').

My application needs to import services from an external source, but the fields in the external source require some transformation before I can save them using the 'ServiceRepository.' I receive these two fields from the external source:

ExternalServiceId (int) ClientCode (string)

Before I can save these external services, I need to generate a ServiceId and find the ClientId for the ClientCode.

So, my approach is the following:

  • Create two different entities with their repositories: 'Service' and 'ExternalService.'
  • Create a use case which:
    1. Gets the services from the 'ExternalService' repository
    2. Use a service for transform the data from the ExternalService so I can save it using the 'ServiceRepository'

My question is if this would be the best approach because I will be duplicating the entity 'Service' and the repository. Is there any option for avoid this duplication?


Solution

  • First of all, the domain layer must indicate your core business model and rules. Any other interaction with your domain is the Application layer's concern. Note that it's the ACL layer's job to retrieve data from an external service and convert data to contracts that the Application layer defines.

    Here's a list of notes that you should apply to your design to prevent it from becoming a mess when you are communicating with external services:

    • Do not pollute your domain with the domain model of external services. All the communications must go through the Application layer. Sometimes it's handling or publishing events (messaging between microservices or bounded contexts), and sometimes it's calling an ACL layer method to process a use case. So defining the ExternalService entity in your domain is wrong.

    • To use external services, you should create an ACL layer around those services to prevent your application from getting tightly coupled with the external services. So your domain model must know nothing of converting or retrieving data from external services. The ACL layer pattern is one of the strategic patterns used in domain-driven design context mapping.

    • Your application layer should define the interfaces it needs for the external services. To do that, put all the interfaces you need to use in the Application layer (probably in the Application contracts) and implement them in the ACL layer.

    Edit:

    If I got this right, I think you are duplicating data between multiple microservices. it's a common thing to do in microservice architecture. You can define correspondent identity properties in your Service Entity to map the external service in your domain. It's not bad to put tracking identities in your domain model to relate to external services. So you can put ExternalServiceId and ClientCode into your ServiceEntity. And with those identities, you can make sure that duplicate services won't get created in your database.