THE ARCHITECTURE LAB

Published

- 4 min read

5 deadly Clean Architecture mistakes

img of 5 deadly Clean Architecture mistakes
Reach 13,500+ engaged devs by sponsoring this newsletter

I failed.

2 weeks ago, I wrote a post on X that caught a lot of traction and controversy:

Some people agreed that the Clean Architecture is the worst thing ever. And it was produced in the 7th circle of Hell.

Others wrote that Clean Architecture is the best thing ever. And it was born and raised in the Heaven.

The 3rd told me I was stupid. But that’s X for you.

But where I failed was in explaining what I meant with the post.

If you notice the double quotes around “Clean Architecture”, I wasn’t attacking the architecture style itself.

Instead, what I was pointing out was the idea that if you overengineer your Clean Architecture, or any other architecture pattern, then you lose a lot of the benefits that you would get with it.

Where developers get Clean Architecture wrong

Clean Architecture is helpful when applied with clear boundaries and simple rules.

The problems appear if you add more structure than your system requires.

This usually happens gradually.

With good intentions.

But it can lead to unnecessary complexity.

In some cases, developers make one or more of these 5 deadly Clean Architecture mistakes.

1. Overengineering simple projects

Clean Architecture shines in complex, long-lived systems.

But what happens when you apply it to a small CRUD app with minimal logic?

You get mountains of folders, interfaces, and layers you don’t need.

I’ve seen projects where there are more abstractions than actual business rules.

The cost of all that indirection outweighs the flexibility it provides when your domain is thin.

If your app is simple, your architecture should be too.

2. Leaking infrastructure into the domain layer

The domain layer is the layer in the Clean Architecture that should only contain your business logic.

When it’s free from external frameworks, it’s easier to change and easier to test.

On the other hand, if:

  • Entity classes execute the SQL code
  • Services reference the HTTP client or other web clients

You directly violate the Clean Architecture patterns.

And your unit tests become a maze of mocks, where every change to the code breaks 5 unit tests.

The people then blame unit testing. But the real culprit is the way the domain layer was implemented.

3. Organizing code by technical layers, instead of features

Often, when you look at various “Clean Architecture” templates, you get the folder structure like this:

  • Behaviors
  • Exceptions
  • Interfaces
  • Mappings
  • Models
  • Security

The top-level application tells you nothing about the application domain.

But what if you flip the switch and have the following structure in our app:

  • Categories
  • Orders
  • Products
  • ShoppingCarts
  • Users

Now, you know where to navigate when fixing a bug related to retrieving categories.

All code related to creating orders is in a single place.

Unrelated code is separated.

In other words, combine Clean Architecture with Vertical Slice Architecture concepts.

4. Mapping code everywhere

Another common trap is to have a separate DTO for every single layer.

Plus using the mapping library to connect the different layers.

Blindly mirroring every object across every boundary leads to enormous boilerplate, bugs in mapping code, and a codebase that’s painful to change.

Which is the exact opposite of what Clean Architecture promises.

Add mapping boundaries when you need to isolate the external layer, not by default.

5. Putting business logic in the wrong layer

This happens if you stuff logic into controllers or the presenter layer instead of concentrating it in Use Cases and Entities.

You end up with an anemic domain model that does nothing but holds the data, while a fat controller becomes the real brain of the application.

This makes the core logic untestable without integration tests that call the API layer.

And defeats the purpose of the architecture entirely.

What the Clean Architecture is about

Clean Architecture gives you a simple blueprint to keep your monolith healthy as it grows.

The essence of the Clean Architecture blueprint is as follows:

  • Separate your domain from everything else,
  • Push 3rd-party dependencies to the edges,
  • Keep dependencies flowing in one direction.

Nail this, and your code will be easier to test, easier to change, easier to evolve, and easier to test.

If you're a .NET developer ready to architect scalable systems...

Every Friday I reveal insights with frameworks, tools & easy-to-implement strategies you can start using almost overnight.

Join the inner circle of 13,500+ .NET developers