Mathieu Eveillard

Hexagonal Architecture: Do We Still Need an ORM?

Hexagonal Architecture: Do We Still Need an ORM?

Today, let’s address a question that is often overlooked when discussing Hexagonal Architecture: is it appropriate to use an Object-Relational Mapping tool (let’s call it an “ORM,” for short)?

The problem is as follows:

The Hexagonal Architecture aims to isolate the domain and the application in order to avoid unwanted dependencies on the infrastructure (web framework, database, etc.), and thereby facilitate testing. It achieves this through dependency inversion. The implementation of such an architecture starts with the domain: the model that underpins the desired behavior and satisfies the business invariants is created before anything else.

But what does an ORM do? An ORM does exactly the opposite: it exposes entities directly mapped to database tables and manages their lifecycle, deciding for itself when to read and write data (an ORM is, in fact, most often a framework—see “Entity Framework”—at least things are clear). These entities are fully aware of the physical data model: if the infrastructure changes, the domain must change as well.

In other words, hexagonal architecture and ORMs are mutually exclusive.

You can, of course, use the ORM as an implementation of a secondary port for the domain: pure business entities to represent the domain, and the repositories exposed by the ORM to implement the same port. This is technically feasible, but very cumbersome—and what’s the benefit? In fact, you retain the benefits of the hexagonal architecture but lose those of the ORM. It’s like trying to have your cake and eat it too, or forcing squares into circles…

On closer inspection—and this is just my opinion—I actually find the promise of ORMs highly questionable. They promise that you won’t have to learn SQL, the standard language of relational databases. Except that to avoid having to learn this standard, you have to learn the proprietary pseudo-language of an ORM…

This is all the more problematic because the promise is only kept in 80% of cases—the simplest ones: 1-to-1 mapping, where an entity is mapped to a single table, possibly with a few joins. But sooner or later, you’ll end up writing SQL queries by hand—either for the 20% of business cases that are too specific to be handled by the ORM, or for performance reasons.

Whether or not you agree with this view doesn’t change one thing: it all comes down to the use case. An ORM may make sense in the case of a CRUD-type application (assuming such an application even exists, for that matter). Beyond that, as soon as you implement real business rules—isolated within a hexagonal architecture—there is no longer any room for an ORM.

← All posts