Hexagonal Architecture seems to make so much sense when I read about it (like more than I can say; the ultimate eureka moment), but actually implementing it is a different story.
I more or less understand the structure, but my biggest problem I think is the delineation between components.
In the simplest example, say we're just doing simple retrieval of data, with a UI library, a Logic library, and a Data library (and a program running it all).
The user opens a window, or a webpage, and a list of data should appear there. The series of requests is something like: UI Event -> Primary Adapter -> Logic -> Secondary Adapter -> Database (and then returning back up the chain). (The Primary and Secondary Adapters have each implemented their respective Ports).
The main questions I have are:
- Who does what?
- Who lives where?
Let's say my DB Model is differently structured than my Business Logic Model. And then there is also a UI Model of sorts (presentation types).
I want to say that it should be the DB library's responsibility to translate the DB Model into the Logic Model, and that the Core Logic should be ignorant of this process. Similarly it should be the UI library's responsibility to translate the Logic Model into the UI Model.
But if I do this, then the issue is that I have not actually captured anything of value in the Logic Layer. And also, the UI Model is something that is not actually specific to any particular UI. The "presentation rules" are something that could be taken out of the UI and put into a reusable place.
It's almost as if there could be UI and DB "translation layers" put in between the Logic Library and UI and DB Libraries. You would then have a Logic Model, a separate UI Model, and an actual UI Implementation Library. Similarly you could separate the DB into one or more Data Access Libraries (in my case I have at least two separate databases), and a Data Translation Library that translates data from the DBs into the Logic Model.
Or... the translation could live in the UI and DB Libraries? Or it could live in the Logic Library?
As concrete examples, imagine that a single concept in the Business Logic actually comes from two different places (databases) and must be composed together. Similarly, when presented, there are things like running totals, grand totals, numeric text formats, etc. that are basically "UI Rules" rather than Business/Logic rules and are (or can be) separate from the UI implementation itself.
(And then I still feel like I would not have determined where things actually go in practice. For each interface that is defined there is the question of whether it should be implemented alongside it, or in the neighbouring library.)