Is “Clean Architecture” by Bob Martin a rule of thumb for all architectures or is it just one of the options?

softwareengineering.stackexchange https://softwareengineering.stackexchange.com/questions/371966

  •  06-02-2021
  •  | 
  •  

Pergunta

I really liked the concepts in the video The Principles of Clean Architecture by Uncle Bob Martin. But I feel like this pattern is like a combination of Abstract Factory and Builder patterns at its core.

This is one way to write good programs but not the only way.

Rails and reactjs are 2 frameworks that come to mind that do not promote this kind of clean architecture. Rails expects your business logic to be in the models (FatModels and SkinnyControllers), and react inside your components. Both approaches tightly couple business logic and framework code.

I don't find anything wrong in any of the 3 ways. It is a judgement call to pick any one.

But in the video I feel he suggests that clean architecture should have a clear boundary between business logic and frameworks. Frameworks (web, android, etc.) should be plugins that plug in to to the business logic. He even subtly mocks rails in the video.

So, Is "Clean Architecture" by Bob Martin a rule of thumb for all architectures or is it just one of the options?

Foi útil?

Solução

While the “Clean Architecture” is fine and has many advantages, it is important to remember that:

  • The Clean Architecture is largely Robert C. Martin's re-branding and evolution of related approaches like the Onion Architecture by Jeffrey Palermo (2008) and the Hexagonal Architecture (“Ports and Adapters”) by Alistair Cockburn and others (< 2008).

  • Different problems have different requirements. The Clean Architecture and related approaches turn decoupling, flexibility, and dependency inversion up to eleven, but sacrifice simplicity. This is not always a good deal.

The precursor to these architectures is the classic MVC pattern from Smalltalk. This disentangles the model from the user interface (controller and view), so that the model does not depend on the UI. There are many variations of MVC like MVP, MVVM, ….

More complex systems do not have just one user interface, but possibly multiple user interfaces. Many apps choose to offer a REST API that can be consumed by any UI, such as a web app or a mobile app. This isolates the business logic on the server from these UIs, so the server doesn't care which kind of app accesses it.

Typically, the server still depends on backend services such as databases or third party providers. This is perfectly fine, and leads to a simple layered architecture.

The Hexagonal Architecture goes further and stops making a distinction between frontend and backend. Any external system might be an input (data source) or an output. Our core system defines the necessary interfaces (ports), and we create adapters for any external systems.

One classic approach for strong decoupling is a service oriented architecture (SOA), where all services publish events to and consume events from a shared message bus. A similar approach was later popularized by microservices.

All of these approaches have advantages, such as making it easier to test the system in isolation (by replacing all external systems it interfaces with by mock implementations). They make it easier to provide multiple implementations for one kind of service (e.g. adding a second payment processor), or to swap out the implementation of a service (e.g. moving from an Oracle database to PostgreSQL, or by rewriting a Python service in Go).

But these architectures are the Ferrari of architectures: expensive, and most people don't need them. The added flexibility of the Clean Architecture etc. comes at the cost of more complexity. Many applications and especially CRUD webapps do not benefit from that. It makes sense to isolate things that might change, e.g. by using templates to generate HTML. It makes less sense to isolate things that are unlikely to change, e.g. the backing database. What is likely to change depends on the context and business needs.

Frameworks make assumptions about what is going to change. E.g. React tends to assume that design and behaviour of a component change together, so it doesn't make sense to separate them. Few frameworks assume that you might want to change the framework. As such, frameworks do present an amount of lock-in. E.g. Rail's reliance on the (very opinionated!) Active Record pattern make it difficult to impossible to change your data access strategy to the (often superior) Repository pattern. If your expectations of change do not match the framework, using a different framework might be better. Many other web frameworks do not make any assumptions about data access.

Outras dicas

I really liked the concepts in the video The Principles of Clean Architecture by Uncle Bob Martin. But I feel like this pattern is like a combination of Abstract Factory and Builder patterns at its core.

Not even close.

When you look at this:

enter image description here

