Question

I really like the fundamental principles behind the Hexagonal Architecture (Ports and Adapters) and I have mostly applied it to my system/application.

There is one thing that I wasn't able to completely grasp:

  • The system needs to wake up and do some actions during specific hours of a day. For example, it needs send notifications to users at 7pm UTC.
  • I have a Cron job scheduled in the OS that invokes my Python application via a Bash Script.
  • I am guessing time is the Primary Actor.
  • How this primary actor interacts with my system isn't all clear. I am guessing the combination of Cron Job + Bash Script become the adapters

Does anybody know how such time based events are modeled in the "Hexagonal Architecture"?

Was it helpful?

Solution

Let us look into Alistair Cockburn's description of the Hexagonal architecture:

A ‘’primary actor’’ is an actor that drives the application (takes it out of quiescent state to perform one of its advertised functions). A ‘’secondary actor’’ is one that the application drives, either to get answers from or to merely notify. The distinction between ‘’primary ‘’and’’ secondary ‘’lies in who triggers or is in charge of the conversation.

I think it is pretty obvious that a "cron job" or "timer event generator" fits perfectly into this description of a "primary actor". It "lives" outside of your core application (since it is part of the operating system or environment), and it definitely "takes it out of quiescent state to perform something".

And yes, the cron job as well as any script which supports it are "adapters" in this sense; your core application can be run without them, for example, started fromt a test driver which simulates the timer event. If, however, you would have designed your core application differently, without cron and with an in-built time service, then the "timer event mechanism" would be inside your system, and there would be no adapter any more.

One note: I would not speak of "Time" as a primary actor, this is not "Alice in Wonderland". I prefer speaking of "the cron demon", or "a timer event service", or whatever this thing is called in the particular system.

OTHER TIPS

In short

Despite a "yes" could be defended, you shall not consider time, nor even cron, as primary actor. Using cron is only an implementation detail to achieve periodical action.

Some more details

In theory, time is not an actor

Actors are not part of the hexagonal architecture, but belong use-cases of the system (link to Alistair's archived original article is in the references of wikipedia):

This is related to the idea from use cases of “primary actors” and “secondary actors”. A ‘’primary actor’’ is an actor that drives the application ...

These actors interact with the system to achieve their goal. I'm not a qualified philosopher, but I think that time is a dimension and has no goal. And if it would have, it would certainly not need our systems.

In a use-case analysis, cron could be seen as a separate system, that uses your system to achieve its own goals, and could thus qualify as primary actor. But does your system bring any value to cron and interact with it?

In practice, cron is not an actor but an implementation detail

Although we could argue whether theoretically cron could be an actor, in reality cron is just an implementation detail. Cron does not need your system, but your system needs cron to fulfil a periodicity requirement.

The right way to handle this implementation detail is, as you say, to view cron + bash script as an adapter. Another valid implementation could be to let your system in the background and monitor itself the OS timer. For the human observer, this would make no difference and would address exactly the same requirements.

Note: Timing considerations are usually not relevant for use-case and actor identification. Time is specific to the sequence of actions; so you would show it in activity diagrams with timing events, or in timing diagrams (although these seem overkill here).

But what was the problem in the first place?

Your question is meant to help you design your architecture. Let's read Alistair's article till the end, to see how actors are used :

the asymmetry matches Ivar Jacobson’s primary and secondary actors concept, and affects how the Configurable Dependency is implemented.
...
In the case of primary actor ports, the macro constructor will pass to the UI, test framework, or driver the handle for the app and say, “Go talk to that”. The primary actor will call into the app, and the app will probably never know who called it. (That is normal for recipients of a call).

In your special case, whether cron is or not an actor would not really influence your design. The macro-constructor would probably be the same.

The question of the primary actor is a different one:

  1. Isn't there some interaction between your system and some humans or other system? Your app may talk with the standard input/output (redirected from somewhere), may use files (provided by real actors, users or other systems), may interact with real actors (directly with user or remote systems, or indirectly via log/output files).
  2. How should the construction process be these interactions? For example, how would the construction be different for running tests and for the productive use?
Licensed under: CC-BY-SA with attribution
scroll top