Assertfail

Clean Architecture Comparison

02 Dec 2023

High level image of the clean architecture from Uncle Bobs blog post:

The Clean Architecture image

Below is a comparison between clean architecture solutions in C# and Java. Most of the samples are in C#.

High level overview

There are some similarities and some key differences between the samples. No general conclusions can be taken from this comparison since:

Samples

Note also that the solutions I’ve picked are somewhat arbitrarily chosen. Some have a lot of attention on GitHub while I’ve kept my eyes on others for a longer time.

Sample Use of Libraries/Structure Grouping/Vertical slice
@CanerPatir/aspnet-core-clean-arch WebApi, Infrastructure, Application, Domain libraries Per use case grouping of folders in Application and WebApi
@ivanpaulovich/clean-architecture-manga WebApi, Infrastructure, Application, Domain libraries Per use case grouping of folders in Application and WebApi
@jasontaylordev/CleanArchitecture Web, Infrastructure, Application, Domain libraries  
@mattia-battiston/clean-architecture-example Groups entities and use cases in core project configuration, entrypoints, dataproviders, core libraries
@ardalis/CleanArchitecture Web, Infrastructure, UseCases, Core libraries Per use case grouping in Application
@dotnet-architecture/eShopOnWeb Web, PublicApi, Infrastructure, ApplicationCore libraries Aggregate, “Service”
@kgrzybek/modular-monolith-with-ddd Api, Infrastructure, Application, Domain libraries Per subdomain projects

Comparison

There does not seem to be a clear consensus around the naming of layers. Some projects are too simple to get into grouping into slices or subdomains, some of the projects (most notably modular monolith with ddd) shows how a more fleshed out structure could look (in the case that your web api only implements one bounded domain).

Sample Command handler interface/base class Query handler interface/base class
@CanerPatir/aspnet-core-clean-arch ICommandHandler IQueryHandler
@ivanpaulovich/clean-architecture-manga IOutputPort/Named IOutputPort/Named
@jasontaylordev/CleanArchitecture IRequestHandler IRequestHandler
@mattia-battiston/clean-architecture-example - -
@ardalis/CleanArchitecture ICommandHandler IQueryHandler
@dotnet-architecture/eShopOnWeb - Specification
@kgrzybek/modular-monolith-with-ddd ICommandHandler IQueryHandler

The solutions presented use a couple of different patterns. Most of the solutions use classes per action while some (such as eShopOnWeb) group all of the actions into one class per entity (in this case called service-classes).

We see that @jasontylerdev, @kgrzybek, @ardalis in their samples marries the framework MediatR. In the case of @ardalis we note that he marries the framework Ardalis.SharedKernel in his sample. In the case of the dotnet architecture sample eShopOnWeb that solution marries Ardalis.Specification. We can only echo what Robert C. Martin writes in his book Clean Architecture on page 292 that you have a extraordinarily asymmetric marriage when you take on a direct dependency on a framework. @ardalis is aware of this fact and write in the about text on his SharedKernel project the following:

Some useful base classes, mainly used with the CleanArchitecture template. Also, a template to make your own SharedKernel nuget package.

Sample Anemic domain entities
@CanerPatir/aspnet-core-clean-arch No
@ivanpaulovich/clean-architecture-manga No
@jasontaylordev/CleanArchitecture Yes
@mattia-battiston/clean-architecture-example Yes
@ardalis/CleanArchitecture No
@dotnet-architecture/eShopOnWeb No
@kgrzybek/modular-monolith-with-ddd No

The use of anemic domain model is not uncommon. A dissenting view from what Martin Fowler teaches is that you should embrace manipulating data instead of coupling data and behavior as seen in the book Data Oriented Programming. Note also that even though the domain might be too simple in many cases, I’ve given the authors the benefit of doubt.

Conclusion

From what I can see, there seems to be some convergence and some differences in naming conventions and patterns. These differences implies that it helps to document the source of your architecture and name conventions.

We have not gone into the how different samples around how they marry frameworks but simply noted that some of them do couple the domain to a framework. From a clean architecture point of view, being overly dependant on a framework, introduce significant constraints and asymmetries.

We could improve our understanding of how clean architecture is implemented by reaching out to different organizations implementing clean architecture, but that goes beyond the scope of a simple blog post.

Tags


Comments

Do you want to send a comment or give me a hint about any issues with a blog post: Open up an issue on GitHub.

Do you want to fix an error or add a comment published on the blog? You can do a fork of this post and do a pull request on github.