zbentley 6 hours ago

It's striking to me how out of touch Martin seems to be with the realities of software engineering in this transcript. Stylistic refactors that induce performance regressions, extremely long and tortured method names for three-line methods, near-total animus towards comments ... regardless of who is right/wrong about what, those takes seem like sophomoric extremism at its worst, not reasoned pragmatism that can be applied to software development in the large.

When I encounter an Uncle Bob devotee, I'm nearly always disappointed with the sheer rigidity of their approach: everything must be reduced thus, into these kind of pieces, because it is Objectively Better software design, period. Sure, standard default approaches and best practices are important things to keep in mind, but the amount of dogma displayed by folks who like Martin is really shocking and concerning.

I worry that his approach allows a certain kind of programmer to focus on like ... aesthetic, dogmatic uniformity (and the associated unproductivity of making primarily aesthetically-motivated, dogmatic changes rather than enhancements, bugfixes, or things that other coders on a project agree improves maintainability) instead of increasing their skills and familiarity with their craft.

Maintainability/appropriate factoring are subjective qualities that depend a lot on the project, the other programmers on it, and the expectations around how software engineering is done in that environment.

Pretending that's not true--that a uniform "one clean code style to rule them all" is a viable approach--does everyone involved a disservice. Seasoned engineers trying to corral complexity, new engineers in search of direction and rigor, customers waiting for engineering to ship a feature, business stakeholders confused as to why three sprints have gone by with "refactor into smaller methods" being the only deliverable--everyone.

  • jbm 40 minutes ago

    The Uncle Bob thing is something I'm experiencing right now.

    I hired a friend who was a huge Uncle Bob mark, and he kept trying to flex his knowledge during interviews with other people in the company. I didn't really think much of it and told the other interviewer that it was just his personal quirk and not to worry much.

    I had him work with some junior devs on a project while I took care of something more urgent. After finishing it, I went over to take a look at how it was going on his end. I was horrified at the unnecessary use of indirection; 4 or 5 levels in order to do something simple (like a database call). Worse, he had juniors build entire classes as an interface with a database class that was "wrong".

    No practical work was done, and I've spent the past 4 weeks building the real project, while tossing out the unnecessary junk.

    I liked Clean Code when I read it, but I always assumed a lot of it was meant for a specific language at a specific time. If you are using it verbatim for a Python project in 2025, why?

    • randomNumber7 34 minutes ago

      I don't see how it is uncle Bob's fault that your friend misunderstood his book.

      • jbm 26 minutes ago

        Judging from this thread, it seems like a lot of people have similar issues with UB's work.

  • overgard 3 hours ago

    I haven't seen a lot of evidence that Martin really has the coding chops to speak as authoritatively as he does. I think when you become famous for giving advice or being an "expert", it can be difficult to humble yourself enough to learn new things. I know personally I've said a lot of dumb things about coding in the past; luckily none of those things were codified into a "classic" book.

    What strikes me about the advice in Clean Code is that the ideas are, at best, generally unproven (IE just Martin's opinion), and at worst, justify bad habits. Saying "I don't need to comment my code, my code speaks for itself" is alluring, but rarely true (and the best function names can't tell you WHY a function/module is the way it is.) Chopping up functions and moving things around looks and feels like work, except nothing gets done, and frankly often strikes me as being the coding equivalent of fidget spinners (although at least fidget spinners dont screw up your history). Whenever Martin is challenged on these things he just says to use "good judgement", but the code and advice is supposed to demonstrate good judgement and mostly it does not.

    Personally I wish people would just forget about Clean Code. You're better off avoiding it or treating it as an example of things not to do.

    • CSMastermind 3 hours ago

      I watched some talks he gave 15 years ago and what struck me was that he would use analogies to things like physics that were just objectively incorrect. He was confidently talking about a subject he clearly didn't understand at even an undergraduate level.

      Then for the rest of the talk he would speak just as confidently about coding. Why would I believe anything he has to say when his confidence is clearly not correlated to how well he understand the material?

  • valenterry 4 hours ago

    > It's striking to me how out of touch Martin seems to be with the realities of software engineering in this transcript

    It was always like that. And Fowler the same thing with his criticism of anemic domain model. But software-engineering is no exceptions to having a mass of people believing someone without thinking by themselves.

    • motorest 2 hours ago

      > It was always like that. And Fowler the same thing with his criticism of anemic domain model.

      What leads you to disagree with the fact that anemic domain models are an anti-pattern?

      https://martinfowler.com/bliki/AnemicDomainModel.html

      I think it's obvious that his critique makes sense if you actually take a moment to try learn and understand what he says and where he comes from. Take a moment to understand what case he makes: it's not object-oriented programming. That's it.

      See,in a anemic domain model, instead of objects you have DTOs that are fed into functions. That violates basic tenners of OO programming. It's either straight up procedural programming or, if you squint hard enough, functional programming. If you focus on OO as a goal, it's clearly an anti-pattern.

      His main argument is summarized in the following sentence:

      > In essence the problem with anemic domain models is that they incur all of the costs of a domain model, without yielding any of the benefits.

      Do you actually argue against it?

      Listen, people like Fowler and Uncle Bob advocate for specific styles. This means they have to adopt a rethoric style which focuses on stressing the virtues of a style and underlining the problems solved by the style and created by not following the style. That's perfectly fine. It's also fine if you don't follow something with a religious fervor. If you have a different taste, does it mean anyone who disagrees with you is wrong?

      What's not cool is criticizing someone out of ignorance and laziness, and talking down on someone or something just because you feel that's how your personal taste is valued.

      • overgard an hour ago

        "It's not object oriented programming" is only a good case to make if you think object oriented programming is synonomous with good. I don't think that's true. It's sometimes good, often not good.

        Why would focusing on OO be a goal? The goal is to write good software that can be easily maintained. Nobody outside of book writers are shipping UML charts

        • rester324 20 minutes ago

          Why would you not focus on writing OO code in an OO language for example? Would you start writing OO code in a functional langugage? No you wouldn't, because it would be pointless. There are programming paradigms for a reason

  • the__alchemist 5 hours ago

    I'm not familiar with the Clean Code book etc; my introduction is the article. UB seems to be advocating consistently for patterns that are not my cup of tea! For example: Functions sometimes make sense as 2-3 lines. Often 5-20. Less often, but not rarely, much more than that!

    I'm also a fan of detailed doc comments on every module and function, and many fields/variants as well. And, anything that needs special note, is unintuitive, denotes units or a source etc.

    • milesrout 4 hours ago

      Function length also depends on language. Every line of one language requires three line in another if the former has implicit error handling and the latter explicit. But I find the cognitive load of the two to be similar.

      I am also okay with 1000 line functions where appropriate. Making me jump around the code instead of reading one line at a time, in a straight line? No thanks!

    • waynesonfire an hour ago

      The issue that of function length is irrelevant and incidental. Keep paying attention to what UB is saying.

  • motorest 33 minutes ago

    > It's striking to me how out of touch Martin seems to be with the realities of software engineering in this transcript. Stylistic refactors that induce performance regressions, extremely long and tortured method names for three-line methods, near-total animus towards comments ... regardless of who is right/wrong about what, those takes seem like sophomoric extremism at its worst, not reasoned pragmatism that can be applied to software development in the large.

    I think you're talking out of ignorance. Let's take a moment to actually think about the arguments that Uncle Bob makes in his Clean Code book.

    He argues in favor of optimizing your code for clarity and readability. The main goal of code is to help a programmer understand it and modify it easily and efficiently. What machines do with it is of lower priority. Why? Because a programmer's time is far more expensive than any infrastructure cost.

    How do you make code clear and easy to read? Uncle Bob offers his advise. Have method names that tell you what they do, so that programmers can easily reason about the code without having to even check what the function does. Extract low-level code to higher level methods so that a function call describes what it does at the same level of detail. Comments is a self-admission you failed to write readable code, and you can fix your failure by refactoring code into self-descriptive member functions.

    Overall, it's an optimization problem where the single objective is defined as readability. Consequently, it's obvious that performance regressions are acceptable.

    Do you actually have any complain about it? If you read what you wrote, you'll notice you say nothing specific or concrete: you only throw blanket ad hominems that sound very spiteful, but are void of any substance.

    What's the point of that?

    > Maintainability/appropriate factoring are subjective qualities that depend a lot on the project, the other programmers on it, and the expectations around how software engineering is done in that environment.

    The problem with your blend of arguments is that guy's like you are very keen on whining and criticizing others for the opinions they express, but when lightly pressed on the subject you show that you actually have nothing to offer in the way of alternative or guideline or anything at all. Your argument boils down to "you guys have a style which you follow consistently, but I think I have a style as well and somehow I believe my taste, which I can't even specify, should prevail". It's fine tha you have opinions, but why are you criticizing others for having them?

    • Mossy9 16 minutes ago

      > Comments is a self-admission you failed to write readable code, and you can fix your failure by refactoring code into self-descriptive member functions

      This may be true for some cases, but I don't see a non-contrived way for code to describe why it was written in the way it does or why the feature is implemented the way it is. If all comments are bad, then this kind of documentation needs to be written somewhere else, where it will be disconnected from the implementation and most probably forgotten

  • hakunin 5 hours ago

    Another example of not quite pragmatic advice is Screaming Architecture. If you take some time to think about it, it’s actually not a good idea. One of the blog posts I’m working on is a counter argument to it.

    • edwardsdl an hour ago

      I’d love for you to expand on this!

  • aprilthird2021 5 hours ago

    I read Clean Code when I started out my career and I think it was helpful for a time when I worked on a small team and we didn't really have any standards or care about maintainability but were getting to the point where it started mattering.

    Sure, dogmatism is never perfect, but when you have nothing, a dogmatic teacher can put you in a good place to start from. I admired that he stuck to his guns and proved that the rules he laid out in clean code worked to make code more readable in lots of situations.

    I don't know anything about him as a person. I never read his other books, but I got a lot out of that book. You can get a lot out of something without becoming a devotee to it.

    EDIT: I think even UB will agree with me that his dogmatism was meant as an attitude, something strong to hit back against a strong lack of rigidity or care about readable code, vs a literal prescription that must be followed. See his comment here:

    > Back in 2008 my concern was breaking the habit of the very large functions that were common in those early days of the web. I have been more balanced in the 2d ed.

    And maybe I was lucky, but my coding life lined up pretty neatly with the time I read Clean Code. It was an aha moment for me and many others. For people who had already read about writing readable code, I'm sure this book didn't do much for them.

  • frozenlettuce 6 hours ago

    I don't know why people take UB seriously. He never provided proof of any work experience - he claims to have worked for just a single company that... never shipped any code into production. Even his code examples on GitHub are just snippets, not even a to-do app (well, I think that his style of "just one thing per function" works as a self-fulfilling prophecy).

    Maybe people like him are the reason why we have to do leet code tests (I don't believe he would be capable of solving even an easy problem).

    • rester324 5 hours ago

      Uncle Bob is one of the core contributors to Fitnesse, which had moderate success in the Java popularity era back in the day.

      Also, you do understand that people worked as software engineers even before Github became popular, or open sourcing to begin with, do you? So if someone is 60+ year old, chances are that most of his work has never been open sourced, and his work was targeting use cases, platforms, services which have no utility in this age any more.

      Which have all nothing to do with how good a software engineer someone is.

      And finally, do you have any proof that he never shipped any code into production?

      • imjonse an hour ago

        > So if someone is 60+ year old, chances are that most of his work has never been open sourced,

        John Ousterhout is 70 years old and one of the open source pioneers. We don't know what Uncle Bob shipped or did not ship but his friendly opponent in this discussion definitley did ship high profile projects.

      • zabzonk 4 hours ago

        > So if someone is 60+ year old, chances are that most of his work has never been open source

        Somewhat ageist? I'm 72 and have produced a number of FOSS tools.

        • sebmellen 3 hours ago

          Truly. I know plenty of people in their 60s and 70s who use Git and are still very sharp programmers.

      • fourside 4 hours ago

        The criticism was that UB worked at a company that allegedly didn’t ship code to production, not that he doesn’t have a corpus of open source projects on GitHub.

  • NomDePlum 5 hours ago

    I'm going to have to admit to never having read Clean Code. It's just never appealed to me. I did read some of UBs articles a fair number of years ago. They did make me think - which I'd say is a positive and along the lines you are putting forwards.

    Rigidity and "religious" zeal in software development is just not helpful I'd agree.

    I do however love consistency in a codebase, a point discussed in "Philosophy of Software Design", I always boil this down to, even if I'm doing something wrong, or suboptimal, if I do it consistently, once I realise, or it matters I only have one thing to change to get the benefit.

    It's the not being able to change regardless, in the face of evidence, that separates consistency and rigidity (I hope)!

  • hansvm 4 hours ago

    > sheer rigidity

    That looks more like a communication style difference than anything else. Uncle Bob's talks and writing are prescriptive -- which is a style literally beaten into me back when I was in grade school, since it's implied just from the fact that it's you doing the speaking that you're only describing your opinions and that any additional hedging language weakens your position further than you actually intend.

    If you listen to him in interviews and other contexts where he's explicitly asked about dogmatism as a whole or on this or that concept, he's very open to pragmatism and rarely needs much convincing in the face of even halfway decent examples.

    > animus toward comments

    Speaking as someone happy to drop mini-novels into the tricky parts of my code, I'll pick on this animus as directionally correct advice (so long as the engineer employing that advice is open to pragmatism).

    For a recent $WORK example, I was writing some parsing code and had a `populate` method to generate an object/struct/POCO/POJO/dataclass/whatever-it-is-in-your-language, and as it grew in length I started writing some comments describing the sections, which for simplicity's sake we'll just say were "populate at just this level" and "recurse."

    If you take that animus toward comments literally, you'll simply look at those comments and say they have to be removed. I try to be pragmatic, and I took it as an opportunity to check if there was some way to make the code more self-evident. As luck would have it, simply breaking that initial section into a `populate_no_recurse` method created exactly the documentation I was looking for and also wound up being helpful as a meaningful name for an action I actually wanted to perform in a few places.

    That particular pattern (breaking a long method into a sequence of named intermediate parts) has failure modes, especially in the hot path in poorly optimized runtimes (C#, Java, ..., Python, ...), and definitely in future readability if employed indiscriminately, but I have more than enough experience to be confident it was a good choice here. The presence in my mind of some of Uncle Bob's directionally correct advice coloured how I thought about my partial solution and made it better.

    > other animus

    - Stylistic refactors that induce performance regressions can be worth it. As humans, we're pre-disposed to risk avoidance, so let's look at an opposite action with an opposite effect: How often are you willing to slow down feature velocity AND make the code harder to maintain just to squeeze out some performance (for a concrete example, suppose there's some operation with space/time/bandwidth tradeoffs which imply you should have a nasty recursive cte in your database to compute something like popcount on billion-bit-masks, or even better just rewrite that portion of the storage layer)? My job is 80% making shit faster and 10% teaching other people how to make shit faster, but there are only so many hours in the day. I absolutely still trade performance for code velocity and stability from time to time, and for all of those fledgeling startups with <1M QPS they should probably be making that trade more than I do (assuming it's an actual trade and not just an excuse for deploying garbage to prod).

    - The "tortured method names" problem is the one I'm most on the fence about. Certainly you shouldn't torture a long name out of the ether if it doesn't fit well enough to actually give you the benefits of long names (knowing what it does from its name, searchability), but what about long names which do fit? For large enough codebases I think long names are still worth the other costs. It's invaluable to be able to go from some buggy HTML on some specific Android device straight to the one line in a billion creating the bug, especially after a couple hiring/firing sessions and not having anybody left who knows exactly how that subsystem works. I think that cutover point is pretty high though. In the 100k-1M lines range there just aren't enough similar concepts for searchability to benefit much from truly unique names, so the only real benefit is knowing what a thing does just from its name. The cost for long names is in information density, and when it's clear from context (and probably a comment or three) I'm fine writing a numeric routine with single-letter variable names, since to do otherwise would risk masking the real logic and preventing the pattern-recognition part of your brain from being able to help with matters. HOWEVER, names which properly tell you what a thing does are still helpful (the difference between calling `.resetRetainingCapacity()` and `.reset()` -- the latter you still have to check the source to see if it's the method you want, slowing down development if you're not intimately familiar with that data structure). I still handle this piece of advice on a case-by-case basis, and I won't necessarily agree with my past self from yesterday.

    > "Uncle Bob devotees" vs "Uncle Bob"

    This is maybe the core of your complaint? I _have_ met a lot of people who like his advice and aren't very pragmatic with it. Most IME are early-career and just trying to figure out how to go from "I can code" to "I can code well," and can therefore be coached if you have well-reasoned counter-examples. Most of the rest IME like Uncle Bob's advice but don't code much, and so their opinions are about as valuable as any other uninformed opinion, and I'm not sure I'd waste too much time lamenting that misinformation. For the rest of the rest? I don't have a large enough sample I've interacted with to be very helpful, but unrelenting dogmatism is pretty bad, and people like that certainly exist.

sudobash1 6 hours ago

There is an important case for comments that neither of them touched on. Sometimes you are dealing with bugs or counterintuitive processes beyond your control.

For example, I am writing some driver software for a USB device right now. It is so easy to get the device into a bad state, even when staying within the documented protocol. Every time I implement a workaround, or figure out exactly how the device expects a message to appear, I put in a comment to document it. Otherwise, when (inevitably) the code needs to have features added, or refactoring, I will completely forget why I wrote it that way.

The prime number example is a self-contained, deterministic algorithm. While I did find it far easier to parse with comments, I could still spend the time to understand it without them. In my USB device driver, no amount of review without comments would tell another person why I wrote the sequence of commands a certain way, or what timings are important.

The only way around that would be with stupid method names like `requestSerialNumberButDontCallThisAfterSettingDisplayData` or `sendDisplayDataButDontCallTwiceWithin100Ms`.

  • zbentley 5 hours ago

    > The only way around that would be with stupid method names

    Yep. Method names make terrible comments. No spaces, hard to visually parse, and that's before acronyms and ambiguity enter the conversation.

    As the person who often writes borderline-essay-length comment blocks explaining particularly spooky behaviors or things to keep in mind when dealing with a piece of counterintuitive/sensitive/scary code, my reason for mega-commenting is even simpler: all the stuff I put in comments should absolutely instead live in adjacent documentation (or ADRs, troubleshooting logs, runbooks, etc). When I put it in those places, people do not read it, and then they do the wrong things with the code. When I put it in comments, they read it, as evidenced by the rate of "that bug caused by updating the scary code in the wrong way happened again"-type events dropping to zero. It's easier to fix comment blocks than it is to fix engineers.

    • rswail 2 hours ago

      > Yep. Method names make terrible comments. No spaces, hard to visually parse, and that's before acronyms and ambiguity enter the conversation.

      Which is why snake_case or kebab-case (if the language allows it) is much better than PascalCase or camelCase.

      Even worse when camelCase enters into JSON because people want to automate the serde but are too lazy to make the actual interface (the JSON Schema) easy to read and debug.

  • slotrans 3 hours ago

    > I will completely forget why I wrote it that way.

    This is the main reason for comments. The code can never tell you "why".

    Code is inherently about "what" and "how". The "why" must be expressed in prose.

  • mbo 6 hours ago

    While I am not a Uncle Bob-style "no comments"er I do love a ridiculous method name. I pay very close attention to that method and the context in which it is called because, well, it must be doing something very weird to deserve a name length like that.

    • hakunin 4 hours ago

      That’s exactly why you should save that length only for a method that’s indeed doing something weird. If every method is long, the codebase turns into noise. (IOW I agree)

    • tikhonj 5 hours ago

      There are a few Haskell functions with names like reallyUnsafePtrEquality# or accursedUnutterablePerformIO, and you know something interesting is going on :P

  • Mawr 3 hours ago

    Sounds like you should instead be making these invalid states unrepresentable by encoding them in types and/or adding assertions. Especially if you're exposing them as interfaces, as your example function names would imply.

marcusbuffett 6 hours ago

I strongly recommend "A Philosophy of Software Design". It basically boils down to measuring the quality of an abstraction by the ratio of the complexity it contains vs the complexity of the interface. Or at least, that's the rule of thumb I came away with, and it's incredible how far that heuristic takes you. I'm constantly thinking about my software design in these terms now, and it's hugely helpful.

I didn't feel like my code became better or easier to maintain, after reading other programming advice books, including "Clean Code".

A distant second recommendation is Programming Pearls, which had some gems in it.

  • narnarpapadaddy 4 hours ago

    Implicitly, IIRC, the optimal ratio is 5-20:1. Your interface must cover 5-20 cases for it have value. Any fewer, the additional abstraction is unneeded complexity. Any more, and your abstraction is likely too broad to be useful/understandable. The example he gives specifically was considering the number of subclasses in a hierarchy.

    It’s like a secret unlock code for domain modeling. Or deciding how long functions should be (5-20 lines, with exceptions).

    I agree, hugely usual principle.

ctrlp 4 hours ago

I've enjoyed both books but Uncle Bob is something you grow out of. He was a bit of a cult figure at the time. Trying to actually follow the guidelines in Clean Code taught me a lot about "over-decomposition" and, ultimately, how not to write code. It reminds me it's possible to take aesthetics so far the results become ugly. Fussing over a proliferation of small functions that do only one thing is a kind of madness. Each individual function eventually does zero things. You are left sifting through the ashes of your program wondering "Where did I go wrong?"

On the meta level, these exchanges, while mildly interesting, have the vibe of debating how many angels can dance on the head of a pin. I'm reminded of the old saying: "Writing about music is like dancing about architecture." If you want to write good code, read good code. Develop a taste that makes sense to you. I don't think I'll ever read a book about code composition again.

  • Willingham 4 hours ago

    > If you want to write good code, read good code.

    As a junior in the field working at a small company, I often rely on this community for guidance, and this seems the most sound advice on this thread.

    • acmj 4 hours ago

      You need to know what is good code. Opinions may vary a lot between programmers, even senior ones. The Clean Code cult would tell you to find good code there but that is the most poisonous programming book I have read.

      • ctrlp 3 hours ago

        there are lots of very robust programs in various languages to learn from. It would be hard to know in isolation but by contrast it is easier to learn what good code looks like. Some code will flow and be easy to read. Other code will be obtuse. Start with simpler projects that don't involve a lot of low-level calls. Work up to more complex implementations. There was never a better time to read code than now with an LLM as a tutor. If you use one of the AI-integrated editors or a code packer you can provide a lot of context to the LLM. Ask the LLM for important modules and work your way through them. Ask it for alternative implementations of a function or translated into a different language. Set up an program in a running environment and walk through using a debugger. Look at the way the code is organized in files and modules. You will inevitably encounter cruft and "bad code". Sometimes there are good reasons for that too. If you prefer books, the Architectures of Open Source Applications (AOSA) books are interesting, but there really isn't a way to avoid pulling down a repo and reading the code. Soon, you'll develop your own taste for what makes sense to you and be able to think independently about the choices the developer made.

        It is a bit sad but I think with the advent of LLMs some of the stylistic quirks of programmers past will become a bit anachronistic. Still, they will present opportunities for code archeology.

    • rswail 2 hours ago

      Agreed.

      Some other heuristics:

      * Every if statement is a chance of a bug because the code has two or more paths to follow. Keep the choice making at the business/requirements level of the code, not hidden inside lower level decomposition.

      * A switch statement that is not exhaustive (ie covers all possible values) is a change of a bug, especially if there is no default case.

      Modern languages with better type systems make the second point less relevant because they require exhaustive pattern matching.

getnormality 6 hours ago

Uncle Bob's insistence that functions should be 2-4 lines long is baffling to me. I don't understand how he can be taken seriously. Is there a single application in the entire world with substantial functionality that conforms to this rule?

  • PlunderBunny 5 hours ago

    I've seen this in what I call 'lasagna code' - multiple thin layers that seem to do nothing (or almost nothing) but each one is an implementation of some abstruse interface that exists in the mind of the original developer.

    Eventually, your code has to do something. Get that thing in one place where you can look at it in its whole.

  • Scubabear68 5 hours ago

    There are. A lot of Java code bases look like this.

    It is all as bad as you imagine. Functionality is spread out all of the place so it is very difficult to reason about how it all hangs together.

    • MobiusHorizons 5 hours ago

      I once fully spelunked such a Java call stack to convert some code to golang. It was amazing, there were like 5 layers of indirection over some code that actually did what I want, but I had to fully trace it keeping arguments from the full call stack in mind to figure this out, because several of the layers of indirection had the potential of doing substantially more work with much more complex dependency graphs. I ended up with a single go file with two functions (one that reproduced the actually interesting Java code and one that called it the way it would have been called across all the layers of indirection. It was less than 100 lines and _much_ easier to understand.

    • nyarlathotep_ 5 hours ago

      It's always fun stepping through 412 stack frames that are all 2-line long methods to figure out where the thing you're interested in actually happened.

    • monksy 4 hours ago

      Add in Go and C++ code bases to that as well.

  • monksy 4 hours ago

    This is something that's easier to read than it is to understand. A lot of languages force you to do quite a lot in a function and becoming blind to bloat is way to easy to do. (C++/Go/Java/etc yep).

    He did an example in the article of:

    void concurrentOperation() { lock() criticalSection(); unlock() }

    So if you subsitute criticalSection with a lot of operations, such as open file, read lines, find something, close file. I think you have a better representation of an over bloated function.

    Scala has the langauge support to show what this could look like.

    What you're doing in that method is starting a critical section, doing something, and then ending a critical section. It's a good suggestion to break that with:

    def criticalSection(f: () => Unit) { lock() f() unlock() }

    How you have a single method that does one thing and is easy to understand. Also it's reusable.

    The original code would be used as:

    criticalSection { _ => doSomething() }

    That replacement is now longer dependent on locking. Locking is layered in.

  • WalterBright 4 hours ago

    Too often I see functions that are shells that reshuffle the arguments and pass them to another function, which also reshuffles the arguments and forwards them to another, and on and on. One was 11 layers deep.

  • dionian 3 hours ago

    Like with a lot of his approach, its great for teaching people better coding skills in an educational setting, but doesn't make as much sense in the real world.

seanwilson 3 hours ago

I find the lack of discussion of type systems really surprising in these sorts of discussions and books. Effective use of type systems is a killer factor for me for creating clean, safe, readable and maintainable software designs.

When used correctly, strong static type checking make certain kinds of bugs impossible, spare you from writing many kinds of tedious tests that often get in the way of refactoring, serve as documentation, and make refactoring/maintenance an order of magnitude faster and safer. Even when a type checker isn't available, avoiding dynamic behaviour is very often the safer way to go so learning how to think in that way is still beneficial.

Most of these minor topics like how big a function should be, what to name your variables, or even if you write tests before/after coding... it's like trying to come up with general rules on how to write essays, creating graphic designs, or how to cook. "It depends" on the context and juggling different priorities each time. It's the kind of thing you only learn properly through practice (https://en.wikipedia.org/wiki/Tacit_knowledge), so there's only so much to gain in reading about it or discussing it after you've defined the no-brainer things to always do and always avoid.

  • WillAdams 2 hours ago

    That was exactly the approach taken by Prof. Ousterhout in setting up the class which lead to this book --- rather than just having students turn in working code for a grade, the code is reviewed with the student and the student then works to make it better --- in turn, the 2nd edition of the book was informed by the experience of teaching the class and the author actually changed his position based on the experience gained.

nickm12 an hour ago

This was a fun read. I read APoSD for the first time a couple of months ago and found myself nodding enthusiastically as I read. I have a few quibbles, of course, but overall it matches my experience in how to write software that is correct, maintainable, extensible, and understandable.

I've never read CC, but I've read some of the take downs[1]. I was worried that the take downs were attacking a strawman, but no, Uncle Bob believes this stuff, including that comments are evil and you just need to read all the code and keep it in your head.

Even if that were true, the code I write is better for having written the comments, especially interface comments, because the writing helps my thinking. Moreover, it helps my code reviewers—without written interfaces. If all you have is the code and not a description of what the code is supposed to do, how can you know if it is correct? I think most code reviewers are verifying the code against what they infer the interface to be. It helps us both to just be explicit.

[1]: https://qntm.org/clean

ilrwbwrkhv 6 hours ago

john ousterhout's book is the only book on how to write software that has any actual evidence behind it. i highly recommend it as the only book to read on how to write code. and uncle bob, well, best to avoid his stuff as much as possible. clean code takes away about 5 years from every dev's life as they think they need to read it to become an intermediate developer and one they realize that is not the way, can they finally grow.

  • ziml77 6 hours ago

    That book really poisons the mind. Even if there's some good things to learn in there, it's stashed among a lot of advice that is either plain bad or needs asterisks. But there aren't really any asterisks and instead it presents what look like rules that you shouldn't be breaking if you want to be a good programmer.

    When I first read the book I'd already been programming for 10 years, but I was in my first job out of college. I'd heard a lot about the book and so I trusted what it had to say. I let it override how I would have written code because I figured coding professionally was just far different than what I would consider the best way to write code.

    Interestingly, 5 years sounds about right for how long it took me to finally start trusting my own judgement. I think it was a combination of being more confident in myself but also because I was doing larger projects and it was more frequent that I was putting down a project and then coming back a couple months later. That's how I was able to see how bad the code was to work with once my mental model of it had flittered away.

    Now I take a much less strict approach to my code and I find it a lot better to work with later.

    • MobiusHorizons 5 hours ago

      > instead it presents what look like rules that you shouldn't be breaking if you want to be a good programmer.

      I see this a lot, especially among more junior programmers. I think it likely stems from insecurity with taking responsibility for making decisions that could be wrong. It makes sense, but I can’t help but feel it is failing to take responsibility for the decisions that are the job of engineering. Engineering is ultimately about choosing the appropriate tradeoffs for a specific situation. If there was a universally “best” solution or easy rule to follow, they wouldn’t need any engineers.

      • runevault 5 hours ago

        I always think of this as the programmer version of "No one got fired for choosing IBM." that was a common phrase about executives back in the day. Do the thing that you can just point to "experts" and blame them.

    • OnionBlender 5 hours ago

      Which book are you referring to? The parent comment mentioned two books.

      • ziml77 3 hours ago

        Clean Code

    • WalterBright 4 hours ago

      1. newbie follows the rules because he is told to

      2. master follows the rules because he understands them

      3. guru breaks the rules because they don't apply

  • chillpenguin 5 hours ago

    "john ousterhout's book is the only book on how to write software that has any actual evidence behind it."

    This is false and hopefully no one takes you seriously when they read that. There are books about empirical methods for software engineering, for example, which actually seek to find real evidence for software engineering techniques. See Greg Wilson's work, for example.

    There are lots of other architecture/design books that use real world systems as examples. "Evidence" is definitely lacking in our field, but you can find it if you try.

  • owl_vision 6 hours ago

    5 years is about right.

    when i found a copy of clean code in a bookstore, it only took me a few minutes to put it back. I had read John Ousterhout's book prior.

  • pinoy420 6 hours ago

    In typical HN commenter smugness. It took me less than that to realise it was bullshit. It didn’t make things clear, it made them more abstract and more resistive to change. Similarly with DDD. Just build what you need and deal with the consequences of inevitable change later. No one cares if you miraculously perfectly modelled your “definitely the final form” of your domain from day 0.

    Oh and TDD?! Ah yes those perfectly defined unit cases you write for implementation details. The best comment I read recently (sorry I can’t find it) something akin to “The first unit I write is to validate the intended side effects through properly exercising associated mocks”

    As with everything there is no “best way” to do something, but in software engineering… there are far more bad “best ways” than best “best ways”

    • rswail 2 hours ago

      DDD is a good way to extract the business logic from the implementation.

      By modelling the business you raise the business logic up to a 1st class element.

      By implementing the business objects you encapsulate their functionality in the business.

      The words "Account" or "Outstanding Balance" have business meanings. Modelling them allows you to express the business logic explicitly.

      It also allows you to create tests that are related to that business logic, not the implementation.

      You can still "build what you need and deal with the consequences of inevitable change later".

      Model what you need to build, the business is going to have to make changes to that model to implement their changes, IT systems are a detail.

      Change by extending and changing the DDD models.

      To reverse the question, how do you write code that "does what you need" without understanding the domain?

LunicLynx an hour ago

The example they use is irrelevant. A solved problem can be written how ever one likes.

Code that will change or can’t ever be considered final, is the real challenge.

Overly cutting code into methods makes code just rigid. This could be the point, I guess, but if you need to change the methods name in order to reflect the methods intent, than you just wrote the classic unhelpful comment of:

// check a is not null

if (a != 0) { … }

Overuse of comments has the same issue as overuse of methods.

Without rigor, comments and methods names will start to lie.

Because their content / name weren’t necessary to understand the code. And should just not exist in the first place.

overgard 2 hours ago

Bob's comments on... commenting.. are so bizarre that I can't help but think that he just refuses to concede the point rather than admit he might have been wrong about it. Like, the paranoia around incorrect/stale comments is fairly absurd, I've been coding for 20 years across many code bases, and I can't even recall a time when I've been significantly mislead by a comment which caused a significant waste of time. However, the amount of time I've wasted on unclear code that has zero comments is absolutely staggering. However, what really sealed the weirdness to me was his argument that this was somehow a good comment:

                                                                    X
                                                        1111111111111111111111111
           1111122222333334444455555666667777788888999990000011111222223333344444
       35791357913579135791357913579135791357913579135791357913579135791357913579
       !!! !! !! !  !!  ! !! !  !  !!  ! !!  ! !  !   ! !! !! !
     3 |||-||-||-||-||-||-||-||-||-||-||-||-||-||-||-||-||-||-||-||-||-
     5 |||||||||||-||||-||||-||||-||||-||||-||||-||||-||||-||||-||||-
     7 |||||||||||||||||||||||-||||||-||||||-||||||-||||||-||||||-||||||-
    11 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||-||||||||||-
    13 ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
    ...
    113||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
That's verbatim, I'm not unfairly clipping context away from it. Like, what the hell is that supposed to tell someone?! Wouldn't it just be easier to drop a link to the algorithm, or briefly explain the algorithm, or just give a name of the algorithm so someone can look it up? Instead he just talks about taking a bike ride to understand it and making a weird picture. He also has bizarre arguments that if something can't be expressed in a programming language, it's the fault of the programming language (what?!) and that code is more understandable than English. I really find it hard to believe that he thinks these are actually good arguments, I just get the impression he does not want to concede that he was wrong about this.
  • nvlled 28 minutes ago

    > I'm not unfairly clipping context away from it

    Yes you are, you didn't attach the surrounding code where this comment was found. That comment would make a lot of more sense even just with the function name.

WalterBright 4 hours ago

One method of commenting that has paid off for me the most was inserting links to:

1. the online documentation of the function being called

2. the instruction documentation for an instruction being generated, inserting

3. the issue that the code fixes

4. the specification of what the function is trying to implement

Then I fixed my text editor to enable click on those links.

  • WalterBright 4 hours ago

    I also fixed the disassembler to also add a clickable link to the instruction spec page for each instruction.

imjonse an hour ago

I am biased ( a former coworker was an Uncle Bob fan, and was bent on doing everything by the book, with layers of abstraction, patterns, hexagonal architecture, lots of unit tests, no cutting corners, even as we did not know what exactly we want to build and needed an MVP ASAP) but I'll just say this: Ousterhout wrote TCL - widely considered one of the best C codebases - besides being a professor at Standford and having other software achievements under their belt, while Robert Martin is more like a software technology evangelist. The former good at actual deliverables the latter good at selling.

Also Ousterhout's book on design is very easy to read and I guess I liked it because I mostly just nodded in approval while reading and there were very few things that made me stop.

  • begueradj 10 minutes ago

    Let's not forget that Uncle Bob, by the time of writing "Clean Code" had 4 decades coding experience.

mkoubaa 6 hours ago

I can just tell that John Ousterhout works with much better developers on average than UB and that probably informs their biases.

  • Jach 5 hours ago

    He also works with a lot more students, with student-sized projects and problems and code lifetimes. He's used his book for classes, I think it's on a level appropriate for a freshman.

    Both books are bad, but APOSD is my most disliked technical book ever. CC is at least interesting as an exercise to see that critics are way too uncharitable. Kernighan and Pike's The Practice of Programming is far better than either. And https://antirez.com/news/124 is one of the few good discourses on comments out there, something as a profession we care way too much about when the cost of doing it "wrong" is typically so low.

    • WillAdams 3 hours ago

      While reading APoSD, one of my thoughts was that it walks up to, but never gets to the point of advocating for Literate Programming, and that resolving how the author feels about that presentation would make for a better and clearer text.

      Apparently, there is something of a tension at Stanford in that freshmen are being taught to keep methods/functions short, while the course on software design has as a pre-requisite CS140 which in turn requires CS 107 or EE 108B and CS107 requires CS106B, so it probably couldn't be taken until almost halfway through a four-year degree (and there is a note on the course page that preference will be given to those graduating in the near term).

      That said, there is value in laying out basic principles and premises, _and_ the experiences which in turn support them. Reading through your link, it seems to line up well with my understanding of recommendations for comments in APoSD, which makes one wonder how it could be made to work as a text for an introductory course in some language which was approachable by beginners.

    • tikhonj 5 hours ago

      What's there to dislike so much in APOSD?

      The book struck me as giving mostly reasonable advice, none is which was overly prescriptive. None of the things I disagreed with struck me as egregious.

      • Jach 5 hours ago

        Here's mostly from what I wrote down after reading it. Indeed, the "reasonableness" is part of the problem.

        What's agreeable is mostly only so because it's such a straightforward platitude. "Things that are not important should be hidden, and the more of them the better. But when something is important, it must be exposed." Ok? Anyone want to argue to the contrary? This is not teaching or learning anything new or of value, it's not even inviting argument like CC makes it easy to do. I was also hoping that with the book being so short it would be concise, but alas, it's full of this sort of stuff. The single page summary of design principles at the end is similar. A few of them you could quibble about, but arguments would likely just be in fully understanding the meaning of the terminology and what background contexts are assumed. Much advice is dependent on context! Context is something not really called out much in this book. As one example there was only a very slight hint that the author is aware that writing for the code reader means a reader from a particular audience, often your co-workers, and that gives you certain affordances you wouldn't have for say random blogger.

        Elsewhere, not in the book, the author once wrote "The strong typing of object-oriented languages encourages narrowly defined packages that are hard to reuse. Each package requires objects of a specific type; if two packages are to work together, conversion code must be written to translate between the types required by the packages." This is actually a nuanced point and is good to discuss. The context of whether you have static types or dynamic types or a half-baked OOP system or a full-baked OOP system is very important context. But it seems a completely absent point of consideration from his "philosophy", even when you'd think it'd be appropriate to go over in the final chapter where he highlights OOP as a "trend".

        A lot of the author's rants seem to be snipes at Java. Fine, whatever, though Java has answers to the complaints. (Especially modern Java.)

        Lastly, and originally my first complaint because it's about the very beginning of the book (including the cover art), he's on shaky foundations with its definition of simplicity/complexity by conflating it with the subjective easy/hard. I was hoping for a post-Hickey (of Clojure/"Simple Made Easy" talk fame for anyone unaware) understanding that complexity is objective, but alas. It's not like Hickey invented that understanding, but in current year, I think it's quite questionable to disagree. So, the book: "For the purposes of this book ... complexity is anything related to the structure of a software system that makes it hard to understand and modify the system." Sorry, that's not a useful definition of complexity, and now the whole book is harder to read/easier to misinterpret because of the custom definition. Well, at least it's explicit that it's custom.

namuol 5 hours ago

I’ve come full-circle back to my junior engineer attitude with respect to coding “best practices”: Avoid anything resembling dogma.

nickm12 21 minutes ago

buried at the end: there's a planned second edition of Clean Code! Given Bob's intransigence in this conversation, I wonder what he'll change.

hakunin 4 hours ago

For anyone like me who at first skipped over this article because it seems from the title that someone just compared two approaches:

No, it’s an actual debate between the actual John and Bob. Them debating each other. It’s an amazing read.

jillesvangurp 2 hours ago

They are both mostly right but the devil is in the details and to try to not get too dogmatic about things. For example function length is one of those things that you can obsess about and debate endlessly.

What's the value of extracting a function that is used only once or twice. It's probably very limited. It's debatable whether that even should be a public function and whether you should encourage more use. And then we can look at the function declaration as well. Does it have a lot of parameters? Is there any complexity to its implementation? Does it have tests? Are there going to be lot of uses of the function? If the answer to all those questions is no, you could probably inline it without losing much. But the flip side is that you wouldn't gain much by doing so. A small function that is used a lot is probably somewhat valuable.

And there's a third thing that needs to be considered: does a function increase the API surface of your module. Having lots of private functions makes your module hard to understand. Having lots of public functions, makes the API less cohesive.

So, there's a grey area here. Languages like Kotlin give you a additional options: make it a nested function, make it an extension function, put it in a Companion object, etc. You can put functions in functions and those can help readability. The whole point of doing that is preventing usage outside the context of the outer function. Nested functions should probably be very short. And their only goal should be to make the outer function logic more readable/understandable. It's not something I use a lot but I've found a few uses for this. There's no point to using nested functions other than for readability.

And speaking of Kotlin, it's standard library is full of very small extension functions. Most of them are one or two lines. They are clearly valuable because people use them all the time. You get such gems as fun List.isNullOrEmpty(): Boolean which helps make your if statements a lot more readable and less flaky. Also works on Java lists. Stuff like that is a big part of why I like Kotlin.

I tend to dumb down a lot of advice like both are debating here to cohesiveness and coupling. In the context of functions, you get coupling via parameters and side effects (e.g. modifying state via parameters) instead of return values. And you lose cohesiveness if a single function starts doing too many not so related things. High coupling and low cohesiveness usually means poor testability. You'll find yourself mocking parameters just to be able to test a function. Improving testability is a valid reason for extracting smaller, easier to test functions.

pjmlp an hour ago

All great, but generaly useless in most big corp project with offshoring, where we are already happy that we actually delivered something that works in first place.

htk 7 hours ago

What a great discussion between two prominent figures in the field of software design. Thank you for posting this!

dionian 3 hours ago

"That's a valid concern. However, it is tempered by the fact that the functions are presented in the order they are called. Thus we can expect that the reader has already seen the main loop and understands that candidate increases by two each iteration."

I think this missed the point entirely. If i had to read the entire code to understand the behavior of that method, then is it really cleaner? Side-effects are evil

khana 2 hours ago

[dead]