I'm going to start this with saying that Clean Code helped me a lot early in my career.

It also hindered me a lot.

Clean Code places so much emphasis on things so trivial... I was misinformed about what is actually important to writing software.

This used to be my top recommended book. Now I recommend Beyond Legacy Code.

This isn't about why I recommend it, and it's not the code level Clean Code provides. For code level I suggest Elegant Objects.

Why

Why am I writing a review of a book 10 years old? It's still so strongly recommended as a "best practices" book - I want to have a place I can direct people when they ask, "Why?" after hearing me say, "It's a terrible book". There's a little context around when I say that - and that's why I'm writing this.

Little Story

First though, a little story.
I read a lot. Stupid amounts. I learn really well from books - but I won't get into that.

Despite reading all of the recommended books, and trawling their bibliographies for more... I couldn't write good Object Oriented code.

I read all the books - I couldn't write maintainable code.
I knew SOLID inside and out - I couldn't write maintainable code.
I didn't UNDERSTAND HOW - I couldn't write maintainable code.

None of the books I read actually helped me write better object oriented code. I stuggled for 20 years to write maintainable code - and I knew what I did wasn't.

After how to write Object Oriented code actually clicked (forever thankful to Fred George and Yegor's Elegant Objects) ... I had a sense that all of the books purporting the Software as a Craft mentality, the Craftsmanship practice, had an underlying assumption - That you understood how to write good OO code, and these are things you get from it.

These aren't the instruction guides I thought they were.

Here's why Clean Code isn't A Handbook of Agile Software Craftsmanship.

The Review

I decided I had to re-read the books I previously recommended to see if they really line up with my new understanding of writing highly maintainable code.
First up is the one I most often recommended: Clean Code.

When I read, I put post-its in the book with notes on them. This review is the result of those post-its.

The Good Parts

The book has good suggestions for writing code so others won't hate you; don't get me wrong there. Things like "Meaningful Names" - Fantastic to do. The advice, I don't think it's all great.

Uncle Bob's written ten thousand sentences, you should read them all. Kent Beck wrote 4 - Memorize them.

Second rule of Simple Design - Convey's intent. How? Keep itterating until it conveys the intent.

I'm sure there's more useful bits in here... But that's not really what I'm going to focus on.

There are useful suggestions, I just don't see the whole being valuable enough to warrant the place it has in our industry.

The Complaints

Clean Code's subtitle is, A Handbook of Agile Software Craftsmanship, which I disagree with. It's got a lot of suggestions to make others looking at your code not hate you as much - but it doesn't bring it near the level of code quality I'd expect from a book talking about being a Crafter. (My term, Uncle Bob still fights the gender-neutrality efforts around it)

I don't feel the book goes in strong enough terms. As a fresh developer, SHOULD, MIGHT, MAY - These are things that if I don't know how to do them, it's a suggestion... which I'm happy to ignore.

I understand the use of this language, but it's cheat. I've given talks and used my "SHALL NOT" and "NEVER" form to get feedback of "You shouldn't use such strong language, it'll turn Sr Dev's off of your message". No critique of the content... just the tone.

Bullshit.

Deal with the content. If someone will stop listening because I'm voicing a strong opinion, then they can't face their own inability to argue against it.

For Example

We can't always avoid switch statements

You CAN avoid switch statements. It's hard. It requires different thinking. A switch stuffed in the bowels of the program to make the polymorphic decision is quicker/easier... But it's not un-avoidable.
switch is always evil and you can always avoid using it; Do So.

One of my stickies is about testing. I'm going to trust my earlier self that the book has about 12 pages on testing. That's about 3% of the book. I don't remember where/how I got 12 pages, but that's what I wrote.
TDD gets a single mention. Two WHOLE lines. ... For something as critical as Test Driven Development and testing in general - for it to fail to have any emphasis in a such a well recommended book for the industry is a travesty.
The sections that talk about tests are fully in favor, but never in strong terms.

But I also have a suite of unit tests that cover every one of those clumsy lines of code

This isn't "You should always have a suite of tests covering every line". It's "I have". Doesn't drive the reader to start writing tests for all their code - which is so super critical to maintainable code - you literally can't maintain code without tests.

Comments

There's an entire chapter called "Comments". As a fresh dev - An entire chapter? Damn, better get good with my comments. Tests.... those are off handed remarks... Comments is where I should focus!

I gave the topics with more content more weight - I kinda assume a book about how to write good code would have more content about the things that matter more. ... Like "Formatting"... Oh yea... That's a chapter.

Depending on what page count you want to give the book (I stopped 'reviewing' at chapter 14 because it's a walkthrough)... How to comment and format your code is about 20% of the book.
1/5 of the book is about not actually code. I gave comments and formatting A LOT of weight in those early days. I drove a few adoptions and standardization efforts. It's not bad to have those - but my reason and singluar push was wrong.
There are better ways to get them, mostly by pairing and mobbing - everyone starts to write the same.

Saying things like

Sometimes you really do want simple data structures with procedures operating on them

and expecting developers to develop good object oriented programming practices is just silly.
Databags are only violation of encapsulation. If you need to operate on them, encapsulate the data. I fully reject the quoted statement for OO systems.

I really dislike how acceptable "Data Transfer Objects" are made to be. They can exist, but it doesn't mean they should. They are databags. They aren't objects - why do they float about an OBJECT oriented code base? They shouldn't. The terminology should be a lot stronger about not using them and the damage they cause to a system when they escape the VERY NARROW space they MIGHT have to exist in.

I've looked at code I wrote and thought, "This smells, but X, so I can't do anything about it". This thinking, and the book saying "Active Records are OK to pass around, and don't put methods in it" is ... horrific to me now. If I see code that smells now, I find a way to remove the smell. Push it away until it exists in ONLY one place if I can't get it out entirely.
Allowing a smell in is allowing it to spread.

NULL

I'm harsh about books being weak against null. Clean Code has some pretty good headings

Don't Return Null

Followed by a little over a page of content.

Don't Pass Null

Followed by almost two pages of content.

That it's focused on still protecting against null, with asserts instead of throwing NPE... That's a null check. You still have to deal with null.

The book seems to contradict itself by saying

the problem is that [the code] has too many [null checks]

And later has

assert p1 != null : "p1 should not be null";
assert p2 != null : "p2 should not be null";

as ... guard asserts? for a method. This is "too many null checks" regardless if the syntax is an if or an assert... If it smells one way, it smells the other.

There's a few one line off-handed mentions of ways to help protect the code from nulls.

This, in particular, is where I feel that it's assumed certain things about how the reader handles nulls. That certain things are ... known? Which ... when they aren't leaves so many gaps in understanding how to write good effective maintainable code.

Tests

There is a chapter on tests... Mostly on me for failing at this early in my career. It's still only 12 pages, less than half of comments and formatting.
TDD is hard, and it's put forth as so trivial. That failure at it feels like personal failure and is abandoned. ... Could just be me.

I don't think tests are given the weight they need in the book, especially when Comments and Formatting each alone have more pages than testing.

Failed Me

This is where these books failed me. They'd say the good things

Class should have a small number of instance variables

How do I get there? The assumption of TDD and the knowledge of the techniques and practices to have a small number of instance variables is assumed, or left out.
I can see that this isn't a HOW TO book - even though it reads like it's telling you how to do something.

It's just brushing on the practices like there's another book un-mentioned that gets explicit on how to apply these. Not just know about them - Which Fowler's Refactor gives you the KNOW, but not the HOW.

These skills are hard - without a mentor to help... Software engineers will not be successful in learning to apply these techniques. This is a missing piece from the book, and the industry.

Conclusion

I don't recommend this book any more. Others still do, and I'll say it has some useful information if asked. It does. I think it just places too much emphasis and time on entirely unimportant things.
While lightly touching on other things that when practiced repeatedly in a Kata can help drive understanding... like the 4 rules of simple design. Which got... 5 pages. Slightly more than a page per... if you ignore code. And that the first and last are 1/2 page each... ... A crucial simple list and it's not even fully laid out...

As a friend threatened to quote me once, "Clean code is a horrible book to learn how to write good OO from". Maybe it's not the purpose, but it's how I see it recommended, and it fails at that.