Hexagonal/Cockburn Architecture

My 2 years of experiences in software development, I found the big challenge is to write program that don’t break business logic of application, since the application code is so coupled with framework classes as well as database. Changing in database, requires the business logic to change according to database changes. Furthermore, If the framework’s libraries are out date or migrating to another framework version, causes breaking of lot of business models.

The intuition of Hexagonal architecture is that the business logic is independent of external entities such as HTTP, Database and Frameworks. The business logic should not be in the limitation of framework constraint.

This will make the application easy to extend and easy to test as the external dependencies can be mock or replaced by other alternates easily furthermore, the same business logic will be used different delivery mechanism such as HTML, console or desktop etc.

Rules:

Ports are the mechanism through which the logic communicates. It represents the boundaries between the layers. Simple example of ports are communicating from GUI, HTTP or other externals to core logic, these are also called Primary port.

On the other secondary ports are the port through which the core logic communicates with user.

Adapter are the implementations of the ports in which the logic is implemented, Like primary and secondary ports there is also a primary and secondary adapter.

First lets create a contract which is used by the database (external entities) to store data.

public interface IPersists<T,TCOMMAND> {
    void save(T t, TCOMMAND tcommand);
    void delete(T t, TCOMMAND tcommand);
}

Now, create domain logic

A POJO class representing domain

public class EmployeeDomainObject {

    public String name;
    public String address;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    @Override
    public String toString() {
        return "EmployeeDomainObject [name=" + name + ", address=" + address
                + "]";
    }

}

Lets provide the implementation when will to save is called. This does not know about how and who is storing the data but only provide the core logic.

public class EmployeeDomainDao
{
    IPersists adapter;

    public void save(EmployeeDomainObject t,EmployeeCommand commandObject)   {
        adapter.save(t, commandObject);
    }

    public void delete(EmployeeDomainObject t,EmployeeCommand commandObject)   {
        adapter.delete(t, commandObject);
    }

    public IPersists getAdapter() {
        return adapter;
    }

    public EmployeeDomainDao(IPersists adapter) {
        this.adapter = adapter;
    }
}

This contains the business/domain logic

public class EmployeeCommand {

    public String[] splitEmployName(String name)
    {
        return name.split(" ");
    }
}

Now plugin the primary adapter to persist data

public class DataBaseChannelAdapter implements IPersists<EmployeeDomainObject,EmployeeCommand> {

    @Override
    public void save(EmployeeDomainObject employeeDomainObject, EmployeeCommand employeeCommand) {
        String[] underlyingEntity = employeeCommand.splitEmployName(employeeDomainObject.getName());
        System.out.println("Called saved on " + underlyingEntity.length + " names");
    }

    @Override
    public void delete(EmployeeDomainObject employeeDomainObject, EmployeeCommand employeeCommand) {
        String[] underlyingEntity = employeeCommand.splitEmployName(employeeDomainObject.getName());
        System.out.println("Called delete on " + underlyingEntity.length + " names");
    }

}

 

Let use these services

public class App {

    public static void main(String[] args)
    {

        EmployeeDomainObject object = new EmployeeDomainObject();
        object.setName("First Name");
        object.setAddress("House No. 33 New York 1022");

        EmployeeCommand command = new EmployeeCommand();
        IPersists<EmployeeDomainObject, EmployeeCommand> adapter = new DataBaseChannelAdapter();
        EmployeeDomainDao dao = new EmployeeDomainDao(adapter);

        dao.save(object, command);
        dao.delete(object,command);

    }
}

 

DatabaseChannelAdapter can be replace by some other adapter for example FileChannelAdapter without changing the core logic. Moreover, if someone wish to use Spring Framework then one has to create controller and use the JPA or JDBC with DatabaseChannelAdapter rather with core logic.

In summary, Visual Studio, Eclipse or IntelliJ IDEA does not change there code/logic for some particular plugins but the plugins are developed according to their provided contracts.

 

Reference

Ports and Adapter Pattern / Hexagonal Architecture

https://8thlight.com/blog/uncle-bob/2012/08/13/the-clean-architecture.html

https://dzone.com/articles/hello-hexagonal-architecture-1

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: