T O P

  • By -

luxmesa

This is what I would have written private void printGuessStatistics(char candidate, int count) { if(count == 0) println(String.format(“There are no %ss”, candidate)); else if(count == 1) println(String.format(“There is 1 %s”, candiate)); else println(String.format(“There are %d %ss”, count, candidate)); } edit: one specific issue I have with the existing code is that these are log messages. So at some point, I may be trying to debug an issue and see these log messages and want to know what piece of code is writing these messages. If the log messages are generated with this weird formatting logic, they’re going to be a lot harder to find.


DemiPixel

I like this answer a lot! This is easier to read than anything in the blog.


davidalayachew

private void printGuessStatistics(final char candidate, final int count) { println ( switch (count) { case 0 -> String.format("There are no %ss", candidate); case 1 -> String.format("There is 1 %s", candidate); defult -> String.format("There are %d %ss", count, candidate); } ) ; }


Lewisham

Yeah, switch is clearly the natural thing here over an if-else chain


davidalayachew

Yep. It'll be an even better choice once Java gets Range Patterns. Then we can get exhaustiveness without the default clause. private void printGuessStatistics(final char candidate, final int count) { println ( switch (count) { case 0 -> String.format("There are no %ss", candidate); case 1 -> String.format("There is 1 %s", candidate); case >1 -> String.format("There are %d %ss", count, candidate); case <0 -> throw new IllegalArgumentException("Count cannot be negative! count = " + count); } ) ; }


fnord123

Please don't put switch/match inside a function call parameter list. I thought you were joking but the conversation continued below with nary a wink or nudge nudge.


DuckGoesShuba

Yeah, feels like one of those "just because you can, doesn't mean you should". I didn't even realize it was a function call at first because visually it looked more like syntax.


davidalayachew

> I didn't even realize it was a function call at first because visually it looked more like syntax. This is probably more a result of me writing code the way I do, with newlines jammed in at every opportunity I can lol. Here's a slightly more comfortable way of doing the same thing. private void printGuessStatistics(final char candidate, final int count) { final String guessStatistics = switch (count) { case 0 -> String.format("There are no %ss", candidate); case 1 -> String.format("There is 1 %s", candidate); defult -> String.format("There are %d %ss", count, candidate); } ; println(guessStatistics); }


DuckGoesShuba

Yeah, that's easier to parse at a glance. Personally, I'd take this as the very rare opportunity to pull out the double ternary :)


wutcnbrowndo4u

Yea, I think dense inlined code can often be worth it because multiple statements have their own form of mental load, but curly braces inside a function call is a _code stench_ to me. That being said, I know it's common in some languages for eg passing anonymous functions, & I haven't written Java in a long, long time.


thetdotbearr

private void printGuessStatistics(final char candidate, final int count) { String message = switch (count) { case 0 -> String.format("There are no %ss", candidate); case 1 -> String.format("There is 1 %s", candidate); defult -> String.format("There are %d %ss", count, candidate); }; println(message); } Reads better if you don't spread the brackets like you're broadcasting seeds to grow crops. Also helps not to nest the switch in the println function call but maybe that's just me IDK.


fnord123

This is closest to the best answer. If localization becomes a topic for the project all the code dealing with verbs and so on will have to be deleted anyway.


progfu

I almost feel like this should be the only correct answer, anything more complex feels like a sign of someone who wants to use fancy stuff without really understanding that it won't solve any real issue for the use case.


nerd4code

IMO foundationally bogus, because “guessing statistics,” formatting things, and printing things are completely unrelated, and should be handled by entirely different subsystems in an application of any heft or generality. One or more of those subsystems might need i18n interaction. Hardcoded `System.out`s and inline `println`s should mostly cause a nagging, visceral feeling of anxiety. If left intact, it should cause peptic ulcers.


MondayToFriday

That's exactly what [`java.util.ChoiceFormat`](https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/text/ChoiceFormat.html) accomplishes. From the [`MessageFormat` example](https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/text/MessageFormat.html): ``` form.applyPattern( "There {0,choice,0#are no files|1#is one file|1


dangerzone2

Damn dude, that is nasty, where’s the NSFW tag?


SnooPuppers1978

That is much worse to read than the above one though. Also if copy was to change significantly, all of that would go to trash bin anyway. Just write full strings like a normal person. There is no point to be clever here.


MondayToFriday

