There's a lot of bad advice being tossed around in this thread. If you are worried about having to jump through multiple files to understand what some code is doing, you should consider that your naming conventions are the problem, not the fact that code is hidden behind functional boundaries.
Coding at scale is about managing complexity. The best code is code you don't have to read because of well named functional boundaries. Without these functional boundaries, you have to understand how every line of a function works, and then mentally model the entire graph of interactions at once, because of the potential for interactions between lines within a functional boundary. The complexity (sum total of possible interactions) grows as the number of lines within a functional boundary grows. The cognitive load to understand code grows as the number of possible interactions grow. Keeping methods short and hiding behavior behind well named functional boundaries is how you manage complexity in code.
The idea of code telling a story is that a unit of work should explain what it does through its use of well named variables, function/object names, and how data flows between function/objects. If you have to dig into the details of a function to understand what it does, you have failed to sufficiently explain what the function does through its naming and set of arguments.
Finally! I'm glad to hear I'm not the only one. I've gone against 'Clean Code' zealots that end up writing painfully warped abstractions in the effort to adhere to what is in this book. It's OK to duplicate code in places where the abstractions are far enough apart that the alternative is worse. I've had developers use the 'partial' feature in C# to meet Martin's length restrictions to the point where I have to look through 10-15 files to see the full class.
The examples in this post are excellent examples of the flaws in Martin's absolutism.
I think one should always be careful not to throw out the baby with the bathwater[0].
Do I force myself to follow every single crazy rule in Clean Code? Heck no. Some of them I don't agree with. But do I find myself to be a better coder because of what I learned from Bob Martin? Heck yes. Most of the points he makes are insightful and I apply them daily in my job.
Being a professional means learning from many sources and knowing that there's something to learn from each of them- and some things to ignore from each of them. It means trying the things the book recommends, and judging the results yourself.
So I'm going to keep recommending Clean Code to new developers, in the hopes that they can learn the good bits, and learn to ignore the bad bits. Because so far, I haven't found a book with more good bits (from my perspective) and fewer bad bits (from my perspective).
I'm completely with you here. Until I read Clean Code, I could never really figure out why my personal projects were so unreadable a year later but the code I read at work was so much better even though it was 8 years old. Sure, I probably took things too far for a while and made my functions too small, or my classes too small, or was too nitpicky on code reviews. But I started to actually think about where I should break a function. I realized that a good name could eliminate almost all the comments I had been writing before, leaving only comments that were actually needed. And as I learned how to break down my code, I was forced to learn how to use my IDE to navigate around. All of a sudden new files weren't a big deal, and that opened up a whole new set of changes that I could start making.
I see a lot of people in here acting like all the advice in Clean Code is obviously true or obviously false, and they claim to know how to write a better book. But, like you, I will continue to recommend Clean Code to new developers on my team. It's the fastest way (that I've found so far, though I see other suggestions in the comments here) to get someone to transition from writing "homework code" (that never has to be revisited) to writing maintainable code. Obviously, there are bad parts of Clean Code, but if that new dev is on my team, I'll talk through why certain parts are less useful than others.
Perfect, Its definitly my personal impression, but while reading the post it looks like the author was looking for a "one size fits all" book and was dissapointed they did not find it.
And to be honest that book will never exist, every knowledge contributes to growing as a professional, just make sure to understand, discuss, and use it (or not) for a real reason, not just becaue its on book A or B.
Its not like people need to choose one book and follow it blindly for the rest of their lives, read more books :D
One mistake I think people like the author make is treating these books as some sort of bible that you must follow to the letter. People who
evangelised TDD were the worst offenders of this. "You HAVE to do it like this, it's what the book says!"
You're not supposed to take it literally for every project, these are concepts that you need to adapt to your needs. In that sense I think the book still holds up.
For me this maps so clearly to the Dreyfus model of skill acquisition. Novices need strict rules to guide their behavior. Experts are able to use intuition they have developed. When something new comes along, everyone seems like a novice for a little while.
The Dreyfus model identifies 5 skill levels:
Novice
Wants to achieve a goal, and not particularly interested in learning.
Requires context free rules to follow.
When something unexpected happens will get stuck.
Advanced Beginner
Beginning to break away from fixed rules.
Can accomplish tasks on own, but still has difficulty troubleshooting.
Wants information fast.
Competent
Developed a conceptual model of task environment.
Able to troubleshoot.
Beginning to solve novel problems.
Seeks out and solve problems.
Shows initiative and resourcefulness.
May still have trouble determining which details to focus on when solving a problem.
Proficient
Needs the big picture.
Able to reflect on approach in order to perform better next time.
Learns from experience of others.
Applies maxims and patterns.
Expert
Primary source of knowledge and information in a field.
Constantly look for better ways of doing things.
Write books and articles and does the lecture circuit.
Work from intuition.
Knows the difference between irrelevant and important details.
Uncle Bob himself acts like it is a bible, so if you buy into the rest of his crap then you'll likely buy into that too.
If treated as guidelines you are correct Clean Code is only eh instead of garbage. But taken in the full context of how it is presented/intended to be taken by the author it is damaging to the industry.
Yup. I see the book as guide to a general goal, not a specific objective that can be defined. To actually reach that goal is sometimes completely impossible and in many other cases it introduces too much complexity.
However, in most cases heading towards that goal is a beneficial thing--you just have to recognize when you're getting too close and bogging down in complying with every detail.
I still consider it the best programming book I've ever read.
I agree with the sentiment that you don't want to over abstract, but Bob doesn't suggest that (as far as I know). He suggests extract till you drop, meaning simplify your functions down to doing one thing and one thing only and then compose them together.
Hands down, one of the best bits I learned from Bob was the "your code should read like well-written prose." That has enabled me to write some seriously easy to maintain code.
That strikes me as being too vague to be of practical use. I suspect the worst programmers can convince themselves their code is akin to poetry, as bad programmers are almost by definition unable to tell the difference. (Thinking back to when I was learning programming, I'm sure that was true of me.) To be valuable, advice needs to be specific.
If you see a pattern of a junior developer committing unacceptably poor quality code, I doubt it would be productive to tell them Try to make it read more like prose. Instead you'd give more concrete advice, such as choosing good variable names, or the SOLID principles, or judicious use of comments, or sensible indentation.
Perhaps I'm missing something though. In what way was the code should read like well-written prose advice helpful to you?
Absolutely this. Code should tell a story, the functions and objects you use are defined by the context of the story at that level of description. If you have to translate between low-level operations to reconstruct the high level behavior of some unit of work, you are missing some opportunities for useful abstractions.
Coding at scale is about managing complexity. The best code is code you don't have to read because of well named functional boundaries. Natural language is our facility for managing complexity generally. It shouldn't be surprising that the two are mutually beneficial.
I tried to write code with small functions and was dissuaded from doing that at both my teams over the past few years. The reason is that it can be hard to follow the logic if it's spread out among several functions. Jumping back and forth breaks your flow of thought.
I think the best compromise is small summary comments at various points of functions that "hold the entire thought".
Nice! However, none of this is required for this endpoint. Here's why:
1. The connect action could be replaced by doing the connection once on app startup.
2. The validation could be replaced with middleware like express-joi.
3. The stripe/email steps should be asynchronous (ex: simple crons). This way, you create the user and that's it. If Stripe is down, or the email provider is down, you still create the user. If the server restarts while someone calls the endpoint, you don't end up with a user with invalid Stripe config. You just create a user with stripeSetup=false and welcomeEmailSent=false and have some crons that every 5 seconds query for these users and do their work. Also, ensure you query for false and not "not equal to true" here as it's not efficient.
Off topic but is connecting to Mongo on every API hit best practice? I abstract my connection to a module and keep that open for the life of the application.
Robert Martin and his aura always struck me as odd. In part because of how revered he always was at organizations I worked. Senior developers would use his work to end arguments, and many code reviews discussions would be judged by how closely they adhere to Clean Code.
Of course reading Clean Code left me more confused than enlightened due precisely to what he presents as good examples of Code. The author of the article really does hit the nail on the head about Martin's code style - it's borderline unreadable a lot of times.
Who the f. even is Robert Martin?! What has he built? As far as I am able to see he is famous and revered because he is famous and revered.
He ran a consultancy and knew how to pump out books into a world of programmers that wanted books
I was around in the early 90s through to the early 2000s when a lot of the ideas came about slowly got morphed by consultants who were selling this stuff to companies as essentially "religion". The nuanced thoughts of a lot of the people who had most of the original core ideas is mostly lost.
It's a tricky situation, at the core of things, there are some really good ideas, but the messaging by people like "uncle bob" seem to fail to communicate the mindset in a way that develops thinking programmers. Mainly because him, and people like Ron Jerfferies, really didn't actually build anything serious once they became consultants and started giving out all these edicts. If you watched them on forums/blogs at the time, they were really not that good. There were lots of people who were building real things and had great perspectives, but their nuanced perspectives were never really captured into books, and it would be hard to as it is more about the mentality of using ideas and principles and making good pragmatic choices and adapting things and not being limited by "rules" but about incorporating the essence of the ideas into your thinking processes.
So many of those people walked away from a lot of those communities when it morphed into "Agile" and started being dominated by the consultants.
10 or so years ago when I first got into development I looked to people like Martin's for how I should write code.
But I had more and more difficulty reconciling bizarrely optimistic patterns with reality. This from the article perfectly sums it up:
>Martin says that functions should not be large enough to hold nested control structures (conditionals and loops); equivalently, they should not be indented to more than two levels.
Back then as now I could not understand how one person can make such confident and unambiguous statements about business logic across the spectrum of use cases and applications.
It's one thing to say how something should be written in ideal circumstances, it's another to essentially say code is spaghetti garbage because it doesn't precisely align to a very specific dogma.
This is the point that I have the most trouble understanding in critiques of Fowler, Bob, and all writers who write about coding: in my reading, I had always assumed that they were writing about the perfect-world ideal that needs to be balanced with real-world situations. There's a certain level of bluster and over-confidence required in that type of technical writing that I understood to be a necessary evil in order to get points across. After all, a book full of qualifications will fail to inspire confidence in its own advice.
Now, some people will claim that having 8-character indentations makes
the code move too far to the right, and makes it hard to read on a
80-character terminal screen. The answer to that is that if you need
more than 3 levels of indentation, you're screwed anyway, and should fix
your program.
The big problem that I have with Clean Code -- and with its sequel, Clean Architecture -- is that for its most zealous proponents, it has ceased to be a means to an end and has instead become an end in itself. So they'll justify their approach by citing one or other of the SOLID principles, but they won't explain what benefit that particular SOLID principle is going to offer them in that particular case.
The point that I make about patterns and practices in programming is that they need to justify their existence in terms of value that they provide to the end user, to the customer, or to the business. If they can't provide clear evidence that they actually provide those benefits, or if they only provide benefits that the business isn't asking for, then they're just wasting time and money.
One example that Uncle Bob Martin hammers home a lot is separation of concerns. Separation of concerns can make your code a lot easier to read and maintain if it's done right -- unit testing is one good example here. But when it ceases to be a means to an end and becomes an end in itself, or when it tries to solve problems that the business isn't asking for, it degenerates into speculative generality. That's why you'll find project after project after project after project after project with cumbersome and obstructive data access layers just because you "might" want to swap out your database for some unknown mystery alternative some day.
I don’t disagree with the overall message or choice of examples behind this post, but one paragraph stuck out to me:
> Martin says that it should be possible to read a single source file from top to bottom as narrative, with the level of abstraction in each function descending as we read on, each function calling out to others further down. This is far from universally relevant. Many source files, I would even say most source files, cannot be neatly hierarchised in this way.
The relevance is a fair criticism but most programs in most languages can in fact be hierarchized this way, with the small number of mutually interdependent code safely separated. Many functional languages actually enforce this.
As an F# developer it can be very painful to read C# programs even though I often find C# files very elegant and readable: it just seems like a book, presented out of order, and without page numbers. Whereas an .fsproj file provides a robust reading order.
> But mixed into the chapter there are more questionable assertions. Martin says that Boolean flag arguments are bad practice, which I agree with, because an unadorned true or false in source code is opaque and unclear versus an explicit IS_SUITE or IS_NOT_SUITE... but Martin's reasoning is rather that a Boolean argument means that a function does more than one thing, which it shouldn't.
I see how this can be polemic because most code is littered w/ flags, but I tend to agree that boolean flags can be an anti-pattern (even though it's apparently idiomatic in some languages).
Usually the flag is there to introduce a branching condition (effectively breaking "a function should do one thing") but don't carry any semantic on it's own. I find the same can be achieved w/ polymorphism and/or pattern-matching, the benefit being now your behaviour is part of the data model (the first argument) which is easier to reason about, document, and extend to new cases (don't need to keep passing flags down the call chain).
As anything, I don't think we can say "I recommend / don't recommend X book", all knowledge and experience is useful. Just use your judgment and don't treat programming books as a holy book.
> This is done as part of an overall lesson in the virtue of inventing a new domain-specific testing language for your tests. I was left so confused by this suggestion. I would use exactly the same code to demonstrate exactly the opposite lesson. Don't do this!
This example (code is in the article) was very telling of the book author's core philosophy.
Best I can tell, the OOP movement of the 2000s (I wasn't a professional in 2008, though I was learning Java at the time) was at its heart rooted in the idea that abstractions are nearly always a win; the very idealistic perspective that anything you can possibly give a name to, should be given a name. That programmers down the line will thank you for handing them a named entity instead of perhaps even a single line of underlying code.
This philosophy greatly over-estimates the value, and greatly under-estimates the cost, of idea-creation. I don't just write some code, I create an idea, and then I write a bit of code as implementation details for it. This is a very tantalizing vision of development: all messy details are hidden away, what we're left with is a beautiful constellation of ideas in their purest form.
The problem is that when someone else has to try and make sense of your code, they first have to internalize all of your ideas, instead of just reading the code itself which may be calling out to something they already understand. It is the opposite of self-documenting code: it's code that requires its own glossary in addition to the usual documentation. "wayTooCold()" may read more naturally to the person who wrote it, but there's a fallacy where they assume that that also applies to other minds that come along and read it later.
Establishing a whole new concept with its own terminology in your code is costly. It has to be done with great care and only when absolutely necessary, and then documented thoroughly. I think as an industry we have more awareness of this nowadays. We don't just make UML diagrams and kick them across the fence for all those mundane "implementation details" to be written.
This thread is full of people saying what's wrong with the book without posing alternatives. I get that it's dogmatic, but do people seriously take it as gospel? I'd read it along with other things. Parts are great and others are not. It's not terrible.
I agree. Trying to apply the lessons in there leads to code that is more difficult to read and reason about. Making it "read like a book" and keeping functions short sound good on the surface but they lead to lines getting taken up entirely by function names and a nightmare of tracking call after call after call.
It's been years since I've read the book and I'm still having trouble with the bad ideas from there because they're so well stuck with me that I feel like I'm doing things wrong if I don't follow the guidelines in there. Sometimes I'll actually write something in a sensible way, change it to the Clean Code way, and then revert it back to where it was when I realize my own code is confusing me when written like that.
This isn't just a Robert C Martin issue. It's a cultural issue. People need to stop shaming others if their code doesn't align with Clean Code. People need to stop preaching from the book.
I recently read this cover to cover and left a negative review on Amazon. I'm happy to see I'm not the only one, and this goes into it in a whole lot more detail.
The author seems like they took a set of rules that are good for breaking beginning programmers bad habits and then applied them into the extreme. There's a whole lot of rules which aren't bad up until you try to apply them like laws of gravity that must always be followed. Breaking up big clunky methods that do way too much is great for readability, right up until you're spraying one line helper methods all over your classes and making them harder to read because now you're inventing your own domain specific language everyone has to learn (often with the wrong abstractions which get extended through the years and wind up needing a massive refactoring down the road which would have been simpler with fewer methods and abstractions involved at the start).
A whole lot of my job is taking classes, un-DRY'ing them completely so there's duplication all over the place, then extracting the right (or at least more correct) abstractions to make the whole thing simple and readable and tight.
My biggest gripe: Functions shouldn't be short, they should be of appropriate size. They should contain all the logic that isn't supposed to be exposed to the outside for someone else to call. If that means your function is 3000 lines long, so be it.
Realize that your whole program is effectively one big function and you achieve nothing by scattering its guts out into individual sub-functions just to make the pieces smaller.
If something is too convoluted and does too much, or has too much redundancy, you'll know, because it'll cause problems. It'll bother you. You shouldn't pre-empt this case by just writing small functions by default. That'll just cause its own problems.
This is an interesting article because as I was reading Martin's suggestions I agreed with every single one of them. 5 lines of code per function is ideal. Non-nested whenever possible. Don't mix query/pure and commands/impure. Then I got to the code examples and they were dreadful. Those member variables should be readonly.
Using Martin's suggestion with Functional Hexagonal Architecture would lead to beautiful code. I know because that's what I've been writing for the past 3 years.
Great! While we're on it, can we retire the gang of four as well? I mean, the authors are obviously great software engineers, and the Patterns have helped to design, build, and most importantly read, a lot of software. But as we move forward, more and more of these goals can be achieved much more elegantly and sustainably with new languages and more functional approaches. Personally, I find re-teaching junior programmers, who are still trying to make everything into a class, very tiring.
I don’t understand the amount of hate that Clean Code gets these days…it’s a relatively straightforward set of principles that can help you create a software system maintainable by humans for a very long time. Of course it’s not an engineering utopia, there’s no such thing.
I get the impression that it’s about the messengers and not the messages, and that people have had horrible learning experiences that have calcified into resistance to do with anything clean. But valuable insights are being lost, and they will have to be re-learned in a new guise at a later date.
For me Clean Code is not about slavishly adhering to the rules therein, but about guidelines to help make your code better if you follow them, in most circumstances. On his blog Bob Martin himself says about livable code vs pristinely clean code: "Does this rule apply to code? It absolutely does! When I write code I fight very hard to keep it clean. But there are also little places where I break the rules specifically because those breakages create affordances for transient issues."
I've found the Clean Code guidelines very useful. Your team's mileage may very. As always: Use what works, toss the rest, give back where you can.
I never recommended Clean Code, but I've become a strong advocate against it on teams that I lead after reading opinions by Bob Martin such as this one: https://blog.cleancoder.com/uncle-bob/2017/01/11/TheDarkPath.... That whole article reads as someone who is stuck in their old ways and inflexible, then given their large soapbox tries to justify their discomfort and frustration. I consider Swift, Kotlin (and Rust) to be one of the most important language evolutions that dramatically improved software quality on the projects I've worked on.
I've seen so many real world counter-examples to arguments made in that article and his other blog posts that I'm puzzled why this guy has such a large and devoted following.
Actually, I found the post you linked to fairly logical. He’s saying that humans are inherently lazy, and that a language that gives us the option between being diligent (strong types) or being reckless (opt-out of strong types) will lead to the worst form of recklessness: opting out while not writing tests, giving the misimpression of safety.
His point is that you can’t practically force programmers to be diligent through safety features of a language itself, since edge-cases require escape hatches from those safety features, and those safety hatches will be exploited by our natural tendency to avoid “punishment”.
I’m not sure I agree with his point, but I don’t find it an unreasonable position. I’d be curious if Rust has escape hatches that are easily and often abused.
My favorite example here, and a counterpoint to Bob, is Reacts’s dangerously-unsafe-html attribute. I haven’t seen it in years (to the point where I can’t recall the exact naming), and perhaps it was removed at some point. But it made the escape hatch really painful to use. And so the pain of using the escape hatch made it less painful to actually write React in the right manner. Coming from Angular, I think I struggled at first with thinking I had to write some dangerous html, but over time I forgot the choice of writing poor React code even existed.
So I guess I disagree with Bob’s post here. It is possible to have safety features in languages that are less painful than the escape-hatches from those safety features. And no suite of tests will ever be as powerful as those built-in safety features.
[+] [-] hackinthebochs|4 years ago|reply
Coding at scale is about managing complexity. The best code is code you don't have to read because of well named functional boundaries. Without these functional boundaries, you have to understand how every line of a function works, and then mentally model the entire graph of interactions at once, because of the potential for interactions between lines within a functional boundary. The complexity (sum total of possible interactions) grows as the number of lines within a functional boundary grows. The cognitive load to understand code grows as the number of possible interactions grow. Keeping methods short and hiding behavior behind well named functional boundaries is how you manage complexity in code.
The idea of code telling a story is that a unit of work should explain what it does through its use of well named variables, function/object names, and how data flows between function/objects. If you have to dig into the details of a function to understand what it does, you have failed to sufficiently explain what the function does through its naming and set of arguments.
[+] [-] jugg1es|4 years ago|reply
[+] [-] dham|4 years ago|reply
My clean code book:
* Put logic closest to where it needs to live (feature folders)
* WET (Write everything twice), figure out the abstraction after you need something a 3rd time
* Realize there's no such thing as "clean code"
[+] [-] mabbo|4 years ago|reply
Do I force myself to follow every single crazy rule in Clean Code? Heck no. Some of them I don't agree with. But do I find myself to be a better coder because of what I learned from Bob Martin? Heck yes. Most of the points he makes are insightful and I apply them daily in my job.
Being a professional means learning from many sources and knowing that there's something to learn from each of them- and some things to ignore from each of them. It means trying the things the book recommends, and judging the results yourself.
So I'm going to keep recommending Clean Code to new developers, in the hopes that they can learn the good bits, and learn to ignore the bad bits. Because so far, I haven't found a book with more good bits (from my perspective) and fewer bad bits (from my perspective).
[0]https://en.wikipedia.org/wiki/Don%27t_throw_the_baby_out_wit...
[+] [-] simonsaysso|4 years ago|reply
I see a lot of people in here acting like all the advice in Clean Code is obviously true or obviously false, and they claim to know how to write a better book. But, like you, I will continue to recommend Clean Code to new developers on my team. It's the fastest way (that I've found so far, though I see other suggestions in the comments here) to get someone to transition from writing "homework code" (that never has to be revisited) to writing maintainable code. Obviously, there are bad parts of Clean Code, but if that new dev is on my team, I'll talk through why certain parts are less useful than others.
[+] [-] dsego|4 years ago|reply
[+] [-] flatlin3|4 years ago|reply
And to be honest that book will never exist, every knowledge contributes to growing as a professional, just make sure to understand, discuss, and use it (or not) for a real reason, not just becaue its on book A or B.
Its not like people need to choose one book and follow it blindly for the rest of their lives, read more books :D
[+] [-] rockbruno|4 years ago|reply
You're not supposed to take it literally for every project, these are concepts that you need to adapt to your needs. In that sense I think the book still holds up.
[+] [-] mattmcknight|4 years ago|reply
The Dreyfus model identifies 5 skill levels:
Novice
Wants to achieve a goal, and not particularly interested in learning. Requires context free rules to follow. When something unexpected happens will get stuck.
Advanced Beginner
Beginning to break away from fixed rules. Can accomplish tasks on own, but still has difficulty troubleshooting. Wants information fast.
Competent
Developed a conceptual model of task environment. Able to troubleshoot. Beginning to solve novel problems. Seeks out and solve problems. Shows initiative and resourcefulness. May still have trouble determining which details to focus on when solving a problem.
Proficient
Needs the big picture. Able to reflect on approach in order to perform better next time. Learns from experience of others. Applies maxims and patterns.
Expert
Primary source of knowledge and information in a field. Constantly look for better ways of doing things. Write books and articles and does the lecture circuit. Work from intuition. Knows the difference between irrelevant and important details.
[+] [-] runevault|4 years ago|reply
If treated as guidelines you are correct Clean Code is only eh instead of garbage. But taken in the full context of how it is presented/intended to be taken by the author it is damaging to the industry.
[+] [-] LorenPechtel|4 years ago|reply
However, in most cases heading towards that goal is a beneficial thing--you just have to recognize when you're getting too close and bogging down in complying with every detail.
I still consider it the best programming book I've ever read.
[+] [-] jugg1es|4 years ago|reply
[+] [-] throwaway2037|4 years ago|reply
I agree: Clean Coders and TDDers are cut from the same cloth.
[+] [-] unknown|4 years ago|reply
[deleted]
[+] [-] breck|4 years ago|reply
[+] [-] rglover|4 years ago|reply
I agree with the sentiment that you don't want to over abstract, but Bob doesn't suggest that (as far as I know). He suggests extract till you drop, meaning simplify your functions down to doing one thing and one thing only and then compose them together.
Hands down, one of the best bits I learned from Bob was the "your code should read like well-written prose." That has enabled me to write some seriously easy to maintain code.
[+] [-] MaxBarraclough|4 years ago|reply
That strikes me as being too vague to be of practical use. I suspect the worst programmers can convince themselves their code is akin to poetry, as bad programmers are almost by definition unable to tell the difference. (Thinking back to when I was learning programming, I'm sure that was true of me.) To be valuable, advice needs to be specific.
If you see a pattern of a junior developer committing unacceptably poor quality code, I doubt it would be productive to tell them Try to make it read more like prose. Instead you'd give more concrete advice, such as choosing good variable names, or the SOLID principles, or judicious use of comments, or sensible indentation.
Perhaps I'm missing something though. In what way was the code should read like well-written prose advice helpful to you?
[+] [-] hackinthebochs|4 years ago|reply
Coding at scale is about managing complexity. The best code is code you don't have to read because of well named functional boundaries. Natural language is our facility for managing complexity generally. It shouldn't be surprising that the two are mutually beneficial.
[+] [-] pradn|4 years ago|reply
I think the best compromise is small summary comments at various points of functions that "hold the entire thought".
[+] [-] winrid|4 years ago|reply
1. The connect action could be replaced by doing the connection once on app startup.
2. The validation could be replaced with middleware like express-joi.
3. The stripe/email steps should be asynchronous (ex: simple crons). This way, you create the user and that's it. If Stripe is down, or the email provider is down, you still create the user. If the server restarts while someone calls the endpoint, you don't end up with a user with invalid Stripe config. You just create a user with stripeSetup=false and welcomeEmailSent=false and have some crons that every 5 seconds query for these users and do their work. Also, ensure you query for false and not "not equal to true" here as it's not efficient.
[+] [-] nichch|4 years ago|reply
[+] [-] amptorn|4 years ago|reply
This is a good assertion but ironically it's not Bob Martin's line. He was quoting Grady Booch.
[+] [-] theflyinghorse|4 years ago|reply
Of course reading Clean Code left me more confused than enlightened due precisely to what he presents as good examples of Code. The author of the article really does hit the nail on the head about Martin's code style - it's borderline unreadable a lot of times.
Who the f. even is Robert Martin?! What has he built? As far as I am able to see he is famous and revered because he is famous and revered.
[+] [-] pydry|4 years ago|reply
[+] [-] keithnz|4 years ago|reply
I was around in the early 90s through to the early 2000s when a lot of the ideas came about slowly got morphed by consultants who were selling this stuff to companies as essentially "religion". The nuanced thoughts of a lot of the people who had most of the original core ideas is mostly lost.
It's a tricky situation, at the core of things, there are some really good ideas, but the messaging by people like "uncle bob" seem to fail to communicate the mindset in a way that develops thinking programmers. Mainly because him, and people like Ron Jerfferies, really didn't actually build anything serious once they became consultants and started giving out all these edicts. If you watched them on forums/blogs at the time, they were really not that good. There were lots of people who were building real things and had great perspectives, but their nuanced perspectives were never really captured into books, and it would be hard to as it is more about the mentality of using ideas and principles and making good pragmatic choices and adapting things and not being limited by "rules" but about incorporating the essence of the ideas into your thinking processes.
So many of those people walked away from a lot of those communities when it morphed into "Agile" and started being dominated by the consultants.
[+] [-] strict9|4 years ago|reply
But I had more and more difficulty reconciling bizarrely optimistic patterns with reality. This from the article perfectly sums it up:
>Martin says that functions should not be large enough to hold nested control structures (conditionals and loops); equivalently, they should not be indented to more than two levels.
Back then as now I could not understand how one person can make such confident and unambiguous statements about business logic across the spectrum of use cases and applications.
It's one thing to say how something should be written in ideal circumstances, it's another to essentially say code is spaghetti garbage because it doesn't precisely align to a very specific dogma.
[+] [-] headbee|4 years ago|reply
[+] [-] joshribakoff|4 years ago|reply
My recollection of the clean code book and Fowler books were very much “I think these are smells, but smells in the code are also fine”
Note: Robert Martin and Martin Fowler are different people. Are you saying Fowler said this?
[+] [-] rootlocus|4 years ago|reply
[+] [-] beckingz|4 years ago|reply
[+] [-] lobstrosity420|4 years ago|reply
Does it say that though?
[+] [-] jammycakes|4 years ago|reply
The point that I make about patterns and practices in programming is that they need to justify their existence in terms of value that they provide to the end user, to the customer, or to the business. If they can't provide clear evidence that they actually provide those benefits, or if they only provide benefits that the business isn't asking for, then they're just wasting time and money.
One example that Uncle Bob Martin hammers home a lot is separation of concerns. Separation of concerns can make your code a lot easier to read and maintain if it's done right -- unit testing is one good example here. But when it ceases to be a means to an end and becomes an end in itself, or when it tries to solve problems that the business isn't asking for, it degenerates into speculative generality. That's why you'll find project after project after project after project after project with cumbersome and obstructive data access layers just because you "might" want to swap out your database for some unknown mystery alternative some day.
[+] [-] nicklecompte|4 years ago|reply
> Martin says that it should be possible to read a single source file from top to bottom as narrative, with the level of abstraction in each function descending as we read on, each function calling out to others further down. This is far from universally relevant. Many source files, I would even say most source files, cannot be neatly hierarchised in this way.
The relevance is a fair criticism but most programs in most languages can in fact be hierarchized this way, with the small number of mutually interdependent code safely separated. Many functional languages actually enforce this.
As an F# developer it can be very painful to read C# programs even though I often find C# files very elegant and readable: it just seems like a book, presented out of order, and without page numbers. Whereas an .fsproj file provides a robust reading order.
[+] [-] hcarvalhoalves|4 years ago|reply
I see how this can be polemic because most code is littered w/ flags, but I tend to agree that boolean flags can be an anti-pattern (even though it's apparently idiomatic in some languages).
Usually the flag is there to introduce a branching condition (effectively breaking "a function should do one thing") but don't carry any semantic on it's own. I find the same can be achieved w/ polymorphism and/or pattern-matching, the benefit being now your behaviour is part of the data model (the first argument) which is easier to reason about, document, and extend to new cases (don't need to keep passing flags down the call chain).
As anything, I don't think we can say "I recommend / don't recommend X book", all knowledge and experience is useful. Just use your judgment and don't treat programming books as a holy book.
[+] [-] brundolf|4 years ago|reply
This example (code is in the article) was very telling of the book author's core philosophy.
Best I can tell, the OOP movement of the 2000s (I wasn't a professional in 2008, though I was learning Java at the time) was at its heart rooted in the idea that abstractions are nearly always a win; the very idealistic perspective that anything you can possibly give a name to, should be given a name. That programmers down the line will thank you for handing them a named entity instead of perhaps even a single line of underlying code.
This philosophy greatly over-estimates the value, and greatly under-estimates the cost, of idea-creation. I don't just write some code, I create an idea, and then I write a bit of code as implementation details for it. This is a very tantalizing vision of development: all messy details are hidden away, what we're left with is a beautiful constellation of ideas in their purest form.
The problem is that when someone else has to try and make sense of your code, they first have to internalize all of your ideas, instead of just reading the code itself which may be calling out to something they already understand. It is the opposite of self-documenting code: it's code that requires its own glossary in addition to the usual documentation. "wayTooCold()" may read more naturally to the person who wrote it, but there's a fallacy where they assume that that also applies to other minds that come along and read it later.
Establishing a whole new concept with its own terminology in your code is costly. It has to be done with great care and only when absolutely necessary, and then documented thoroughly. I think as an industry we have more awareness of this nowadays. We don't just make UML diagrams and kick them across the fence for all those mundane "implementation details" to be written.
[+] [-] cush|4 years ago|reply
[+] [-] ziml77|4 years ago|reply
It's been years since I've read the book and I'm still having trouble with the bad ideas from there because they're so well stuck with me that I feel like I'm doing things wrong if I don't follow the guidelines in there. Sometimes I'll actually write something in a sensible way, change it to the Clean Code way, and then revert it back to where it was when I realize my own code is confusing me when written like that.
This isn't just a Robert C Martin issue. It's a cultural issue. People need to stop shaming others if their code doesn't align with Clean Code. People need to stop preaching from the book.
[+] [-] lamontcg|4 years ago|reply
The author seems like they took a set of rules that are good for breaking beginning programmers bad habits and then applied them into the extreme. There's a whole lot of rules which aren't bad up until you try to apply them like laws of gravity that must always be followed. Breaking up big clunky methods that do way too much is great for readability, right up until you're spraying one line helper methods all over your classes and making them harder to read because now you're inventing your own domain specific language everyone has to learn (often with the wrong abstractions which get extended through the years and wind up needing a massive refactoring down the road which would have been simpler with fewer methods and abstractions involved at the start).
A whole lot of my job is taking classes, un-DRY'ing them completely so there's duplication all over the place, then extracting the right (or at least more correct) abstractions to make the whole thing simple and readable and tight.
[+] [-] incrudible|4 years ago|reply
Realize that your whole program is effectively one big function and you achieve nothing by scattering its guts out into individual sub-functions just to make the pieces smaller.
If something is too convoluted and does too much, or has too much redundancy, you'll know, because it'll cause problems. It'll bother you. You shouldn't pre-empt this case by just writing small functions by default. That'll just cause its own problems.
[+] [-] ItsMonkk|4 years ago|reply
Using Martin's suggestion with Functional Hexagonal Architecture would lead to beautiful code. I know because that's what I've been writing for the past 3 years.
[+] [-] golergka|4 years ago|reply
[+] [-] hyko|4 years ago|reply
I get the impression that it’s about the messengers and not the messages, and that people have had horrible learning experiences that have calcified into resistance to do with anything clean. But valuable insights are being lost, and they will have to be re-learned in a new guise at a later date.
[+] [-] Communitivity|4 years ago|reply
I've found the Clean Code guidelines very useful. Your team's mileage may very. As always: Use what works, toss the rest, give back where you can.
For more about this see:
* Bob Martin's blog post 'Too Clean' - https://blog.cleancoder.com/uncle-bob/2018/08/13/TooClean.ht...
* Livable Code by Sarah Mei - https://www.youtube.com/watch?v=8_UoDmJi7U8
[+] [-] flipgimble|4 years ago|reply
I've seen so many real world counter-examples to arguments made in that article and his other blog posts that I'm puzzled why this guy has such a large and devoted following.
[+] [-] wildermuthn|4 years ago|reply
His point is that you can’t practically force programmers to be diligent through safety features of a language itself, since edge-cases require escape hatches from those safety features, and those safety hatches will be exploited by our natural tendency to avoid “punishment”.
I’m not sure I agree with his point, but I don’t find it an unreasonable position. I’d be curious if Rust has escape hatches that are easily and often abused.
My favorite example here, and a counterpoint to Bob, is Reacts’s dangerously-unsafe-html attribute. I haven’t seen it in years (to the point where I can’t recall the exact naming), and perhaps it was removed at some point. But it made the escape hatch really painful to use. And so the pain of using the escape hatch made it less painful to actually write React in the right manner. Coming from Angular, I think I struggled at first with thinking I had to write some dangerous html, but over time I forgot the choice of writing poor React code even existed.
So I guess I disagree with Bob’s post here. It is possible to have safety features in languages that are less painful than the escape-hatches from those safety features. And no suite of tests will ever be as powerful as those built-in safety features.