Data Transformers

There are some cases where generating intermediate DTOs for more complex responses like JSON, XML, CSV, and iCAL Contact could be seen as an unnecessary overhead. We could output the representation in a buffer and ask for it later on the delivery side.

Transformers help reduce this overhead by transforming high-level Domain concepts into low-level client details. Let's see an example:

interface UserDataTransformer
{
public function write(User $user);

/**
* @return mixed
*/
public function read();
}

Consider the case of generating different data representations for a given product. Usually, the product information is served through a web interface (HTML), but we might be interested in offering other formats, like XML, JSON, or CSV. This might enable integrations with other Services.

Consider a similar case for a blog. We might expose our potential as writers in HTML to the world, but some people will be interested in consuming our articles through RSS. The use cases — Application Services — remain the same. The representation doesn't.

DTOs are a clean and simple solution that could be passed to template engines for different representations, but this might complicate the logic of this last step of data transformation, as the logic for such templates could become a problem to maintain, test, and understand.

Data Transformers might be a better approach on specific cases. These are just black boxes with Domain concepts (Aggregates, Entities, and so on.) as inputs and read-only representations (XML, JSON, CSV, and so on.) as outputs. These transformers could be really easy to test:

class JsonUserDataTransformer implements UserDataTransformer
{
private $data;

public function write(User $user)
{
// More complex logic could be placed here
// As using JMSSerializer, native json, etc.
$this->data = json_encode($user);
}

/**
* @return string
*/
public function read()
{
return $this->data;
}
}

That was easy. Wondering how the XML or CSV one would look? Let's see how to integrate the Data Transformer with our Application Service:

class SignUpUserService
{
private $userRepository;
private $userDataTransformer;

public function __construct(
UserRepository $userRepository,
UserDataTransformer $userDataTransformer
) {
$this->userRepository = $userRepository;
$this->userDataTransformer = $userDataTransformer;
}

public function execute(SignUpUserRequest $request)
{
$user = // ...
$this->userDataTransformer()->write($user);
}

/**
* @return UserDataTransformer
*/
public function userDataTransformer()
{
return $this->userDataTransformer;
}
}

That's similar to the DTO Assembler approach, but this time without returning a concrete value. The Data Transformer is being used to hold and interact with the data.

The main issue with DTOs is the overhead of writing them. Most of the time, your Domain concepts and DTO representations will present the same structure. Most of the time, you'll feel it's not worth your time to make such a mapping. That said, the relationship between representations and Aggregates is not 1:1. You can represent two Aggregates together in a single representation. You can also represent the same Aggregate in multiple ways. How you do it always depends on your use cases.

However, according to Martin Fowler:

One case where it is useful to use something like a DTO is when you have a significant mismatch between the model in your presentation layer and the underlying domain model. In this case it makes sense to make presentation specific facade/gateway that maps from the domain model and presents an interface that's convenient for the presentation. It fits in nicely with Presentation Model. This is worth doing, but it is only worth doing for screens that have this mismatch (in this case it isn't extra work, since you'd have to do it in the screen anyway.)

We think the long-term vision will be worth the investment. On medium to big projects, interface representations and Domain concepts change at very different rhythms. You might want to decouple them from each other to lower the friction for updates. Using DTOs or Data Transformers allows you to evolve your model freely without having to think about breaking the layout all the time.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset