The main problem seems to be that Clean Code is mostly a premature optimisation in code flexibility. It makes code more complex and objectively worse in hope it would be easier to extend later. Unfortunately we often dont know how the code will change, and in practice the code has to be significantly changed/rewritten anyway when a business requirement change appears.
IMHO optimizing for simplicity and readability has served me the best. Instead of avoiding the changes in code, it is better to write code so obvious that anyone can safely and easily change it when really needed.
And finally, performance of the program vs performance of the developer is a false dichotomy. So many times I’ve seen a more readable, simpler code turned out to be more efficient as well. You often can have both.
Yes, there has been some pushback to Clean Code and the SOLID principles. I’ve seen this kind of thing over the course of my career (anyone still using Hungarian notation?) There is “the way you should do it”, but, given enough time, “the way you should do it” changes. It could be said that a programming language is like a natural language in that either it lives as it is constantly modified by its speakers (or writers) or it starts to become a dead language used only by a coterie.
Still, there are some things I’ve seen stick around, like minimizing the use of NULL (or eliminating it completely) and minimizing the use of GOTO (it can still sometimes be handy for going to cleanup sections of code in some languages, but that’s about it.)
When I started to read about code, I was very soon presented to read Clean Code by “Uncle Bob”. And I read some part of it. I think there are a bunch of good things in Clean Code, but these are very general considerations. They are not super specific about Clean Code.
Then I saw Uncle Bob solve some Advent of Code exercise live. WIth a lot of TDD. I have watched other people solve AoC exercises and I got a lot from them. With Uncle Bob I mainly thought: “Wow, when does he start to tackle the problem. That is a lot of tests and so many tiny functions. Is this how professionals structure their day to day?”.
I mostly forgot about that experience. Until I came to exercism and saw bobahop on the site. My first thought was: “Please, let that be another Bob, I don’t want to read through all those tests”
I wanted to see if I could find that video. I could not, but I found his 2022 AoC solutions that are written in Clojure. A language that can be very, very concise. I love that part of Clojure. I took a random one and he had more than 180 locs and the commit is flagged as “easy peasy”. I also solved that one - in Elixir. And I was 13 days into the language back then. I used a quarter of that. If that is what Clean Code looks like, it feels very bloated to me and not fun to read.
When your code is organized by operation, rather than by type, it’s straightforward to observe and pull out common patterns.
I see the same on wikipedia:
Although OOP appears to “organise code around data”, it actually organises source code around data types rather than physically grouping individual fields and arrays in an efficient format for access by specific functions. Moreover, it often hides layout details under abstraction layers, while a data-oriented programmer wants to consider this first and foremost.
Optimizing code for performance always feels like a fun puzzle, but the maintenance cost is always in the back of my mind. Even in something like a compiler, making the code “as tight as possible” can backfire, if your implementation language does not allow for proper abstractions. The difficulties in adapting LuaJIT’s C codebase to the changes in newer versions of the Lua language come to mind. One such low-level trick in that codebase hinged on the fact that 32-bit address spaces were limited to 4GB, which allowed for some neat packing of data; that assumption, which was perfectly fair in the early 2000s, became central to the implementation. Of course, 64-bit systems arrived and assumptions changed. Getting rid of that limitation in a codebase full of smart data packing turned out to be a multi-year process.
Of course, if you can get a memory-efficient representation without hitting a maintenance cost, that’s the ideal situation. Some languages are better for this than others. I was impressed that Zig implements structs-of-arrays as MultiArrayList using apparently the same client interface as a regular ArrayList, such that changing from one to the other seems to be a “5-character change”.
Let me offer an alternative, even if unpopular here, point of view.
I think Clean Code is well worth a read. Same as many other old books on programming (e.g. the Design Patterns by the Gang of Four).
Regardless whether the ideas are popular right now or not, whether the examples given compare favourably to modern practice, they are still important to know. A lot of code has been written in this style, and it was an improvement to what was there before. I think it is important to study what worked and what didn’t work before. Considering what worked and what didn’t work in its original context, and how it applies today. In my opinion trying to understand the old ideas will help us make better decisions and not reinvent the same thing. And we do reinvent things every ten years or so.
So, in my opinion, some of the ideas in the book have aged better than others and the code examples are definitely not up to modern standards. I agree with many links provided. But especially here, the way I read the comments, it seems the book itself is considered not worth the read. I disagree. In my opinion it is a very important book which enables us to have discussions like this one.
Are you suggesting the book is worth reading as an important historic note in the development of coding styles? Or that the book is worth reading as an important approach to good current coding styles?
Those are two vastly different reasons for reading the book (though both entirely valid). Depending on what people are looking to gain or understand from reading the book, some of those reasons may apply to some people but not to others.
I mean both at the same time. It is an important historic note. But the styles are not constant, they evolve, and I think it is worth nowing what we have already tried and moved away from even if only not to go there again accidentally.
But I agree that the distinction can be made. It should be made. In fact, I think that is what I have missed both in this thread and in the What are your favourite books on programming thread, this is why I wanted to offer the less popular view.
I think we should make the distinction between the book in its historical context and the practices presented in the current, modern context. That’s it.
I agree. And there’s a third aspect: Books like this describe an existing problem and its negative consequences, present some alternatives, and explain why and how those alternatives solve the problem.
Even if you don’t agree with the proposed solution you can still take aways a lot from the other parts: Does the book describe a real problem? Are the consequences really that bad? Do the alternatives at least partially solve those problems?
I read the book and I still like it, I think it made me a better programmer. I do not follow its proposed style but thinking about how to structure my code, how to make it easy to understand, easy to maintain, and easy to combine with other code was definitely a win for me.