Uncle Bob is wrong about web frameworks (mostly)
By: Travis Weston
Tags: Uncle Bob, Code Architecture, Clean Code, Laravel, Programming

Image by ElasticComputeFarm from Pixabay

I’m a self taught programmer, which really means the majority of my instructors have been frozen in time in the form of the written word.

Robert C. Martin, aka Uncle Bob, is one of those instructors.

But, as we grow, and we look at subjects in our own light, it is natural that we will grow different views than our teachers. Which is what I’ve done lately around the topic of Clean Architecture, specifically around Martin’s arguments about folder structure and web frameworks.

What Uncle Bob says about Frameworks

I’ve watched nearly every video I can find on YouTube where Robert Martin gives a talk about clean code, or clean architecture. Granted, they’re largely the same talk, recorded in different venues.

I don’t mind.

It’s like reading a book multiple times, in multiple versions. I always leave with something new.

In this article I’ll focus on two such talks he gave at the Norwegian Developers Conference in 2012 and 2013. It was essentially the same talk, but with a slight twist the second year.

Both talks begin on the same note, however. In his short anecdote, he discusses how one day he was shown a folder structure by his son. With just a glance of the folder structure, he was able to deduce that the application was written in Ruby on Rails.

If you’ve ever spent any time working with frameworks, this is likely a familiar scenario to you. I can open any Laravel application and know instantly what framework it is using — if not the version. The same goes for CakePHP. Or Zend. Or any myriad of frameworks that are available to us.

But, for some reason, for Martin on that day, instead of treating it as a sign of development experience, as most would, it struck him odd that the first thing he sees in this project is the framework, and not the application itself.

He argues initially that the first thing one should see when looking at the folder structure is what the application is meant to perform.

Where Uncle Bob gets it wrong

This idea that folder structure should describe application intent is an excellent concept, and one that I wholeheartedly agree with — when we’re talking about your application code.

Where Martin get’s it wrong is in his argument that the web is an Input/Output device, and that our code shouldn’t concern itself with whether or not it is running on the web. It should simply care about the business logic.

Again, that’s not wrong on it’s face. He’s absolutely right about each of the words he’s said. But he’s wrong about one thing in particular:

Web frameworks are not part of our application, they are an abstraction layer

Martin seems to be looking at the web IO device as one would look at STDIN/STDOUT. The problem is, while standard in/out have operating system level abstraction support native to almost all languages, website IO does not.

When working with web traffic, there are some layers of bootstrapping that are required for any language to handle. Specifically, routing.

Look at any of the largest web frameworks available right now, and the first thing they tackled when getting started was how to handle routing. Why do you think that is?

Because routing is the last hurdle of the web IO device.

Just as it would be silly to argue that your Apache or Nginx installation is part of your core application, we should be just as critical of anyone claiming that our web framework is a part of our core application.

Why do I emphasis core? Because it would also be silly to not consider it a part of our application at all. Just as dynamic link libraries are part of applications written for native operating systems, but are not their core functionality, we incorporate frameworks as our libraries of abstraction to the web.

Folder structure is not architecture

Early on in his 2012 conference, Martin shows a list which he describes as representative of what a large number of people respond with when asked what their “architecture” is. That list is: Java, Eclipse, Spring, Tomcat, Hibernate, MySQL, and MVC.

He argues this is not your architecture, but your tools. And though I agree the list is not an architecture, it is also not just tools. It is a mixture of tools, and raw materials.

He uses the parallel of asking you for your architectural diagram, and you giving him a list of hammers and saws. But, though there are some hammers and saws on his list — Eclipse, for instance — there are also some lumber — Java — and utilities — MySQL — with a little touch of aesthetic — MVC.

He follows this list by attempting to draw a parallel between architectural diagrams and your folder structure. This is a tempting parallel to draw, and the first time I watched his talk I could have been convinced. But as I’ve rewatched, and pulled more out, it occurs to me that it is the wrong parallel to make.

Architectural diagrams are more akin to a planning document, or use case, than they are to a folder structure. They describe how the final product should look.

Uncle Bob is right about a lot, though

Martin quickly moves away from the focus on folder structure, and back to the actual architecture of code, however. The attempts to draw parallels to where files are placed are completely overshadowed by his diagrams explaining how to logically layout your application, and isolate it from whatever frameworks you happen to be using.

