Clean Architecture (Ports & Adapters / Hexagonal Architecture)
An architectural style that isolates domain/application logic in a layer with zero infrastructure dependencies, enforced by module boundaries rather than convention, so business logic can be wired to different entry points (cloud providers, transports, frameworks) largely unchanged.
Also known as: hexagonal architecture, ports and adapters, onion architecture, domain/application/infrastructure layering, dependency rule (architecture), business logic isolation
Part of: Modularity & Coupling
Documents (2)
- Worse is better: C# versus F# Mark Seemann ยท 2026-09-08 source โ Reader ๐ฅ๏ธ
F# is superior to C# along most axes of comparison โ decisively so in F#'s built-in, compiler-enforced prevention of circular dependencies, which C# is unlikely ever to match โ even though F# is, ironically, the least popular of Microsoft's three officially supported .NET languages. - Presentation: Clean Architecture for Serverless: Business Logic You Can Take Anywhere Elena van Engelen ยท 2026-07-27 source โ Reader ๐ฅ๏ธ
Structuring Function-as-a-Service applications with a simplified Clean Architecture โ a domain and application layer with zero cloud dependencies, whose separation from infrastructure is enforced not by convention but by Gradle module boundaries, wired to cloud entry points via Spring Cloud Function's dependency injection โ lets a team write business logic once and deploy it, materially unchanged, to multiple serverless cloud providers, eliminating vendor lock-in without giving up native cloud capabilities.
Propositions touching this concept (1)
By publication month, oldest first (extraction month when no publication date is known).
2026-07
- explicitA simplified, lightweight version of Clean Architecture โ not its full classical layering โ is sufficient for FaaS code, because a single-responsibility function does not carry the complexity a container-based monolith needs the full layering to manage.
Open gaps (6)
- incompleteThe cost of this approach relative to its benefit is never argued. Extra interfaces, Gradle module boundaries, DI wiring, and CDK complexity have a real engineering cost, but the talk never weighs that against the โ for many teams, mostly hypothetical โ benefit of actually being able to switch or dual-run cloud providers, when most organizations pick one primary cloud for reasons (pricing, existing platform investment) unrelated to code portability and rarely execute a true migration even when the code is portable.Presentation: Clean Architecture for Serverless: Business Logic You Can Take Anywhere โ read next: extract-outsourced-ai-still-own-the-risk#p10 raises the structurally identical unresolved premise in the AI-vendor-lock-in context ('portability is achievable enough to function as a real hedge') โ worth reading together to test whether 'engineered portability' claims generalize across domains or share the same unexamined cost side.
- uninformedThe Q&A's observability answer treats 'generic logger + cloud-specific sink config' as basically solving cross-cloud observability, but doesn't address the harder problems: correlating a single business transaction's logs, traces, and metrics when parts of it run on AWS and parts on Azure, distributed tracing across clouds, or cost/retention differences between CloudWatch and Azure Monitor.Presentation: Clean Architecture for Serverless: Business Logic You Can Take Anywhere โ read next: extract-infoq-data-driven-platform-engineering (platform engineering and observability federation across a real multi-cloud platform) and writing on OpenTelemetry's cross-cloud adoption as the actual mechanism for correlating traces, not just directing log lines.
- incompleteThe claim that C#'s compiler is 'unlikely to ever' gain default acyclic-dependency enforcement is asserted, not argued โ especially given the article's own repeated framing that C# has been steadily catching up to F# on feature after feature for over a decade. No reason is given for why this particular feature would be structurally unportable (e.g. because it would be a breaking change to a decade of existing C# codebases) versus merely additive, as most of the other converged features were.Worse is better: C# versus F# โ read next: Read Seemann's earlier 'C# will eventually get all F# features, right?' (2015, linked in this article) for his own longer analysis of which F# features are and aren't likely to migrate to C#, and check whether dependency-cycle prevention was already flagged there as structurally unportable.
- incompleteThe 'what C# does better' section lists real, current C# advantages (Razor/GUI support, IDE tooling, cyclomatic-complexity/coverage/mutation-testing tool support, programmer availability) but never weighs them against F#'s advantages in any explicit cost-benefit โ each point is granted and then set aside ('I do occasionally find cyclomatic complexity useful, so it'd be nice to have tool support for that') rather than integrated into the overall superiority verdict, mirroring the same aggregation-without-weighing pattern flagged in the JSON-vs-XML predecessor article.Worse is better: C# versus F# โ read next: Look for a practitioner cost-benefit account of migrating a real C# codebase to F#, weighing tooling gaps (mutation testing, coverage, IDE refactoring support) against the architectural and expressivity gains claimed here.
- incompleteThe article names 'declarative programming is harder to learn than imperative programming' as a likely driver of C#'s greater popularity, but explicitly declines to investigate whether this is inherent to human cognition or an artifact of how most programmers first encounter programming โ leaving the actual mechanism behind F#'s unpopularity, and thus the practical case for or against teaching F# (or FP) first, unresolved.Worse is better: C# versus F# โ read next: Read CS-education or cognitive-science literature on whether imperative-first instruction creates a lasting bias against declarative/functional thinking, versus functional programming being intrinsically harder to learn regardless of instruction order.
- incompleteThe claimed F# tooling deficit for mutation testing rests on information the author flags as possibly outdated ('last time I worked with mutation testing in .NET I found no F# support, but it looks as though Stryker has at least rudimentary F# support... I should look into that in the future') โ the article's own concession that C# has a testing-tooling advantage is not verified as current at time of writing.Worse is better: C# versus F# โ read next: Check Stryker.NET's current F# support maturity directly rather than relying on this now-superseded claim, especially since this extraction may itself now be dated.