You are looking at the design of an object graph. This dictates what knows about what. What's missing from this story is how that object graph got built. Sorry but you won't find that here. There isn't any mention of construction.

You can construct all this without abstract factories and builders. I know because I've done it. I didn't even set out to avoid them. I love them. I just didn't happen to need them. I just used reference passing. Dependency Injection is the fancy term for that.

In fact, I could build everything you see in that diagram in main. Then just call one method on one object to start the whole thing ticking.

Now things do have to exist before you can shove them into other things. I explored that here and gave it this cute little diagram:

enter image description here

And you can build all of that without even leaving main().

I would recommend using builders and factories when you want to break up a pile of procedural construction code into nice bite sized conceptual chunks. But there is nothing in clean architecture or any of the other buzzword architectures that demands that you do. So if you want to stick with main(), fine. Just please, have mercy.

Is “Clean Architecture” by Bob Martin a rule of thumb for all architectures or is it just one of the options?

I regard Clean Architecture as a buzzword used to drive people to a blog and a book. That blog and book have very good explanations of very similar older Architectures with older names used to drive people to older blogs and older books. Specifically Onion as well as Ports and Adapters. None of which are the only architectural options you have.

I like Uncle Bob because he's an awesome public speaker and author. He makes me think of things I wouldn't have otherwise. But if you let that turn you into a religious zealot that insists everything must be done his way you'll quickly find that updating documentation is the closest I'll let you get to my code.

The buzzword architectures are useful when you have long lived code that needs to persist while the world changes around it. That's when it shines. If the world is stable in comparison to the code, then you're making things fancy for no good reason.

No matter how awesome something seems there is a context you can put it in that will make it absurd. Sorry, this isn't a silver bullet either.

But in the video I feel he suggests that clean architecture should have a clear boundary between business logic and frameworks. Frameworks (web, android, etc.) should be plugins that plug in to to the business logic. He even subtly mocks rails in the video.

You're right. He does. Uncle Bob feels that frameworks can be treated like libraries. And they can. But even that decision costs you something.

What Mr. Martin is trying to preserve is a space where your general purpose language is still general. You give that up when you spread a framework everywhere. When you do that you're heading down the path of morphing your language into something called a domain specific language. HTML is a domain specific language. It does it's job very well but there are other jobs it can't do at all.

So long as your needs are anticipated by the framework things will go very smoothly. It's nice to have your needs anticipated. It puts you in a box that keeps things simple. Just understand what you're giving up to get this. If you spread Spring everywhere you can't advertise it as as a Java job anymore. It's a Java/Spring job. I could say the same thing about Ruby and Rails but Rails ate Ruby's lunch a long time ago.

To quote the video:

"You don't want to do mail merges in SQL."

followed by:

"I actually saw a SQL stored procedure which was an entire mail merge"

The architecture, like mail merges, is just one option among many.

What's not optional are the problems which the architecture is trying to solve.

If you understand what problems the SQL mail merge causes vs other solutions, then your architectural choice will be informed and even if you are forced to choose 'bad' solutions, you will be aware of and mitigate thier shortfalls.

If you follow an architectural style just because it is well thought of, then you are likely to make mistakes and encounter the same problems.

"Clean Architecture" is definitely "only" one of the options. I would argue it is one of the bad options for most projects, especially for object-oriented projects.

Here is a sentence-by-sentence analysis of Uncle Bob's article on Clean Architecture with the reasons for the above statement:

The Clean Architecture from an Object-Oriented perspective

Clean Architecture is a set of principles and patterns to address a number of common symptoms software development organizations often face over the lifetime of building complex applications. Mr. Martin goes to great lengths in the book to identify the symptoms and root causes base on his extensive experience in the field, and to clarify the role of architecture in mitigating these concerns.

However, It isn't a Rule of Thumb, nor a panacea to all ills. If you read the book, you'll have a better understanding of if/when/how to apply the principles and patterns he advocates (and the trade-offs involved). If you haven't read the book, you are likely to make incorrect assumptions, applications, judgements, and statements based on incomplete information.

Licenciado em: CC-BY-SA com atribuição
scroll top