This is where he and I agree.

The problem with frameworks has nothing to do with whether or not they live at the root of your web folder, but whether or not they live in the root of your application logic.

Frameworks, as I described above, are simply an abstraction layer at their core. The core of your application should not care if it is being run from inside Laravel, or WordPress. You should be able to run it from the command line, given the right interface has been written.

Core application should not extend, nor implement, framework features

It’s tempting to allow your core application to use Laravel’s Eloquent models. It seems like it is going against the “Laravel way” to not use those models. But you shouldn’t.

Beyond that, your core architecture should not implement any Laravel helper methods, like the Str helper.

Your core application should implement interfaces, and should solely use those interfaces to accept data from whatever layer is providing it, provided that layer implements the interface correctly. This allows you to write your core business logic, and then abstract away the actual data sources.

Note, this has absolutely nothing to do with folder structure, and everything to do with application logic.

So let’s talk about folder structure

What I believe Martin was attempting to say with his folder structure argument is that folder structure should logically flow with application logic. This, on its face, makes absolute sense.

I’ve already talked in the past about using namespaces to clean up your code. Namespaces provide a ton of benefits, one of with is a natural, and logical, application folder hierarchy by simply designing your folder structure around the namespace structure.

Now, as I get into the weeds here, I’m going to be using PHP as my main example language, but this all works for any language that uses namespaces. Just at a theoretical level, not specific implementation.

But where?

I’ve been using Laravel as my example, so I’ll continue here.

It is my belief that you should avoid writing any of your business logic code inside of the app folder.

This is, I’m sure, a shock if you have used Laravel for any amount of time. The thing is, as we’ve already discussed, Martin is right about one major thing: Removing your business logic from your framework.

He may be wrong about directory structure, but maybe not as much as you think.

I know, I just pulled a little bait and switch on you there didn’t I?

Not really, but kind of.

In a production environment, your root will almost inevitably be a Laravel application. Trying to abstract things around so you implement all of the Laravel framework in your own way would actually make your application logic tied even closer to Laravel.

What you should do, instead, is write your business logic as a package, installed in the vendor directory VIA composer. Your business logic lives in one repository, your Laravel implementation of said business logic lives in another.

Which is likely what Uncle Bob meant all along

Robert Martin’s talks have a flair for both the dramatic, and a high intellectual bent. It would not surprise me if he had placed this discussion of folder structure at the start of the talks simply to draw out those of us willing to argue with him.

Just to bring us around by the end.

All of this is just proper separation of concerns

Separation of concerns is a topic Martin is well known for. He is, of course, the person who first formalised the SOLID principles (though, not the name SOLID) in his paper Design Principles and Design Patterns [pdf].

His approach to clean architecture is simply elevating the single responsibility principle to the level of architecture. If we treat groups of code as repositories, each repository should do one thing, and one thing alone.

In the example above, our business logic repository’s single responsibility is maintaining our domain logic. In fact, we could easily maintain separate repositories for each bounded context, allowing these contexts to communicate amongst each other via the same types of abstractions that we use for interfacing with the framework.

Uncle Bob’s Delivery Mechanisms

In the example above, the framework is what Martin would call a “delivery mechanism.” This is the name he provides for the abstraction layer that displays the results of your business logic, while delivering any necessary inputs to your business logic.

Each delivery mechanism is it’s own repository. In our example, Laravel would be a repository with the sole responsibility of acting as an abstraction layer between our business logic and the IO device that is the web.

Should we decide one day to change frameworks, it’s a simply a matter of writing new implementation code for that framework’s repository.

Architecture is about intent, not folder structure

Whether you decide to maintain separate physical repositories for your business logic, or if you store it all in the same repository, but outside of the traditional Laravel folder hierarchy, the fact is architecture is about intent, not folder structure.

The intent of your application is your business logic, and it is where business logic begins that we should be looking for that intent.

Martin’s logic may hold if we move the posts a hair. Instead of worrying about the framework root, we should be looking at the root of our application logic. If we find, in that structure, a hint of framework infection, then we should call it out as what it is — bad architecture.

If, however, we have separated our concerns enough that we are able to pull our business logic into a new framework, write the implementation code, and be up and running with no changes to our core business logic?

Well, then I say that’s good enough architecture.

Everything else, is details.