DTO in OOP world

I suppose that everyone knows what the DTO is.Object oriented fans hate this pattern because it literally converts classes into plain old C structures.There is also the discussion in stackoverflow about this topic.I personally don't like DTO either because they are not reusable at all.Let's say I have a User class which is managed by persistence framework.Sometimes we want to return a user with the list of associated orders as json. Sometimes we are interested in user's data only.Sometimes the validation logic depends on the specific rules. For each case we will add new and new logic into User and as a result this class becomes completely unmaintainable.But what if we can create a separate DTO for each new requirement. Then all of them will have a lot of similar methods,logic...
One solution for this issue was proposed in this blog post and I want to show you how I applied it in the REST API implementation.

Tom asks for help
Tom & Jerry by William Hanna and Joseph Barbera

Example

Let me show you an example from my plain REST API implementation called widrest but before this, you have to understand the business logic. The main domain of the business is called Widget. Widget has some properties namely:

  • Y coordinate
  • X coordinate
  • Z index
  • Width
  • Height
  • Database id

Simple enough to understand, and now we have the following requirements:

  • User can't specify id during POST and PUT requests
  • Z-index is optional when widget is created and it's obligatory during update

Keep it small and simple

When I design classes , I prefer to make them as stupid as I can. The main reason is Single Responsibility.To be honest I have never googled what is the real definition of this sentence is until a while ago and here is the definition by Robert C. Martin from wikipedia:

A class should have only one reason to change.
Martin defines a responsibility as a reason to change, and concludes that a class or module should have one, and only one, reason to be changed

With this quote in mind let's write a simple solution to the problem above

final class Widget{
    private Integer id;
    private Integer z;
    private Integer x;
    private Integer y;
    private Integer width;
    private Integer height;
   //getters,setters
}

This class could be used in order to parse json request and to send response to a user.

  • We have to keep in mind that user can't specify id in request for widget that is why we should add
    @JsonProperty(access = JsonProperty.Access.READ_ONLY) annotation above id field in Widget class.
  • z-index is optional if user wants to create widget and it's mandatory if user wants to update an existing widget.If we use Javax validation API then we have to add Validation groups to z-index field inside Widget.

The new version of Widget could have the following structure:

final class Widget{
    @JsonProperty(access = JsonProperty.Access.READ_ONLY)
    private Integer id;
    @NotNull(groups={Update.class})
    private Integer z;
    private Integer x;
    private Integer y;
    private Integer width;
    private Integer height;
   //getters,setters
}

Widget had two reasons to be changed depending on new requirements for update and create.It doesn't follow single responsibility principle.

Possible solution

As a solution, I decided that Widget should be an interface and all validation logic should depend on a specific implementation. Widget interface gives you an access to x,y,width,height,z.

 interface Widget{
    Integer getZ();
    Integer getX();
    Integer getY();
    Integer getWidth();
    Integer getHeight();
}

After this I created an envelop for the Widget called ImmutableWidget which just has a single constructor that takes all widget's arguments and delegate them to method calls(Notice that this class is not final but all methods are finals which means that class could be extended but non of the methods could be overridden,you will see the logic behind it a little bit later)

Now let's return to the requirements, create and update widget. Simply enough let's create two different Widget implementations namely WidgetToCreate and WidgetToUpdate
This is how WidgetToUpdate looks like

public final class WidgetToUpdate extends ImmutableWidget {
    public WidgetToUpdate(
             final Integer x,
             final Integer y,
            @NotNull final Integer z,
             final Integer width,
             final Integer height
    ) {
        super(x, y, z, width, height);
}

As you may guess , WidgetToCreate won't have @NotNull annotation for z-index.
Here comes the power of ImmutableWidget. Two classes above just call the parent's constructor with custom validation logic for Jackson.And now, if requirements for update will change , then we will change only one class that won't effect create logic.

What about id?

What about id field? This field could be returned in a response body , but user can't specify this field in request. Again, let's create another interface called DbWidget that will extend Widget interface because both of them have the same parameters and let's add a new method to DbWidget called getId().

public interface DbWidget extends Widget {
    Integer getId();
}

Now we could accept some implementation of Widget in controller and return DbWidget implementation as a response.

    @PostMapping("/widgets")
    public ResponseEntity<Object> create(@RequestBody final WidgetToCreate widget) {
            return new DbWidget...
}

Conclusion

Right now, I see a few problems with this approach but the biggest one is the problem with the amount of classes.For every unique action we have to create a new implementation of the widget.However each implementation would be super small (if it extends ImmutableWidget).At the same time , with this approach, it would be much easier to change business logic because we can be sure that changes in one single class won't effect the whole system but only a small part of it