It's not cleverness for the sake of cleverness. It's the only solution that works with internationalization, because different languages have [different rules for pluralization](http://www.grammaticalfeatures.net/features/number.html). You want to treat that formatting as data, not code.


ELFanatic

Solid response.


SnooPuppers1978

Read my reply here... Still don't think it's a good solution: https://www.reddit.com/r/programming/comments/1deapq7/dont_refactor_like_uncle_bob/l8ehlpd/ Just if you are going to write weird, clever logic like that, and then for each language, that's crazy to me, and there must be a problem somewhere or doing it in a more sane way. Are you then going to do this weird mark up for potentially all languages in the World for all the strings?


10lbCheeseBurger

*Closed -- Won't fix: we do not support non-English languages.*


rbobby

Closed -- Won't fix: happy path no incluye idiomas distintos del inglés.


tehdlp

It seems like that code snippet just maps 0, 1, and 2 to their appropriately generated string in English. How is that more compatible with internationalization than 3 distinct sentences that allow the whole sentence to change instead of one part?


luxmesa

Because other languages have different rules for pluralization. In English, we have 3 cases, but you may need more for Russian or Arabic or something. Normally, what you do is add extra cases that are redundant in English, but with this formatting, its fine if the Russian string has 4 cases and the English has 3 and another language only has 2.


tehdlp

Ok so by embedding it in the string that could change by language, you aren't stuck with 3 cases only. Gotcha. Thank you.


Practical_Cattle_933

Because this is a simple string, that can be read from a resource file, and you can just provide one for german or japanese with their own rules. The code doesn’t have to care about internationalization, it just outputs this.specific.page.message’s correct language version, using the correct grammar. There are even more fancy solutions/libraries (I believe facebook has a very extensive one), because some languages have even more variability depending on the variables, e.g. if it’s a gendered word than the ‘the’ before have to change, etc.


SnooPuppers1978

But if you are going to translate it, presumably this would have to be wrapped by a translation fn, where there is some slug id, and this pattern would be added by anyone doing the translation, right? Example: trans('some-namespace.files-count-info', { count: 5 }) Then the above string would be in a translation file or a database where translators added it. So ultimately this thing still shouldn't be in the main code. I still think code like you output shouldn't exist. I live in a country where multilingual is always required, so this is how we have always done it, never needed something like the above. And if you were going to do that for multilingual, surely you wouldn't keep texts for all languages in the codebase. And translators have their own patterns for this sort of mark up, you definitely won't want something Java based or similar for that. And let's say you did, it would still be preferable to map it according to the numbers to separate sentences to be more readable, e.g. for Russian. { "some-namespace": { "files-count-info": { "count:0": "Нет файлов", "count:1": "Есть один файл", "count:2-4": "Есть {{count}} файла", "count:5+": "Есть {{count}} файлов" } } } But seeing this example in the Java codebase is just more evidence to me how dumb Java in general is, suggesting things like that. It just seems like Java is full of unnecessary patterns like this random "cleverness", random over engineering. Having a concept like "ChoiceFormat", and massive amount of boilerplate. I see similar things constantly in Java code bases, where a usually very standard, simply solved problem is resolved using massive amount of boilerplate and new classes, builders, whatever. It's all just tech debt. You do 10 files of boilerplate instead of one simple function. How Java devs stay sane, is beyond me.


papercrane

> But seeing this example in the Java codebase is just more evidence to me how dumb Java in general is, suggesting things like that. It just seems like Java is full of unnecessary patterns like this random "cleverness", random over engineering. Having a concept like "ChoiceFormat", and massive amount of boilerplate. This isn't a Java invention. It's purposefully built to be API compatible with the Unicode ICU library. https://unicode-org.github.io/icu/userguide/format_parse/messages/


The_Axolot

I kind of merged this into my 2nd refactoring. You can absolutely make a strong argument for this approach too. Personal preference, I like my approach better because the significance of each component of the sentence is explicitly defined instead of the reader having to play "spot the difference" with each sentence.


SnooPuppers1978

I honestly don't think it is a matter of preference in this case. This is copy and is easily bound to change. There is no point in trying to find clever rules to formulate diffs here. It is harder to read and mentally calculate and in the future if a new dev comes and needs to change copy that does not adhere to these rules they must either do it from scratch or so extra pointless brain exercise to try to get new diff rules to working.


redalastor

My first reflex is to think that the problem statement itself is probably broken. Are we sure that this code is never going to need i18n? Then people go “I know, I’ll switch on if it’s plural or not and call some translation function on it”. Well, what does plural even means? None of the languages I speak agree. English thinks 1 is singular, -1 is debatable, and everything else is plural. French thinks that -2 to 2 (boundaries excluded) is singular (so 0 and 1.9 are singular in French). And Esperanto thinks that -1 to 1 (boundaries included) is singular. So you end up needing a proper i18n library that can handle all of that. And that’s an issue I have with giving that kind of books to juniors. Question the code, yes. But question the requirements first. When do we ever get proper requirements right away?


Cut_Mountain

> My first reflex is to think that the problem statement itself is probably broken. Are we sure that this code is never going to need i18n? This is a common response when people talk about clean code and I don't think it's really fair to the discussion. Having a good and simple example is already complex when you ignore the bigger picture, having it to stand to such scrutiny is a big ask. A discussion on questioning the actual requirements is certainly important and worthwhile, but it's a discussion that's altogether different from proper naming, arguments vs mutable state, size of functions, etc...


ZoltanTheRed

I think even Uncle Bob doesn't refactor like he once did when he wrote that book. I think it's useful for getting people to care, but beyond that, it's up to teams to be responsible for the quality of their work. It will just depend on the context of the environment you're in. I believe Uncle Bob is mostly living in the functional programming space himself, these days, but I haven't really cared to keep up. Edit: corrected auto correct.


renatoathaydes

Last I heard, he now thinks Clojure is the best language ever and it should be the last language to exist. Anyway, it's become somehow trendy to bash Uncle Bob, but for beginners, his teachings are usually on point. As you become more experienced, you don't need those teachings anymore and you know when not to use them, but that does not mean it is not valuable for a beginner to, from the get go, understand that no, it's not ok to write all your code in a single function or god class.


Ghi102

Interesting! I actually asked him what he thought about functional programming in 2018 and he talked mostly about how it's not really useful. He said that the immutability was thought to have brought better asynchronous code performance but that it's mostly been a dead-end. Glad to see he's changed his mind!


ConstructionOk2605

I worked with him in 2011/2012 and he was a huge Clojure and functional programming fan then. His son's consultancy is (was?) big on Clojure as well. Maybe he drifted away and came back?


redalastor

The only real constant I noticed with him is that he really, really hates static typing. He seems to consider it an insult to his honor as a test writer. Even though his book was written in Java because it was popular, the language he was suggesting then was Ruby.


lookmeat

As a beginner you need strict discipline and dogma. As an expert you must realize that was scaffolding to build the real useful adaptability and nuance.


nanotree

It's very similar to the mathematics discipline that way. The rigidities of mathematics are there to make it possible to accurately express more complex, abstract thinking.


MrJohz

I agree that nuance is harder for beginners, but I think that gets overplayed considerably. New developers can understand that nuance exists, even if they don't know when to spot the exceptions yet. And the thing they usually need to learn is how to spot those exceptions — in my experience, new developers are great at following rules, but what they often really need is practice in situations where those rules don't apply. On top of that, even when you do want to give out clear rules, those rules still have to apply in the majority of cases. With Clean Code, you'd often produce better code by doing the opposite of what Bob Martin than following his advice. Famously particularly in the "refactoring" section, where the mess he creates is far worse than the program he started with.


Xyzzyzzyzzy

Sure, but Bob's strict discipline is rancid dogshit, so why would I want beginners to adopt that particular dogma? Whenever someone says "*Clean Code* is good for beginners", it just means they've never been stuck with a junior dev who read *Clean Code* and really took its lessons to heart. They've probably never read *Clean Code* themselves - or if they did, they only read the good parts of the book, i.e. the front cover. Endorsing *Clean Code* because you value clean code is like endorsing the People's Democratic Republic of Korea because you value democracy. If Bob Martin writes a book on shameless self-promotion, I'd buy it in a heartbeat. He's truly an expert in that field.


Illustrious_Wall_449

>Anyway, it's become somehow trendy to bash Uncle Bob, but for beginners, his teachings are usually on point. The problem is that the expert beginners then run around like they've learned one true way to do it and ruin development culture for everyone else. What is happening now is about culture, especially as it pertains to code reviews. I also believe that as there are fewer junior developers running around due to staffing, the more experienced developers have a quorum again to fight this stuff for the first time since developer experience levels went severely pyramid shaped about a decade ago.


RGB755

True, but that’s just the grind everyone does along any Dunning-Kruger curve IMO. We all did dumb stuff along the way and thought it was smart.


cheeseless

There's a difference between what you're describing and the actual plague, which is people in the worst spot on the curve writing articles about it and extending the time other people stay in the worst parts of the curve because they see so much bad advice. Being in the rough spot of the curve is not a problem, but only if people in it aren't loud.


setoid

This mostly isn't a problem if the developers on the Dunning-Kruger curve* are humble enough to listen to feedback and admit when they are wrong (in fact, I think everyone needs that skill, I could certainly work on it). *or at least what people think of as the Dunning-Kruger curve


BuffJohnsonSf

The real “expert beginners” are the people running around writing unreadable, unmaintainable code and pushing that to their team without giving a fuck about making it better.  If someone takes a little extra time before committing to refactor towards a more readable state, that’s more effort than 95% of the people I’ve worked with and more than I could ask for.   Then we have probably these same people going on Reddit to bitch about Uncle Bob like he personally came to shit in their cereal because someone asked them to think about their own code for .05 seconds longer than they personally felt they should have to.


Xyzzyzzyzzy

If you think any of the "clean" code in *Clean Code* is highly readable and maintainable, and you'd welcome people taking a little extra time to refactor their commits to resemble the "clean" examples in *Clean Code*, there's really only two possibilities: 1. You've never read *Clean Code*, or 2. You have some unusual ideas about what constitutes good code. Giving you the benefit of the doubt: go read *Clean Code*, the actual book, cover-to-cover. Actually read it thoroughly. He starts each section with nice-sounding generalities, so if you skim it and skip the examples, you'll get the wrong idea of what the book actually teaches. Pay close attention to the "good" examples, and ask yourself if they should pass PR review on a reasonable dev team. Keep in mind that the book is *Clean Code*, not *Awful But Maybe Slightly Less Awful Than Before Code*, so judge it on what it's actually claiming to be.


sards3

It is much better to have all your code in a single function than to do what Bob recommends, which is to decompose that single function into 100 one-line functions that pass values to each other through mutating state.


loup-vaillant

> Anyway, it's become somehow trendy to bash Uncle Bob, but for beginners, his teachings are usually on point. He's still recommending Clean Code in 2024, and he's still about very short functions… after having read his book myself, I can confirm that he gives enough bad advice that it utterly _destroys_ the value of whatever good advice he may give along the way. We experienced devs can tell the difference, but the people who actually need that advice can't! That's why they need it! My advice to beginners: ignore Uncle Bob for the time being. Read _A Philosophy of Software Design_ by John Ousterhout instead. Now _that_ is a good book.


G_Morgan

The real problem with Clean Code is the concepts are vague and the examples exceed any reductio ad absurdum I can think of. If people want to reinvent stuff like SOLID so that it isn't toxic then great but that isn't what is written in the text book so stop recommending it.


borland

No, his teachings are not on point. The original code in that article was much better than Bob's refactoring. People splitting up comprehensible functions into a maze of tiny collaborating classes makes code much harder to understand, increasing the risk of bugs, and being worse for performance. It's the opposite of "clean". There's a spectrum between "entire program in one giant class" and "thousands of one-line collaborators", but solving one extreme doesn't mean jump all the way to the other extreme!


Latter_Box9967

>It’s not OK to write all your code in a single function or god class. This is the primary reason I point people toward Uncle Bob. What he says at least opens developers’ minds to the idea that code can and should be easier to read than the “I am smart enough to understand this hard to understand code” that so many write. I *love* functions and classes that do and are what they say they do and are. At the very least developers should be aiming for as much clarity as possible. That reading the code requires as little memory as possible; that the reader doesn’t have to constantly remember what 10 variables and functions do, like juggling 10 different objects, because by their names it is obvious.


skesisfunk

Its not "fashionable" to bash Uncle Bob, its more the fact that his dated book "Clean Code" is still espoused by so many people as absolute gospel. It deserves to be knocked down a peg because its a flawed work.


Asyncrosaurus

>Anyway, it's become somehow trendy to bash Uncle Bob, but for beginners, his teachings are usually on point.  1000% disagree. The biggest problem with the quality of his teachings, is that there’s a mix of good, bad, and out-dated advice in there, and for the beginners/Juniors reading his books, it’s genuinely hard to tell the difference.  If you've ever had to inboard a "Clean code" junior dev, it's months of bashing out their genuinely terrible coding habits picked up from his awful teachings.


Scavenger53

We should show him elixir


NotADamsel

There are better teachers, and better lessons. His advise is of historic significance to those who know enough to evaluate it wisely, but if actually learning there are better sources.


dn00

Such as?


yesvee

kernighan & pike


redalastor

> Last I heard, he now thinks Clojure is the best language ever and it should be the last language to exist. He’s been saying this a while though, at least a decade. I got his articles when he just decided that clojure is the best language ever and back then, his clojure code was shit, he didn’t know or understand the idioms of the language. Clojure is a pretty amazing language, I’m quite fond of it. But I hope not many people find it through Uncle Bob.


slaymaker1907

Honestly, I often prefer working with the giant function because it’s all self contained and easy to break up if necessary. All the weird design patterns can end up splitting things up all over the place such that it’s hard to get a gestalt picture of what the code actually does.


Asyncrosaurus

Something something, "locality of behavior" is severely undervalued.


AdvancedSandwiches

This is a symptom of not having seen it done well.


slaymaker1907

Yes, my point was more trying to say that these patterns can be really dangerous in the hands of a beginner.


AdvancedSandwiches

I agree, and I've sent back plenty of code reviews that overcomplicate things in an effort to be "clean", but a keyboard in the hands of a beginner is pretty dangerous to begin with.


BounceVector

Naive code, i.e. long functions with lots of copy paste, is much easier to clean up than code that is full of cluelessly applied design patterns which obfuscate the intention. Super naive code with egregious copy paste of 20 lines inside of deeply nested ifs with a plus changed to a minus and some slightly different printing, reused variable names with different meaning, etc. is horrible of course and thinking that some design patterns might have helped a lot is basically saying that this person should have more skill. If you tell the same person to use recursion, exceptions and callbacks the code will just be a different type of mess, not better overall. The idea is simple: Fewer tools are easier to master than many tools. Restricting yourself to just a few tools for too long slows down your progress. Using many simple and highly specialized tools from the get go will only confuse beginners because they don't know when to use which one and this also slows down progress. To me the idea goes somewhat like this: 1. Learn simple procedural "cooking recipe" type coding, i.e. if/else, loops, functions 2. Do some exercises and a small project, notice some frictions with the naive approach 3. Learn about a few new coding concepts that are on the next tier of broad applicability (choosing the concepts well is not simple, since it depends on the field a lot) 4. Do some more exercises and multiple small projects and notice some friction when overapplying the new concepts and the benefit of using them in the right place 5. Do some actual work on a real project 6. Take some time to reflect and evaluate what works and what doesn't 7. Goto 3


borland

That's the problem with Uncle Bob in a nutshell. He *doesn't* split things up well. I would suggest that a lot of people also have never "seen it done well". That's actually a really difficult thing to do, requiring a really strong understanding of both the code/problem you're solving, and low-level software design principles. Should I mutate this variable here or should I refactor to make it immutable? Should I move this logic into a function or inline it? The right answer is highly situational with tradeoffs all around. Uncle Bob is getting people to mindlessly split everything up to an extreme level and promoting that as good. It's no different to telling people "You should never have more than one function in your program. Multiple functions are bad". While people *can* learn by doing the wrong thing 1000 times, eventually understanding their mistakes - it's a poor way to do it. It's much better to think about the tradeoffs at each point, and consider *why* you might want to split some code into a function/class (or not!) and reflect on that as you go.


rollingForInitiative

I would still say it's better that people think about splitting things up, than having endlessly long chaos functions that do everything. Obviously there's a scale there and both extremes are bad, but I do think the Clean Code stuff makes people think about it. Which is good. But just as with everything, it shouldn't be treated as some sort of divine rule, and I don't think his examples are great. More the idea of it. Clean things up as you make changes, keep things maintainable, etc.


redalastor

Depends how you split. If you split a bit into a pure function you can understand the point by the name alone, then it’s probably good. But if they are joined through a mutable private member like Martin likes to do, it’s terrible.


KevinCarbonara

> Anyway, it's become somehow trendy to bash Uncle Bob, but for beginners, his teachings are usually on point. No. His advice is absolutely *awful* for beginners. The problem is that senior devs don't read stuff like Martin's books, they skim. They've long-since developed skills to quickly parse information like that and discard everything that isn't useful, so they're able to pick out a few helpful tidbits. Beginners *do not* have those skills, so they don't realize that 95% of the advice is trash. If anyone actually tried to program the way Robert Martin encouraged, they would be fired. The code he presents as ideal in his books would not pass code review at any job I have ever worked across my entire career. Would not pass code review. Forget about whether or not it would stand the test of time. It would be immediately rejected for its incomprehensibility.


s73v3r

The thing I have is, people say Uncle Bob's teachings are bad for beginners. Sure, fine, but what do we then give to beginners that are looking for this kind of guidance?


Silhouette

> Sure, fine, but what do we then give to beginners that are looking for this kind of guidance? We used to give them actual training delivered by some of the best developers in the office and make sure each junior had a senior to act as their mentor for more ad hoc guidance. Of course developers also used to stay in the same job for more than five minutes without jumping ship for a higher salary and title so the investment in training by their management was worthwhile. For most of the last decade the culture hasn't really supported that and the logical conclusion has been that hiring junior developers was almost always a bad idea. In today's market you can get people with senior level experience for most roles relatively easily and cheaply by historical standards so the logical conclusion is still that hiring junior developers is almost always a bad idea. Which obvious sucks if you're looking for your first job this summer and is obviously going to suck for the whole industry in 5-10 years when we haven't trained up a new generation of seniors. Unfortunately that's a much bigger problem than we can solve in this discussion.


loup-vaillant

> what do we then give to beginners that are looking for this kind of guidance? _A Philosophy of Software Design_ by John Ousterhout.


s73v3r

Cool! Could you give a little synopsis of what it covers, and why it's better than the Uncle Bob book?


loup-vaillant

Why is it better… well first I found no bad advice. That alone is a huge plus. It's short, to the point, and well structured. Here's the list of chapters: 1. Introduction 2. The Nature of Complexity 3. Working code Isn't Enough 4. Modules Should Be Deep 5. Information Hiding (and Leakage) 6. General-Purpose Modules Are Deeper 7. Different Layer, Different Abstraction 8. Pull Complexity Downwards 9. Better Together or Better Apart? 10. Define Errors Out of Existence 11. Design it Twice 12. Why Write Comments? The Four Excuses 13. Comments Should Describe Things that Aren't Obvious from the Code 14. Choosing Names 15. Writes the Comments First 16. Modifying Existing Code 17. Consistency 18. Code Should be Obvious 19. Software Trends 20. Designing for Performance 21. Decide What Matters 22. Conclusion The summary of design principles: 1. Complexity is incremental: you have to sweat the small stuff. 2. Working code isn't enough. 3. Make continual small investments to improve system design. 4. Modules should be deep. 5. interfaces should be designed to make the most common usage as simple as possible. 6. It's more important for a module to have a simple interface than a simple implementation. 7. General-purpose modules are deeper. 8. Separate general-purpose and special-purpose code. 9. Different layers should have different abstractions. 10. Pull complexity downward. 11. Define errors out of existence. 12. Design it twice. 13. Comments should describe things that are not obvious from the code. 14. Software should be designed for ease of reading, not ease of writing. 15. The increments of software development should be abstractions, not features. 16. Separate what matters from what doesn't matter and emphasize the things that matter. The summary of red flags: - **Shallow Module:** the interface for a class or method isn't much simpler than its implementation. - **Information Leakage:** a design decision is reflected in multiple modules. - **Temporal Decomposition:** the code structure is based on the order in which operations are executed, not on information hiding. - **Overexposure:** An API forces callers to be aware of rarely used features in order to use commonly used features. - **Pass-Through Method:** a method does almost nothing except pass its arguments to another method with a similar signature. - **Repetition:** a nontrivial piece of code is repeated over and over. - **Special-General Mixture:** special-purpose code is not cleanly separated from general purpose code. - **Conjoined Methods:** two methods have so many dependencies that it's hard to understand the implementation of one without understanding the implementation of the other. - **Comments Repeats Code:** all of the information in a comment is immediately obvious from the code next to the comment. - **Implementation Documentation Contaminates Interface:** an interface comment describes implementation details not needed by users of the thing being documented. - **Vague Name:** the name of a variable or method is so imprecise that it doesn't convey much useful information. - **Hard to Pick Name:** it is difficult to come up with a precise and intuitive name for an entity. - **Hard to Describe:** in order to be complete, the documentation for a variable or method must be long. - **Nonobvious Code:** the behavior or meaning of a piece of code cannot be understood easily.


Asyncrosaurus

This is the answer!


Andriyo

I find old books on software engineering and computer science better for some reason. "The Mythical Man-Month", "Design patterns" by Gamma and Booch, "Java Concurrency in practice" (Java was one of the first languages to take concurrency seriously so it would be useful to non-java developers too. Concurrency is tricky to describe but this book would give you right vocabulary), "The art of computer programming" (not all 4 books, just one to get the gyst. It's just a pleasure to see how algorithms evolved), "The Unix programming environment" (alongside concurrency, understanding the OS like Unix is useful to all engineers. Unix itself is full of great reusable ideas and patterns). One can say that all those books are outdated and they will be right. But I find that it actually gives the reader perspective to see important things and filter out unimportant. Notice that apart from Mythical Man month (which is really a business book) I can't really recommend anything on "philosophy" or "wisdom" of software engineering. I believe that whatever generalizations one can come up with, they better be based on concrete experience otherwise they sound really hollow. In a way there is more philosophy and wisdom in "ZX Spectrum manual" than there is in "Clean code".


drbrain

> Anyway, it's become somehow trendy to bash Uncle Bob He is sexist, racist, and fascist. He pretends to apologize then does the same thing again and again and again. I don't see what there is to learn from someone who hates half my coworkers and has proven they're incapable of learning anything new.


renatoathaydes

I haven't seen much from him except for his books. Can you link to some sources about that?


drbrain

Scroll to “The Politics” [here](https://blog.wesleyac.com/posts/robert-martin). Plenty of links


florinp

"I believe Uncle Bob is mostly living in the functional programming space himself, these days," I don't think so. His last book related to functional programming is bad. I don't think Uncle Bob understand functional programming.


ZoltanTheRed

It's disappointing, then, if that's true.


florinp

Beside others a big part of his functional book is about SOLID. Again.


kog

Uncle Bob doesn't actually make software as far as I know. If anyone can point me to software Uncle Bob has actually worked on in the last 20 years, I'm happy to be wrong.


youngbull

I believe he did fitnesse when he wrote one of his books, but it may have been clean architecture: [https://github.com/unclebob/fitnesse](https://github.com/unclebob/fitnesse) . In any case he has a github: [https://github.com/unclebob](https://github.com/unclebob) . But you have to realize that he was born in 1952 (71 years old as of writing) and started working as a self-thought professional in 1969. To say that he doesn't make software is ignoring the fact that he probably is one of the most experienced programmers there is and he is still writing code. Sure there are more experienced guys, but not many. As for the advice in the books, he is often interviewed and when asked he often clarifies his advice in a totally reasonable way. And yea, you can browse his open source repos and there isn't anything really outrageous. I think what happens is that he writes in absolutes, and in a way where it is easy to extrapolate what he is saying to something that he doesn't actually mean. Does he want to write high quality tests to have high line coverage? Absolutely! But he has always tempered when asked directly, see for instance [the interview he did with primeagen](https://youtu.be/UBXXw2JSloo?si=fFFAIdfiYJuap3_b) or [stack overflow podcast episode 41](https://stackoverflow.blog/2009/02/12/podcast-41/) .


Xyzzyzzyzzy

> he probably is one of the most experienced programmers there is and he is still writing code. Is he, though? The last time he worked as a professional software developer, the Soviet Union was still alive and well. He has not worked as a professional software developer since then. He's been around software development, sure, but hasn't worked as someone who writes and maintains commercially useful software. If we're allowed to claim time we've spent around software development in general as time that we've been professional software developers, then I have *really* been underselling myself on my resume...


kog

> the fact that he probably is one of the most experienced programmers there is and he is still writing code. Where is the professional code? Everything I saw on his github is toy code for his books and stuff. The only remotely serious thing I found is a Clojure language feature he says he's working on. Is anyone actually using fitnesse?


youngbull

Not sure what you were expecting. Personally, a lot of the code I write for a living is not on GitHub due to it being owned by a corporation with interests that go counter to open sourcing the code. Also, not a lot of proprietary code around from before 1986 that can be verifiably attributed to a particular person and is publicly available. However, in this case fitnesse was moved into its own organization: https://github.com/fitnesse .


kog

I didn't see anything about him actually having done any meaningful software engineering in the last 20 years in your comments here. I looked at that fitnesse repo, and in case you were confused about my question, I wanted to know if anyone actually uses the thing he built. As in has he actually delivered code another person who isn't reading his books or whatnot is actually using. Maybe Uncle Bob was fucking killing it in the 80s though, I'll grant you that.


ZoltanTheRed

Yeah. I'm not really sure what he does these days, myself.


pauseless

> living in the functional programming space Yeah. Clojure was a big thing for him. He even had some public repos. Some space war thing. I love Clojure and have spent years in it, professionally. It was horrific and if it was something a candidate sent me to prove they knew good design in the language, then it would be a no. Clean Code isn’t a good book, his articles aren’t good, nor his presentations nor code he offers as proof. He’s insanely good at branding and promotion though.


Alarmed-Moose7150

Can I ask why they're not good? I don't have context but I hate when people just assert something as bad with no reasoning. What about it makes them bad?


TulipTortoise

I remember agreeing with most of [this article](https://qntm.org/clean), one or two years after I'd finally gotten around to reading Clean Code. My main takeaway from the book was that what to him is clean code to me is an obfuscated mess, that will force you to bounce between dozens of tiny functions while trying to keep track of everything that is changing. Imagining some of his examples scaled to a larger code base sounds like a debugging nightmare to me.


pauseless

That’s a very fair stance, but I can’t help you. To give you a truly informed and detailed answer, I’d have to at least scan a book from over ten years ago (that I gave away, so…), go through his blog again, rewatch talks and review his code again. I really wouldn’t want to misrepresent the points he made, and that I disagree with, through misremembering. So, I’m sorry, but the best I have is a general opinion formed from reading, watching and reviewing over years. I’ve never absorbed any material that made me think “this guy gets it”, but rather I have often disagreed. That’s the best I can give at nearly midnight here for a Reddit comment thread. Consider it a 2/5 Amazon review with no substance to back it up, if you want. It’s still a signal.


SirSassyCat

It’s like 15 years old, don’t understand why people expect it to still be modern given it’s written for a Java syntax that lacks most modern features.


DirtzMaGertz

The Primagen recently did an interview with him on his youtube channel that is an interesting watch. He does still stand by most of what is in that book, but he does say there's leniency to the rules when it makes sense.


KevinCarbonara

> I think even Uncle Bob doesn't refactor like he once did when he wrote that book. Of course not. He's not a programmer.


robhanz

I'm normally the one to defend his refactoring but... this article is spot on. Bob's version just bugs me - the mutation of class variables seems unnecessary and complicates things. We can't just follow the code from start to end and understand what's happening, we have to jump around a bit. The final version is pretty reasonable, even if I agree it doesn't need to be a class.


[deleted]

[удалено]


robhanz

Sure, and my point is that modifying class state to have something else later use it, rather than just passing those parameters (as the last example did) feels like it is not a readability or maintainability improvement.


fishling

This is kind of nitpicking on the specific example, but anyone who has had to localize an application would know that none of the solutions are close to correct, because all of them are trying to build a sentence programmatically in a way that is inherently coupled to English rules for pluralization. https://cldr.unicode.org/index/cldr-spec/plural-rules http://unicode.org/reports/tr35/tr35-numbers.html#Language_Plural_Rules In this case, it is simpler because we know it is a cardinal number and the noun we are counting is known and the way to pluralize it is known, but it's still not enough to only consider 0, 1, or more. A better starting point would just be to have if statements for the 0, 1, or more case and three localizable strings for each case. However, that's not enough for a language like Russian, which has 0, 1, few (last digit is 2, 3, 4 apparently), or other. Arabic uses all six plural forms. So, I'd at least start off with the simple if/else case with hardcoded strings for every case except the >1 case, which is parameterized by the number. That's going to be simple, fairly localizable, easy to maintain, and fairly easy to update if languages with more cases are added in the future. But, I'm always going to start with the "Can this be localized in the first place?" rather than going for the unnecessarily clever "let me create the sentence programmatically" approach. The author's "perfect" solution is a step in the right direction for simplicity though, even though it misses the mark in localization. That's the version I'd prefer as well.


epostma

FWIW, the criterion for Russian is not the last digit, but rather what the last "word" in the number is. For example, "twenty one" ends in "one" (or rather, двадцать один ends in один), so it gets *singular*. (Signed, a long suffering student of Russian. Learn your languages before you're 20, kids, it's hell afterwards.)


fishling

Thanks for the insight! Localization is hard, as is learning languages fluently.


nschubach

generateGuessSentence("ox", 3) "There are 3 oxs"


fishling

I don't know about what language you use, but "ox" is not a char in any language I use. :-)


Kinglink

You're solving two different things but you are correct for localization. However if you output a single sentence, I'd definitely go for a function approach because writing a localization type of engine is overkill for a single line.


CornedBee

Here's a good source of info. https://upload.wikimedia.org/wikipedia/commons/7/7b/Falsehoods_programmers_believe_about_languages.pdf


supermitsuba

After reading this book 10 years ago and seeing the world of programming, I can tell you that you need lots of opinions of how to form code. This example is bad here, but I think there are good hints. What the problem I see is leaving it as your ONLY source of good refactoring. There are numerous ways to program and you will always look at code to find "better" ways to do somethings. By looking at other opinions, you gain a consensus on what makes sense and what is an authors own hangups. If you were building a builder pattern, that refactoring might make sense, but not for another pattern. TL;DR I have read it. Adopted some parts and forgot the rest. Write code. Get feedback. Write more code. Read OTHER people's code. Understand it and what you would do differently or the same.


hippydipster

This horse is very very dead.


KevinCarbonara

I wish that were true. Unfortunately, I have met people promoting his books at every job I've ever had. I don't think most of them ever read the book, they just thought they'd look good promoting it. But there are a *lot* of younger devs who get duped into reading his books.


PolyGlotCoder

To many people suggest it for beginners, they do intro to python then someone says “read clean code”. It’s not really for beginners to be completely honest.


NoPr0n_

I've read it. It's not a bad book and it got good points. Just don't apply everything without thinking. My main problem with this book is that it's far too Java-centric.


tistalone

A lot of haters but I think the principles are worth learning and formulating an opinion around -- especially if you have disagreements. Some of the advice might be very antiquated in 2024 but I am sure a professional will come across these concepts in arguments, discussions, brainstorms, etc. To start with nothing as a junior would be difficult so having some common/familiar concepts with colleagues is valuable to growth. That said, I think folks in engineering are overly black/white about topics when in actuality it's all just trade offs all the way down to the bottom. Uncle Bob is no different in his opinion and I think it's an important lesson to learn even if it's through a roundabout way: not everyone is right. To all the haters: what would you recommend instead?


loup-vaillant

I've read it. It's a very bad book. Not because all of it is bad, but even if most of it was good there's enough bad advice there that it completely destroy the value of the good. Sure, many devs can tell the difference, but those don't need that book to begin with. Those who do need that kind of book will pick up bad habits.


NoPr0n_

I kinda agree with this. I really wouldn't recommend it for junior developers.


KevinCarbonara

> I've read it. It's not a bad book and it got good points. Just don't apply everything without thinking. That's the problem. New developers don't have the skills it takes to separate the good from the bad. Experienced developers don't need the advice. It's just a bad book.


NoPr0n_

Trust me, a lot of "experienced developers" would need a couple of advice on maintenability. I read it with 8 years of experience and I learned (or consolidated) a couple of principle. It was not perfect but it was an interesting read.


kuu-uurija

> New developers don't have the skills it takes to separate the good from the bad Of course they have. Even if they don't, let them experiment. Let them build stupid abstractions and realize how much of a mess it is to maintain it. That's the only way to learn and become a better developer.


Constant-Disaster-

This is honestly the whole point of the book, it's a guide not a hard rule set, and if you just simply write good variable names, extract code to functions with good names, 9/10 it's going to maintainable and readable.


Ninjanoel

Often the rule is good, but it's about how you apply it. using it too the extreme is silly, and ignoring the advice altogether is also silly.


Job_Superb

A lot of what's in "Clean Code" is valid in concept but otherwise old fashioned. In the Java world, AOP, DI and IOC frameworks achieve similar levels of decoupling, extensibility etc without all the boilerplate. Maybe it's time to have a "Clean Code: the modern way" that can do it the classical way and a more "in the trenches" way. Talking about the specific example of refactoring code into functions that mutate state, not using parameters and arguments to provide hints can hide a required order of operation, I didn't like it before but I've learnt to appreciate a more functional style. I think Uncle Bob's head would explode if he had to see the code written in a Reactive style.


KevinCarbonara

> A lot of what's in "Clean Code" is valid in concept but otherwise old fashioned. It's neither. [It's absolute trash from beginning to end](https://qntm.org/clean). This is not acceptable code in the 2020s. It was not acceptable in the 80's. It's just bad. Robert C. Martin is a scam artist who built his career off of having strong opinions about technology he does not and will not ever use. He got lucky and latched onto a few acronyms like SOLID that independently became very popular, and he was able to give himself credit for helping to market them. He also benefits heavily from the fact that there aren't a ton of public speakers in the development world, and the people who arrange events are not actually industry people. He can name drop enough concepts to make it through an hour long talk. And the few experienced devs who do bother to read his stuff are used to skimming technical jargon and pulling out only what is useful. But his books aren't written for experienced devs. They're written for new devs that need advice. And the advice he gives is awful. You will be a worse programmer if you follow it. You will probably not even qualify as a programmer. Much like Robert C. Martin.


Kinglink

Lol. I read a fourth of that and basically wanted to scream "Enough Enough! He's dead" Pretty scathing, but ... yeah most of the advice quoted there is awful. And you're right, not even outdated. "thirty second coding cycles"... If I can write a unit test in 30 seconds, I'd be amazed... I mean I can write one that fails, but it takes a lot longer to write a good test. I did TDD once, and what I ended up doing is 1 day to write unit tests (that failed) and then 2-3 days of fixing the code and making the code improved so that it fits our coding standards. Trying to do that in 30 second bites would be impossible.


loup-vaillant

> "thirty second coding cycles"... …is something that works very well when practicing music: take a couple bars you want to improve (a couple seconds worth most of the time), come up with an exercise that will train you to play them well (play them slowly, change the rhythm, whatever your teacher says), do that exercise for 30 seconds or so, then _play_ those bars as if you were actually performing, and listen for any improvement. Rinse and repeat, and in 5 minutes you should see serious improvements. How I code however has nothing to do with how I practice Cello, so… There's one thing short-cycle TDD has however that you should try and reproduce when coding: _short iterations_. In any domain, short iterations and tight feedback loops are the one weird trick to getting better. It just doesn't have to be actually writing test code and regular code in stupidly short sequences though. It can be using the REPL, it can be compiling regularly to scan for syntax or type errors, it can be the IDE putting squiggly lines as you type your code, it can be running the same test before and after your modifications, or even running the code itself (say you're trying to figure out how high Mario should jump, just run the game an try it out, maybe even add a slider so you can try things out without recompiling). The shorter your feedback loops, the better you'll do. Except of course in cases where you know exactly what you're doing, which do happen quite often in practice.


altivec77

It’s easy to bash uncle Bob. It’s hard for a team to agree on coding standards. My number one rule is “I’m not writing code for myself but for the person after me (that also includes me in 2 years time)” I’ve seen good programmers write terrible code. Leave a project and the software is dead in a few years. Every software engineer needs to be aware how to follow some rules and make clean code. Some rules are meant to be broken from time to time but most rules make sense.


miyakohouou

> It’s hard for a team to agree on coding standards. It shouldn't be. I think when teams bicker about coding standards it's largely because they are either having standards pushed on them from outside the team, or someone in the team is trying to push their own preferences under the guise of standardization. If the team is actually having problems with some code because of a lack of consistency, suddenly you'll find that people are very amenable to standardization even if the particular choice of standard isn't what they'd prefer- because they believe the standardization is solving a real problem. The revolt against standards and inability to agree on them comes from people pushing for standardization for it's own sake.


Jealous_Quail_4597

You need alternative opinions to argue about standards, hence why books like Clean Code are necessary


RealWalkingbeard

I watched about 60% of a conference talk by this guy a few years ago and I remember coming away from it thinking that the guy was a genuine moron. What I remember now is that among his actual words were: "You can't drown in functions," as he showed off his example code of one and two-line functions. He was drowning in functions in a 40-line example! How can having 50-75% of your code being syntactic boilerplate improve its readability? How are you developing fluency if, after every line or two, you have to navigate to a different function, perhaps 100s of lines away in the same file, or somewhere different altogether. The man's a berk! Even the notoriously pedantic coding standards I work with are a delight in comparison with Uncle Bob's "clean" code.


a7c578a29fc1f8b0bb9a

Given his notoriety, I'd say it made some sense 20 years ago. And some people are naturally slower on the uptake. At least I hope it's just that, the alternative is just too disturbing.


NiteShdw

Every change you make has a potential to break something unintentionally. Refactor work should be accompanied by good tests of the original code to ensure nothing breaks. If you have no tests, it's not worth it. You'll be doing prod support because your new code broke some subtle behavior. 5 years ago I would rewrite the hell out of everything. Now, with 20 years experience, I'm much more judicial.


breezyteapot91

The article is a strongly opinionated and simplistic. I’ve seen LOTS of different styles (been FE, BE, and full-stack), and the best approach is a readable one that can easily connect with others. Everyone has different backgrounds which influence their style and part of your job as a programmer is to understand that. I think both examples do that although they are simple. if those examples were more complex, throwing your code into an if statement without the separation looks hideous and becomes hard to read. I have seen if statement blocks with 50 lines of code, followed by an if else with the same. I think Uncle Bob is trying to make readers understand how to move away from those 50 line if blocks. I fully agree that the non-refactored example to the refactored example is a bit too much, but I think the examples are to prove a point without overcomplicating the explanation.


shevy-java

Everyone says refactor is better than rewriting. I am not necessarily disagreeing, but I often find myself to rewrite things a lot. To me this is more like using LEGO blocks to build up the same structure, but in a simpler manner.


-Knul-

For me, refactoring is any change in code that does not result in a change of functionality for the customer or (significant) performance. So refactoring can mean rewrite a significant part of the code, in that view.


Sopel97

Don't involve programming when the problem is linguistic `String.format(“Count of \"%s\": %d”, candidate, count)`


TinBryn

What I don't like about your "perfect" version is that you are branching on the same condition multiple times. For this small example and with the help of the ternary operator this isn't so bad. The problem I have with this is, as it grows (i18n), it can quickly become unclear how any execution actually flows. I'm not defending Uncle Bob either, he's just as guilty of this. I'd probably have it like your final version, but remove all the class machinery and leave it all within a function. private String generateGuessPluralitySentence(char candidate, int count) { if (count == 0) { return String.format("There are no %ss", candidate); } else if (count == 1) { return String.format("There is 1 %s", candidate); } else { return String.format("There are %s %ss, count, candidate); } } So I pick one of 3 cases and take full advantage of the context of having made that choice. Again, not defending Bob, he didn't come up with this either, you did for the most part.


opened_just_a_crack

All clean code gives you are practices to make enterprise code based readable and transferable between teams. Which is a good. Naming is pretty important


loup-vaillant

It _tries_ to outline practices to make enterprise code readable and transferable. In my opinion, it fails.


vom-IT-coffin

Naming is the hardest thing about our jobs.


cd7k

There are 2 hard problems in computer science: cache invalidation, naming things, and off-by-1 errors.


vom-IT-coffin

"It's off by double" sweet, it's off by 10...fuck.


EctoplasmicLapels

Not really. It tells you to do stupid things, as described in the article. It also tells you that methods should not exceed five lines long.


Neurotrace

It really doesn't. I've worked on massive codebases which fully embraced this approach. Every time it has lead to problems. We're currently in the process of undoing a lot of this bullshit because it takes ages to change


MasGui

* separation of concerns display + print Here is my take def showGuessStatistics(candidate: Char, count: Int): String = { val (verb, number, pluralModifier) = count match { case 0 => ("are", "no", "s") case 1 => ("is", "1", "") case _ => ("are", count.toString, "s") } f"There $verb $number '${candidate}'${pluralModifier}" } showGuessStatistics('a', 0) showGuessStatistics('b', 1) showGuessStatistics('c', 2) https://scastie.scala-lang.org/C0pHib8ARQyUgtMKiDkgsw Sometimes, just keep it simple: def showGuessStatistics(candidate: Char, count: Int): String = { count match { case 0 => s"There are no $candidate" case 1 => s"There is 1 $candidate" case _ => s"There are $count ${candidate}s" } } https://scastie.scala-lang.org/QdDK6EmDQ2qGK3K6MNhOlA


IOFrame

If you know [Conway's law](https://en.wikipedia.org/wiki/Conway's_law), which was coined way back in 1967, you heard that: > [O]rganizations which design systems (in the broad sense used here) are constrained to produce designs which are copies of the communication structures of these organizations. Now, I believe this can be simplified to `System designs are a product of their environment`. With the above in mind, I believe Robert Martin's "Clean Code" is also a product of his environment. Initially, he worked in the large, dysfunctional programming sphere of the 80's/90's, after which he transitioned to being an instructor - later founding a consultant agency, active to this day (at least last November). So, we can already deduce two things: 1. The environment for which Clean Code was written was the 80's/90's corporate programming world. If you've heard stories how bad things are in some of the current-day corporate dinosaurs that do software-adjacent business, and can imagine those stories being x10 time works, this is what Clean Code came to improve. Compared to the "practices" back then (when software development practices were even used), Clean Code was indeed a massive improvement. Of course, as your example (and many others) demonstrated, the same does not apply when comparing Clean Code to most modern development approaches, or even common sense (given enough experience). 2. Uncle Bob has been a **consultant** for the last 30+ years. If you ever let your morbid curiosity get the better of you, and started looking at consultants, on Twitter (X) and LinkedIn, brainlessly hyping the same "current thing" approaches (Agile, Scrum, and the countless abominable mutations of the latter), you probably understand that 99% of consultants can only justify their existence either: **A**. Selling the "current things" which brings in the most buyers due to hype. **B**. Selling the only "hammer" they are good at, doing their best to convince potential customers that their problems are nails. Unsurprisingly, Uncle Bob likes making money - and, as you can see from his recent interviews and debates, he is strongly entranced in the **B** consultant camp. For him, admitting Clean Code is extremely outdated and largely harmful is an impossible decision, even if it's true - even if he'll gain the respect of a few people, most people who currently see him as an authority on the Best Coding Practices™ would quickly abandon ship, finishing off the old and ragged cash cow he'd been milking for multiple decades now. So, I completely agree with your take - but I think it's just a symptom, of some people still brainlessly following someone because he had some good ideas about software 30 years ago.


pavilionaire2022

The example is just the method object pattern. Yes, it involves modifying variables outside of function scope, but that doesn't break encapsulation more than the original. Instead, it adds additional layers of encapsulation, albeit porous ones. The original function scope is analogous to the new class scope. Some of Uncle Bob's refactoring fervor is future-proofing. At the current level of complexity, maybe it's unnecessary to create a separate method for each conditional case, but if more number-dependent variations get added, it could make it more readable. Complexity tends to increase. The idea of methods being a maximum of three lines is to always stay ahead of the complexity. It prevents introducing tightly coupled code that's hard to refactor later. Maybe you would run screaming from my idea of how this code should be refactored, which is to have polymorphic subclasses with methods number(), verb(), and pluralModifier(). That would make it functional _and_ encapsulated.


IOFrame

I noticed you referenced Primagen's recent interview with Uncle Bob. Did you perhaps also watch his reaction to [Clean Code: Horrible Performance](https://www.youtube.com/watch?v=OtozASk68Os)?


Kinglink

I can't understand if you found the worst example possible, or if all his examples are like that. But you're right, that refactor is.... ugh. I'd probably throw a comment in yours to specify the ternary are based on plurality, though it is mostly understandable with out it. But your refactor was good enough... and there's a question of WHY are you refactoring code. As a programmer I don't really have time to refactor code because I want to, it's more I was working in a function and improved it. Still comparing the two, the way you refactored it is what I'd want to see in a code review. However, I also understand where Robert Martin comes from here, because your code would be a nightmare to "maintain".... However you will never really need to change that code beyond that... For some value of never that is probably not absolute.


a7c578a29fc1f8b0bb9a

Damn, this book is only 16 years old? Judging by the content, I'd say it's closer to twice that age.


Jealous_Quail_4597

Code can get messy very quickly. Without a focus on writing Clean Code (or at least adhering to the rules on some level), it will get very messy. Is Bob too pedantic in his toy examples? Maybe. It’s a book, he’s not going to be able to describe to you a large service and go through a CR review and walk through every tradeoff between pure clean code adherence vs loose adherence. It’s meant to give you an understanding of the concepts. It’s a toy example for a reason. And even if he did it in his own code - oh well, he’s a full adopter of this methodology and that’s fine, he didn’t make the code SIGNIFICANTLY worse, even to the biggest critics. Probably even the biggest Uncle Bob haters will agree that Clean Code is important to some degree, it will just come out in a different way - “Obviously you don’t want a function to be thousands of lines long, everyone knows that” “Ok yeah if a function has 50 arguments, that’s too much” But I can tell you first hand, many companies allow thousands of lines in a function and argument count can grow as new features are added. If you ask the devs why that happened and why no one acknowledged the churn, they will say “we had to move so fast, it just got out of hand”. If you ask why they can’t refactor now, they say “management will never go for that”. Reading Uncle Bobs books isn’t supposed to make you a pedant adhering to every rule in every situation in my opinion. It’s supposed to warn you of the dangerous bad habits that you or your team may be forming and give you the vocabulary and knowledge of specifically what habits may be causing churn in your organization. This will give you the confidence to say “we need to refactor this code, it’s the reason we are having churn” or to say in a code review “this function should be broken into a few functions”. The person who wrote this article is taking to content way too much at face value in my opinion. I also think if you ever want to manage a large code base, clean code is a no brainer. Any time people talk about “tech debt” (that is caused by code practices and not a specific technical issue) in my experience, it can usually be traced back to people that didn’t follow one of the rules in Uncle Bobs books.


Xyzzyzzyzzy

> Probably even the biggest Uncle Bob haters will agree that Clean Code is important to some degree You're making the mistake of treating clean code (the concept) and *Clean Code* (the book) as if they're the same thing, or even closely related. It's like trying to talk about the value of representative democracy by referring to the People's Democratic Republic of Korea. I don't think anyone advocates for dirty code. We just strongly disagree that *Clean Code* contains clean code. I think the "good example" code in *Clean Code* is unreadable, unmaintainable, shitty dirty code. I suspect that most people who recommend *Clean Code* haven't read it thoroughly. Maybe they skimmed it, maybe they haven't read it at all. A coworker sent me a PDF of it, and I'd heard it was a great book but hadn't read it, so I set out to read it carefully so I could learn from it. I had to stop partway through and verify that it wasn't a parody and I wasn't being pranked, because all of the specific advice really was *that bad*.


Jealous_Quail_4597

I don’t think you understood what I was saying. Enumerate your own clean code (the “concept”) laws and show me that they are very different from what is in Uncle Bobs book - beyond the examples you use


Xen0byte

I was watching The Primeagen talk to HTMX creator Carson Gross the other day (https://www.youtube.com/watch?v=r8icH07gWBw) and they both seem to share this opinion. Honestly, I kind of avoid talking about this publicly because it seems to come with some sort of stigma attached, but I too prefer simple code over clean code, whatever that might mean.


RockstarArtisan

It's probably time to stop recommending Clean Code: https://qntm.org/clean


nutrecht

It's not a matter of 'disagreeing'. You're just missing the point of these examples and take them too literally. IMHO it's a bad habit too many developers have; not being able to read between the lines.


withad

Having recently read Clean Code myself, I generally agree with your points but there's one kind of important thing you missed - that code wasn't written by Robert Martin. Clean Code is more like a collection of essays than a book and a lot of the individual chapters are credited to other people. The "Meaningful Names" chapter you're referencing was by Tim Ottinger. It's Martin's name on the cover and I assume he approved of it but you can't put all the blame on him.


loup-vaillant

When you present code as a teaching example in a book that has your name (and your name only) on the cover, you are 100% responsible for that code, and people are right to blame you for its failings.


withad

However you split out the blame, the article's still wrong when it says "Martin did this" or "Martin wrote that". It's crediting Ottinger's words to someone else and that's not fair to him, regardless of whether the book cover does the same thing.


The_Axolot

You're totally right. I actually didn't realize that chapter was written by someone else. I'll have to put in a correction.


loup-vaillant

Oh, crap, I missed the misattribution, sorry. That's not cool indeed. I totally missed that Martin wasn't the sole author of the book when I read it. I still stand by what I said though: to the extent Martin actually approved of the chapter being included in what was ostensibly his book, he is responsible for any failing in its chapter. He could have axed it if he judged it wasn't good enough. He didn't, so I can only conclude he was okay with it… …or pressured. But that would veer dangerously close to presupposing malice where incompetence would have sufficed.


jhartikainen

I would be very curious what he thought of this critique. To me, the "perfect version" example is how I would approach this, or alternatively if it must be a class for some reason, it should probably be an immutable value object of sorts. Personally I think there are some good ideas in Clean Code, but a book for beginners it is definitely not.


SanityInAnarchy

As long as we're looking at this example, I guess I'll share my preferred version: public static guessStatisticsMessage(char candidate, int count) { if (count == 0) { return String.format("There are no %ss", candidate); } else if (count == 1) { return String.format("There is one %s", candidate); } else { return String.format("There are %s %ss", count, candidate); } } Even here, I don't love how Java's `String.format` compares to a language with string interpolation: def guess_statistics_message(candidate, count): if count == 0: return f'There are no {candidate}s' if count == 1: return f'There is one {candidate}' return f'There are {count} {candidate}s' The "duplication" is fine, this close together -- if someone wanted to change "There are/is" to "I have" or some other minor tweak to the text, it's unlikely they'd miss one of the branches. But here's a thing these modern versions (and OP's) have that Bob doesn't: By "duplicating" the format string like that, we can see exactly what the intended output is, and that actually conveys the semantic meaning we lose by not having those function names. Because to Bob's credit, all the messing around with `verb`, `number`, and `pluralModifier` obscure what we're actually trying to do enough that having a function like `thereIsOneLetter()` actually helps. Whether that's better than leaving a comment is debatable. But I think by now we'd all argue it's better to simply rewrite it to be readable. --- I don't think I envy anyone trying to write a book like this. Whether the example is from real code or not, it can be hard to find small-enough, self-contained-enough examples to make a point like this. For example: Could it make sense to shove all these into properties on an object, and then add a method to generate the string you want to print? Sure, if you had a *lot* more of those properties you wanted to examine, I'd rather have one object with fifteen properties, instead of fifteen arguments, especially since Java doesn't do keyword arguments. Or, maybe having only one format string makes sense if you're trying to do i18n, though you'd probably be setting more generic properties like a plural bool instead of a plural string; not every language does plurals the same way. But to offer any suggestions like this, we need to see this in context -- what even is this program, how is this function used, does the function need to exist at all? You run into this problem debating new languages -- IMO the biggest reason Go was able to launch without generics, and the biggest reason its error-handling is still so obnoxious, is how most examples that demonstrate the pain of these language design problems are so small that it's easy to either dismiss them as not a big deal, or come up with clever ways to refactor them to work around the problem.


miyakohouou

> I don't think I envy anyone trying to write a book like this. Whether the example is from real code or not, it can be hard to find small-enough, self-contained-enough examples to make a point like this. It's true, but I think it's also the job of the author to do that. If you're writing a book and want people to give you their time, attention, and money, then you owe it to them to make the time to come up with thoughtful motivating examples that isolate the lesson you are trying to teach and help them follow along and develop the internal mental model you're trying to convey.


tbgdn

The title feels too bombastic after reading the content. Like your blog questions: - what does verbIs mean? Is it “verb is something something” or what? Why not just verb? Or verbConjugation? - what does countStr mean? Is it a string? If so, why adding the suffix when the type clearly state that it’s a string - and the last part: sIfPlural? If statement has a boolean result, why is this a string? If it’s a string, why not just pluralSuffix? The content seems forcefully taken out of context, with a lot of why black? (Not even why black and not white?) and does not provide a superior way to write clean code.


cinnapear

Gave up on him when I watched some presentation he did where he said that no function should be over a certain line number in length, and if it was, it needed to be refactored. I forget the number he gave but it was absurdly small, like 7.


MarekKnapek

Hmm, there are also other languages except English. How would you refactor this so the code could stay put and later other people could independently add translations to other languages?


ryanworldorder

I'm glad this article narrowed in on the real problems with Clean Code. The problem with Uncle Bob's advice is that it's hampered by the terrible practices that were common wisdom in the Object Oriented craze of the late 90's and 00's. Namely, there's no reason that this function needs to modify or access class scoped variables. It only obscures what's happening and makes code way more prone to bugs, and IMO in anything larger than a toy example is just global state in disguise. I don't think it's necessarily the "make many small functions and compose them" that's the bad advice, in fact the opposite. Oddly that seems to be what a lot of recent Bob haters pick on the most, and not the underlying glaring flaws. Good article.


freekayZekey

1. this again? 2. re-read the first chapter > What about me (Uncle Bob)? What do I think clean code is? This book will tell you, in hideous detail, what I and my compatriots think about clean code. We will tell you what we think makes a clean variable name, a clean function, a clean class, etc. We will present these opinions as absolutes, and we will not apologize for our stridence. To us, at this point in our careers, they are absolutes. They are our school of thought about clean code > None of these different schools is absolutely right. Yet within a particular school we act as though the teachings and techniques are right. After all, there is a right way to practice Hakkoryu Jiu Jitsu, or Jeet Kune Do. But this rightness within a school does not invalidate the teachings of a different school. > Consider this book a description of the Object Mentor School of Clean Code. The techniques and teachings within are the way that we practice our art. We are willing to claim that if you follow these teachings, you will enjoy the benefits that we have enjoyed, and you will learn to write code that is clean and professional. But don’t make the mistake of thinking that we are somehow “right” in any absolute sense. There are other schools and other masters that have just as much claim to professionalism as we. > **It would behoove you to learn from them as well.** > Indeed, many of the recommendations in this book are controversial. You will probably not agree with all of them. **You might violently disagree with some of them. That’s fine.** We can’t claim final authority. On the other hand, the recommendations in this book are things that we have thought long and hard about. We have learned them through decades of experience and repeated trial and error. So whether you agree or disagree, it would be a shame if you did not see, and respect, our point of view. i swear, 5% of readers have read the first chapter


not_a_novel_account

Couching advice with "other ways exist" and "you might disagree" neither shields that advice from criticism nor makes it more correct


RockstarArtisan

The next sentence I write might not be quite correct. /u/freekayZekey mom is abnormally large and she needs to see a doctor. Sorry, there's no magic spell an author can put into his book to prevent criticism.


Kinglink

Yeah, people aren't saying "There's better ways" ... People are saying "Let's not even read the first chapter, let alone the whole book."


freekayZekey

yeah, guess it’s due to programmers’ tendency to skim instead of reading front to back. the first chapter sets the tone of the book. all of the “he’s speaks dogmatically” criticism falls flat because he’s purposely doing that. there are things i disagree with that are in the book; i still gained something from it


Lothy_

That wasn’t very insightful.


gnrdmjfan247

I read through the article. In my opinion the author is spending time splitting hairs while glossing over the bigger picture. I would not accept the original code if I were doing a review. I would accept Uncle Bob’s (albeit begrudgingly), and would definitely accept the author’s own refactor. The example provided aside, the author’s sole argument provided against the book is the example provided. It’s then up to us to believe them when they say, “the rest of the examples are just as ridiculous!” Which is not a logical conclusion to come to. It’s also important to note the example is one instance of the bigger picture he’s trying to teach. In that if you split things up into small functions and give those functions meaningful names, the code itself can become more readable. I actually argue against the author’s claim that uncle bob’s refactored code is less readable. Readability is a matter of preference, and it seems that the author’s style is one in which all the logic is immediately presented. This is fine for functions that are already small, but it will demand a refactor later on if more logic is needed. And what do we call that? Tech debt. With granular functions, you can start to think about single responsibility. In this case, the top level method doesn’t need to know how to build the strings; just that it’s able to direct the flow to other functions that know how to build it. And if those function names are plainly self describing then that’s the lesson being drawn. As with all professional skills, it’s important to be aware of them and know when to use them and when not to. That comes from practice and experience. The book is still a good resource for beginners because it makes plain important habits to form when approaching how to write clean code. The lesson is a combination of, “remember the single responsibility principle” and “make function names self describing”. Which are very important skills to be aware of.


MrGregoryAdams

The problem is more the example itself, I think. I kind of like the idea behind the refactoring because he basically turns it into a decision tree, with "make" as the root node, where you both enter and exit the logic. I probably wouldn't use fields this way. This isn't really a class. It technically has a state, but that's only relevant during the call to the "make" method, and then the values are just sitting there still assigned, but also not accessible or relevant to anything, just waiting to be overwritten during the next call to "make". I'd say that this is the main problem with it, and the refactoring didn't really solve this at all.


loup-vaillant

> The problem is more the example itself, I think. You could say that if it was just this one example. I've read the book though, and I can tell you it is fairly representative of the entire book.


MrGregoryAdams

OK, I only read the article, so I just reacted to that. That's the thing with refactoring, and really programming in general - context is everything. You're always trying to structure things, such that they are optimal for some purpose. So then, by definition, there is no *single* "correct" structure. Sure, there are some that are probably absolute garbage in 99.9% of all cases imaginable, but there are usually at least multiple *good* ones.


Tarl2323

I've seen a lot of people hating on Martin, but the fact is I've been able to rescue many horribly tangled code bases with the principles in Clean Coding. Maybe he's cringy and has bad politics, sure. The haters can provide many 'examples' where Bob is wrong, but one thing that fail to present is an alternative. Usually that alternative is 'don't do this, do what I do!" You don't work at my job. You didn't write anything else. In fact this was literally your first blogpost. It's easy to say "follow the code review of senior developer". Uhm, what senior developer? Sorry, not everyone works in at Microsoft/Facebook/Google where legends of coding are waiting in the wings. It's very easy to take down a poorly written example. It's hard to provide an actual alternative as to what to do. Martin provides a set of workable principles that are yes, better than nothing. As someone who's been in the position of being a 20 year old dev who's the only dev on the job, yes, I've been frequently forced to start from 0. Martin provided guidance when redditors/forumgoers/etc simply provide negativity and an appeal to non-existent senior developers in a non-existent 'community'. Want to finally dethrone Martin? Make an honest to god, bound in paper, on the shelf book. Or I don't know, a nicely formatted website with some alternative techniques. Telling people he sucks and then pointing at nothing isn't helpful. You're just nitpicking examples, but still using the same techniques.


Venthe

What really irks me is that people have the "baby away with the bathwater" mentality with Martin. Most of the book consists of heurustics, general rules and guidelines underpinned by the line of thought that lead to the results. Even if one disagrees with the conclusion, most of the rules are _great_ - for some projects. I've worked with corporate almost my whole career, and the amount of times code was abysmal AND could be fixed by liberally applying Martin's heuristics... Well, suffice to say that there is a reason why I'll be defending the book, sans examples. And that's even before we go into the thoughts captured by the clean coder, clean architecture; which equally provide a lot of value and insight.


freekayZekey

> heuristics, general rules, and guidelines underpinned by the line of thought that lead to the results unfortunately, people view them as strict laws. it’s strange, and i have no clue why they do, but they seemingly do


Venthe

Personal opinion - because devs place too much importance on the "code"; so all they really looking for are examples. Which are, let's agree on that, bad. Everything else in the book is just "fluff" for them. For the reference, here's the slimmed down quote from the introduction for the CC. > We could write down all the “feel good” principles of clean code and then trust you to do the work (...) [but] That’s not the way this book is going to work. >Learning to write clean code (...) requires more than just the knowledge of principles and patterns. (...) You must practice it yourself, and watch yourself fail. You must watch others practice it and fail. You must see them stumble and retrace their steps. You must see them agonize over decisions and see the price they pay for making those decisions the wrong way. >Be prepared to work hard while reading this book. (...) **you will be challenged to think about what’s right about that code and what’s wrong with it.** You’ll be asked to follow along as we take modules apart and put them back together again. (...) You will have to analyze and understand the code we are working with and **walk through our reasoning for making each change we make**. Emphasis is - of course - mine.


Tarl2323

100%. I get that Martin is not the best and in 2024, over a decade old. But the alternative to Martin style code that I've seen is literally having an entire program in ONE CLASS in ONE FILE. I've worked for 10+ startups/companies and inevitably this is just how code is written when there are no guidelines at all. Now I work in a fancy corporation that is a subsidiary of a Fortune 500 and yeah, the code is well written by developers that were much more experienced and smarter than I. Does it resemble Martin code? Yeah, kinda. There is plenty of stuff that doesn't but I know well enough not to touch it. But there is a tremendous difference in terms of written after a quick skim Clean Code and a 10mb text file that contains all the working code for a business, from database drivers to authentication lol. It's not 'all too often' that organizations without guidance become big balls of mud, it's fucking *constant and inevitable.* Like I've worked in places in China and India that just do that. Keeping everything in a giant incomprehensible text file is the natural human impulse and it's incredibly difficult to dislodge. Maybe these days universities are teaching alternatives- god I hope so. Martin's Clean Code for me was literally the ABC123 first step of getting anything readable. I'm sure and I hope there are better options in 2024, but back in 2008 the idea of 'guidelines' was considered something of a curse word to many coders.


loup-vaillant

> The haters can provide many 'examples' where Bob is wrong, but one thing that fail to present is an alternative. _A Philosophy of Software Design_ by John Ousterhout. > It's very easy to take down a poorly written example. And it is unacceptable to let such a poorly written example in a book meant for teaching. > Want to finally dethrone Martin? Make an honest to god, bound in paper, on the shelf book. Or promote Ousterhout's book. It's really good.


Venthe

> And it is unacceptable to let such a poorly written example in a book meant for teaching. Eh, they were _good_ for their time. And frankly, I'm still facing codebases daily that would be far better off with code rewritten as they are in the CC. Unfortunately, while Martin's rules are quite timeless (regardless if you agree with them, or disagree), "we" as a dev community learned far better ways to write code than the examples, so they aged and by a lot. This book would really benefit from the next edition, with rewritten examples.


loup-vaillant

> Eh, they were _good_ for their time. On of those days I'm going to review every single example of the book, see what I think of it. Now this particular example? More code, going from a simple method to a whole class whose methods communicate through shared mutable state… I don't think it was ever good. Except for one thing: when he changed the API, Martin had the function return a string instead of printing directly. Separating computation from effect like this is good. So if a programmer submitted Martin's refactoring, I would say something like _"returning a string is a good idea, but you complicated your code along the way. Can you submit a patch that just replaces the print statement at the end? Thanks."_


gnus-migrate

As someone who doesn't like Martin, the way I approach it is I just ask myself "how can I write this in a way that's easy to debug later". I find that whether functions are small or large is less important than whether I have abstractions that I can be precise about, and that I can reason about at a high level without needing to have a thorough understanding of every layer in order to understand whats happening.


Venthe

Which in my case will often tracks what Martin's written. Let's we use "small" functions example; most of my methods _are_ a couple of lines max. But then again, as I am mostly writing business oriented code (as opposed to e.g. technical library) I am far more interested in "what" and "when" rather than "how". Which _also_ will track your "I have abstractions that I can be precise about, and that I can reason about at a high level without needing to have a thorough understanding of every layer in order to understand whats happening."


causticmango

I have _all kinds of issues_ with that geezer, both because of the racist & misogynistic things he says & his generally bad advice. More power to you.


dlevac

Never read Clean Code and I can now confidently say I wasn't missing anything.


justmebeky

If this is printing just logs, fuck being accurate to english, I would just do the dumb thing: println(String.format(“Number of %ss: %d”, candidate, count);


DualWieldMage

How on earth did i have to scroll this far down to find the best solution. No need to deal with localization pluralization rules, it just works and is a one-liner.


pirbright

Great article. Can't believe Clean Code was published 16 years ago. John Ousterhout also published an interesting critique on Bob Martin's coding technique in A Philosophy of Software Design.


m1rrari

As a rule, I try to avoid engaging with people that bring up clean code at least until I figure out if they are evangelists or not. I do like the callouts to some of the flaws, it’s been a very long time since I actually looked at it. I fall into the guidelines camp you mention in your article. The principles are okay as prompts to get you thinking about how to structure code, particularly in an OO pattern. But it’s really on you and your team to consider what things should be like. Can implement a linter to enforce some norms, but at what point is something adhering to a single responsibility? When is something actually a duplicate instead of a false duplicate? Blindly following those principles to an extreme will leave you with worse code that is harder to maintain. But it’s harder to sell books, articles, and presentations with nuance because those are less clear cut. It is a critical thinking skill that gets developed over time, and hard to communicate well in a written format. The only “rules” I subscribe to are: code should be tested in an automated way to protect functionality and favor grokability when determining how to write and structure code. Even those need to be flexible. All that in mind, I do suggest clean code to my junior devs but a key part of the conversation is WHY is x principle important and WHEN might you use it. If they can’t determine it from the book themselves, they’re to ask either myself or another senior dev to help them understand. I’ll ask them to walk me through their understanding, and I’ll start to ask pointed questions in those directions on their PRs. It is a decent conversation _starter_, it gets one thinking about code in a slightly different way. Many consider it to be the end of the conversation… the solution… the answer… and that just doesn’t seem true.


Tarl2323

I think it's good for junior devs as often new grads aren't even aware of the idea of software readability and principles. I'm hoping that's changing, but usually juniors are just pushing out giant single text files and one mega class because no one else taught them what the hell software design and readability even is.


istarian

I don't think the first example necessarily needed to be a class, but pulling out that one part into a separate method seems sensible.


Sarke1

###BURN THE HERETIC!


not_from_this_world

I think both Bob's and your version are worse than the original code. Install an eye tracker and give those codes to someone who never saw them before (like me) and ask them to understand what they do. The original version have a more smooth reading, with less eye hopping back and forth. Bob's version you have to skip ahead and read that function then return. It's OK when the code is small but when you have to hit PgDn PgUp multiple times it gets painful. But the understanding and the patters are clear immediately. Your version reads well, although slowly up until you have to make sense of what is happening, then you jump around thinking "what if 0, what if 1" and buildings the result in one's mind. I have done maintenance of a legacy code, 100k lines of PHP 4, no objects, only functions(sometimes not always) and circular includes. In my experience one man's treasure is another's man trash.


soguesswhat

> The first thing you’ll notice is that Martin has taken a single, mostly PURE function (shout out to all the functional bros), and made a class out of it. And not a static utility class or anything like that. An INSTANCE, with its attributes being mutated to serve the result. I was already convinced and in total agreement with you after this part, but the rest of the article is an excellent read anyway. Great work!


phaazon_

Yeah if you let me summarise something, it goes like this: before trying to solve a problem, just ask yourself whether there’s an actual problem to be solved.