7

I've been reading a lot a bout hexagonal architecture and I do get most of the concepts (well, I hope I do), I didn't find any example of that architecture use-case wise.

Let's say that my application domain model is to make people drunk. The whole business logic is contained in Person class which resides in the domain layer.

class Person
{
    private $name;
    private $age;

    function __construct($name, $age)
    {
        $this->age  = $age;
        $this->name = $name;
    }

    public function drink()
    {
        if ($this->age < 18) {
            echo $this->name . ' cant drink';
        }

        echo $this->name . ' drinks tequila';
    }
}

Domain layer also contains a PersonRepository

interface PersonRepository
{
    public function findPersonByName($name);
}

implemented by:

class DoctrinePersonRepository implements PersonRepository
{
    public function findPersonByName($name)
    {
        // actual retrieving
    }
}

Let's assume I want to make a person drunk by accessing: GET /person/johnDoe/drink. Should I create a use case like:

class MakePersonDrinkCase
{
    /**
     * @var PersonRepository
     */
    private $personRepository;

    function __construct(PersonRepository $personRepository)
    {
        $this->personRepository = $personRepository;
    }

    function makePersonDrunk($name)
    {
        $person = $this->personRepository->findPersonByName($name);

        if ($name) {
            throw new \Exception('Person not found');
        }

        $person->drink();
    }
}

and call it from the controller? Should this mentioned case reside in domain layer or application layer? What is a port and adapter in this case? What if I want to have to ways of getting this person drunk - one from GET request, and other from some php console person:drink John CLI command? How should I structure my app?

acid
  • 1,939
  • 4
  • 26
  • 40
  • I think you're almost there - what is critical is the recognition that domain logic (a person should not be able to drink unless they are over 18) rests within the domain model and not outside the domain model. The surrounding infrastructure simply exists to adapt commands from the outside world to commands against your domain model. – Matt Jul 01 '14 at 07:43
  • Love your example :D I recently wrote a post which answers some of your questions, you may find it useful: http://jenko.me/ddd/2015/01/23/building-a-house-with-ddd/ – Jenko Feb 05 '15 at 11:21
  • Another article that explains it up to some extent: http://t.co/U7SZZcvevn – axiac Mar 19 '15 at 13:19

2 Answers2

2

TL;DR: I think that from a DDD point of view, you're basically right, but in order to be an Hexagonal design, you should be able to register or expose your use-cases in your primary ports: web, console or "usage" as @chris-f-carroll suggests.

I currently work in a big Java8 codebase project and we have structured our application following the principles of Clean Architecture/Vertical Slicing and CQRS. We have an Hexagon with 6 ports: web, console, database, scheduling, queues and email.

In order to initialize our app, we create all the required adapters and we use them to create our app instance. Then our app's modules explicitly register their use-cases on the primary port adapters. Finally we start our primary port adapters and the app is running.

Alistair Cockburn tells that "A port identifies a purposeful conversation". In our case, as our design implies CQRS, our purposeful conversation between our application and the HTTP protocol is about exposing Queries and Commands (our use-cases).

That's the reason for having expose(uri, query) or expose(uri, command) methods in our web port instead of get(uri, handler), post(uri, handler), put(uri, handler), delete(uri, handler), etc.

How these queries and commands are exposed (i.e. as HTTP GET or POST) is an implementation detail of the web port adapter that my hexagon needs not to know.

Community
  • 1
  • 1
ggalmazor
  • 691
  • 6
  • 18
0

Yes, what you've done/suggested is right.

  • The Use Case goes in the application layer. But note that this is a dictum of DDD specifically, nothing to do with hexagonal architecture.

  • Your Adapters are

    1. The web server together with your controller.
    2. Doctrine together with your DoctrinePersonRepository.
    3. The php executable+your controller again (assuming that your controller is re-used in the CLI app)
  • Your Ports: Cockburn says "What exactly a port is and isn’t is largely a matter of taste." Personally I'd say that you have 2 ports. I'd name one of them a persistence port for which you have 1 adapter; and I'd name the other a 'usage' port, for which you have 2 adapters.

The one-pager on hexagonal architecture is of course http://alistair.cockburn.us/Hexagonal+architecture

Chris F Carroll
  • 7,909
  • 2
  • 42
  • 51