3

As I was reading a lot lately regarding the Ports and Adapters architecture, I stumbled upon this piece of code as a part of an application that was build following the above mentioned architecture :

package com.example.user.management;

import lombok.*;

import javax.persistence.*;
import java.io.Serializable;

@Table(name = "user")
@AllArgsConstructor
@Data
@NoArgsConstructor
@javax.persistence.Entity
@Setter
@Getter
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class User implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    private Long id;

    @Column(name = "username")
    private String username;

    @Column(name = "password")
    private String password;

    @Column(name = "role")
    private String role;

    public User(String username, String password, String role) {
        this.username = username;
        this.password = password;
        this.role = role;
    }

}

As the main intent of the Ports and Adapters architecture is to separate and isolate the domain layer from any technical details and implementations, and having in mind that this User entity is in fact, the domain layer, doesn't it contain dependency to the java persistence library? As I understand it, the domain layer is responsible only for implementing the use-cases. I am really confused as per what should actually be the Domain Layer in this type of architecture.

mka
  • 51
  • 1
  • 4
  • So somebody couldn't be bothered to create a DAO (and all the mapping). – Henk Holterman Feb 26 '18 at 15:24
  • I am guessing this was because it seems like the demo is simple CRUD app. But as ports and adapters (hexagonal) architecture is meant to be used in large, enterprise projects, this shouldn't be the case there. – mka Feb 26 '18 at 15:38
  • No, but in demos it often is. Don't assume too much. – Henk Holterman Feb 26 '18 at 15:47
  • Yes, but the demo violates the basic rule of the architecture - domain models should not be dependent on any technology stack. – mka Feb 26 '18 at 16:02
  • 1
    'domain layer is responsible only for implementing the use-cases' Personally, I think that application layer implementing use-cases. – shutdown -h now Feb 28 '18 at 12:02

2 Answers2

3

Excellent question, first note that hexagonal architecture does not have layers. Hexagonal architecture has an application and adapters with a one-way relationship between the two, nothing more. There is no domain layer.

The application communicates to its adapters using mere POJOs (without imports). These live in the application and are shared by the adapters. When an adapter needs to customize (adapt) one of these POJOs, it implements its own custom version of that object (e.g. via composition or inheritance). This splits the domain into what you might call the domain API and the domain implementation.

The domain API is specified by the application. This API must be agnostic of the technologies used by the adapters. So you are correct to say that javax.persistence doesn't belong in the domain API inside the application.

The code example in question is what you might call a domain implementation. It includes "plugin" technologies which the application is (and must remain) unaware of.

So you would put a POJO inside the application (without persistence annotations) and the above code would live inside e.g. a relational database adapter that would convert its domain implementation to the application's domain API.

jaco0646
  • 11,033
  • 7
  • 47
  • 64
  • So just to check if I am on the same page. The domain logic (aka all use-cases) would be simple POJO classes. The relational database adapter (or any other persistence adapter) would contain the technology specific domain model implementation. By doing this, I've satisfied the rule that the dependency flow always tends to go toward the center, not the other way around. I am just curious how would this be achieved with inheritance, the Entity classes would just inherit the POJO classes? – mka Feb 26 '18 at 15:54
  • The domain logic (use cases) are implemented in full-fledged objects with state and behavior. The inputs and outputs of the logic are POJOs. Adapters communicate with the domain logic by sending and receiving POJOs. Adapters may subclass the POJOs for customization; but composition is generally preferable as inheritance is a poor tool for code reuse. – jaco0646 Feb 26 '18 at 16:57
  • 'but composition is generally preferable as inheritance is a poor tool for code reuse. ' but composition need additional logic and code multiplication. In case Secured User [security] -> User -> Domain user. I think composition is better option for typical Domain business model not just simple CRUD like user.. – shutdown -h now Feb 28 '18 at 12:05
1

As the main intent of the Ports and Adapters architecture is to separate and isolate the domain layer from any technical details and implementations

The intention is to isolate the application from things that don't belong to the real problem the application has to solve. Those things are input/output devices, databases, technology frameworks, etc. The application code must be clean code. But the pattern says nothing about how you must structure the inside of the hexagon. You may have a domain layer or not, it's up to you.

this User entity is in fact, the domain layer, doesn't it contain dependency to the java persistence library?

Assuming you have a domain model inside de application with a User entity, the code you show here isn't that User entity. The domain model User entity must be tecnnology agnostic, no annotations, no framework code. The code you show here would belong to the persistence adapter that use JPA to access the database. In that adapter you would have to translate between the User entity of the domain model and this JPA User entity.

As I understand it, the domain layer is responsible only for implementing the use-cases.

According to DDD (domain driven design), Domain layer doesn't implement use-cases. Application layer does. And application layer calls domain layer in order to do it. But these concepts of layers, DDD, etc have nothing to do with Ports and Adapters architecture. The pattern says nothing about it.

I am really confused as per what should actually be the Domain Layer in this type of architecture.

This architecture doesn't say anything about what the Domain Layer should be. This architecture just says that you have an application (hexagon), ports (API/SPI belonging to the hexagon), and adapters (outside the hexagon). Whatever layers you put inside the hexagon is up to you, being Domain Layer or whatever.

choquero70
  • 3,332
  • 2
  • 24
  • 40