[VoxxedDaysTicino2026] Why Hexagonal and Onion Architectures Are Answers to the Wrong Question
Lecturer
Oliver Drotbohm is a senior principal software engineer at Broadcom, formerly part of the Spring engineering team at VMware for over 15 years. He has contributed significantly to Spring Data, focusing on repository abstractions, and more recently on architectural topics like Spring Modulith. Oliver is an advocate for modular software design and has spoken extensively on domain-driven design and system architecture. Relevant links include his GitHub profile (https://github.com/odrotbohm) and X account (https://x.com/odrotbohm).
Abstract
This article delves into Oliver Drotbohm’s critique of popular separation-of-concerns architectures like hexagonal and onion models, arguing they often prioritize decoupling over cohesion, leading to suboptimal code structures. Through theoretical analysis and practical examples, it explores software design principles rooted in coupling, cohesion, and anticipated changes. The discussion highlights trade-offs, the role of tools like Spring Modulith, and advocates for functional decomposition to achieve maintainable systems.
Fundamental Principles of Software Design and Cost
Software development’s primary cost lies in modifications rather than initial creation, as most efforts involve evolving existing systems. Oliver draws from Kent Beck’s interpretation of Edward Yourdon and Larry Constantine’s work, positing that change costs are tied to coupling between code elements—classes, packages, or modules. Coupling manifests when alterations in one area necessitate changes elsewhere, with its nature depending on the change type (e.g., database migration versus UI enhancement).
To minimize costs, decoupling is essential, but it introduces its own overhead, such as additional interfaces and implementations. Oliver emphasizes cohesion as the counterbalance: intentional coupling in appropriate places to collocate elements for common changes. Effective design creates cohesive units loosely coupled to others, essentially betting on future change patterns.
Systems emerge not just from parts but their interactions, per Russell Ackoff’s philosophy. Thus, design involves defining cohesive elements, promoting entry points, and establishing connections. This foundational view critiques architectures that overlook these dynamics.
Critique of Separation-of-Concerns Architectures
Hexagonal architecture, coined by Alistair Cockburn in 2005, centers domain logic, shielding it from infrastructure via ports and adapters. Ports are neutral entry points, with adapters depending on them, inverting dependencies to isolate the core. Onion architecture, by Jeffrey Palermo in 2008, similarly layers domain, application, and infrastructure, omitting explicit ports but maintaining inward dependencies.
Oliver compares these to layered architectures from domain-driven design (DDD), where presentation, business, and persistence layers interact, with business potentially depending on infrastructure. The key difference is dependency inversion, but terminology shifts obscure similarities. Spring applications historically embodied this: controllers (presentation/adapters), services (business/ports), repositories (persistence).
Yet, these models often yield complexity, with excessive folders for adapters, contradicting their goal of clarifying business logic. Oliver argues they answer the wrong question—focusing on technical separation rather than business cohesion.
Alternative Approaches: Prioritizing Cohesion and Encapsulation
Instead of technical layers as primary packages or modules, Oliver advocates functional decomposition, grouping by business slices (e.g., order, customer). This avoids scattering related elements across layers, akin to organizing furniture by type rather than function.
In code, vertical slices encapsulate internals: controllers, services, repositories within one package, hidden by default visibility. Public interfaces expose only necessary surfaces, enhancing encapsulation over mere organization. For simple read-only scenarios, direct JDBC in controllers suffices, hidden from outsiders. Complex slices warrant internal abstractions.
This yields cohesive bases automatically decoupled, as inter-slice connections are minimal. Intrinsic complexity dictates accidental complexity—pragmatic layering per slice. Tools like Spring Modulith enforce this, using annotations for stereotypes (e.g., @AggregateRoot), integrating with IDEs to display architectural concepts beyond packages.
Trade-Offs, Tools, and Implications
Trade-offs include initial simplicity versus future adaptability: technical packages force public interfaces, risking violations, while functional ones hide more, supporting evolution. Oliver notes developers’ inclination toward technical structures stems from IDEs’ technology-centric views (e.g., source/main/java), lacking higher abstractions.
Spring Modulith and ArchUnit address this, verifying rules and visualizing modules. IDE integrations (VS Code, Eclipse) convey code via design stereotypes, reducing package reliance.
Implications favor cohesion-first design: functional decomposition aligns with change patterns, reducing scattering. It supports DDD aggregates and repositories naturally, without mandating architectures. As systems grow, this prevents tangled messes from entangled business logic, not just direct database calls.
In conclusion, reframing the question from decoupling infrastructure to fostering cohesive, change-resilient structures yields maintainable software, leveraging tools for integrity.