[HN Gopher] Clean Code vs. A Philosophy Of Software Design
___________________________________________________________________
Clean Code vs. A Philosophy Of Software Design
Author : recursivedoubts
Score : 424 points
Date : 2025-02-24 23:52 UTC (23 hours ago)
(HTM) web link (github.com)
(TXT) w3m dump (github.com)
| htk wrote:
| What a great discussion between two prominent figures in the
| field of software design. Thank you for posting this!
| htk wrote:
| You guys really hated that I found the discussion interesting?
| throw16180339 wrote:
| FWIW, me too comments are usually downvoted.
| htk wrote:
| Makes sense now, they don't add much, or anything. We
| already have the upvote button for this.
| kragen wrote:
| It seemed like a content-free comment. I was no better
| informed after reading it than before, and it was of no
| artistic or cultural value. It did not induce me to question
| any of my assumptions or investigate anything. It expressed
| your experience, but your experience was not unusual or
| surprising in any way, except perhaps that you did not know
| that "Uncle" Bob Martin was an incompetent charlatan.
| Possibly those were among the reasons people downvoted it.
| htk wrote:
| Fair points! Thank you.
| wglb wrote:
| Downvotes are a legitimate expression of disagreement, not
| hate.
| htk wrote:
| "Hate" was too strong of a word to use.
| ilrwbwrkhv wrote:
| 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.
| owl_vision wrote:
| 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 wrote:
| 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 wrote:
| 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?
| ziml77 wrote:
| 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 wrote:
| > 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 wrote:
| 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.
| MobiusHorizons wrote:
| That is a helpful comparison. I guess it is risk aversion
| at the core. At some point risk aversion becomes
| abdication of decision making to others, which seems
| broken in roles that are specifically hired for making
| decisions, but that's even more true of executives.
| runevault wrote:
| I completely agree with you, mind I feel the same way
| about the people who the original comment was talking
| about. They are paid the big bucks to decide how to spend
| money to optimize the company.
| OnionBlender wrote:
| Which book are you referring to? The parent comment mentioned
| two books.
| ziml77 wrote:
| Clean Code
| WalterBright wrote:
| 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
| Cthulhu_ wrote:
| There's a step between 1 and 2, someone who writes rules
| because he _believes_ he understands them.
|
| There was an era where every just-above-newbie PHP
| developer would start writing their own authoritative blog
| posts and frameworks, I strongly feel that had a big impact
| on the fragmentation and reputation of the PHP ecosystem as
| being insecure (because a lot of these authoritative blog
| posts demonstrated how to introduce SQL injection
| vulnerabilities)
| chillpenguin wrote:
| "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.
| recursivedoubts wrote:
| > no links
| froh wrote:
| Greg Wilson indeed is tremendously helpful in facilitating
| "the industry" to think about our craft:
|
| https://github.com/gvwilson
|
| edit: wow, in his project "It will never work in theory" he's
| fairly sober about the ability of "the industry" to reflect
| on "the craft"
|
| https://neverworkintheory.org/
|
| > about the project:
|
| > People have been building complex software for over sixty
| years, but until recently, only a handful of researchers had
| studied how it was actually done. Many people had opinions--
| often very strong ones--but most of these were based on
| personal anecdotes or the kind of "it's obvious" reasoning
| that led Aristotle to conclude that heavy objects fall faster
| than light ones.
|
| in the 2024 retrospective:
|
| > Conclusion
|
| > The comedian W.C. Fields once said, "If at first you don't
| succeed, try, try again. Then quit. There's no point in being
| a damn fool about it." Thirteen years after our first post,
| it is clear that our attempts to bridge the gulf between
| research and practice haven't worked. We look forward to
| hearing what actionable plans others have that will find real
| support from both communities.
| WillAdams wrote:
| The annals of the IEEE and ACM would argue against:
|
| >only a handful of researchers had studied how it was
| actually done
|
| I am pretty sure that there are more than 5 references to
| papers in APoSD.
| zbentley wrote:
| 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.
| frozenlettuce wrote:
| 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 wrote:
| 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?
| zabzonk wrote:
| > 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 wrote:
| Truly. I know plenty of people in their 60s and 70s who
| use Git and are still very sharp programmers.
| kragen wrote:
| Using Git is unrelated to whether the software you write
| is proprietary or open-source.
| fourside wrote:
| 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.
| imjonse wrote:
| > 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.
| ahoka wrote:
| Do you mean commits to the project like this crap: https://
| github.com/unclebob/fitnesse/commit/d6034080a04c740c...
|
| This level of pointless obfuscation would not survive a
| code review at any sane dev team.
| frozenlettuce wrote:
| It's the kind of commit that you get from someone that
| wants to look productive but is just renaming variables
| in their IDE.
| NomDePlum wrote:
| 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)!
| the__alchemist wrote:
| 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 wrote:
| 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 wrote:
| The issue that of function length is irrelevant and
| incidental. Keep paying attention to what UB is saying.
| the__alchemist wrote:
| I didn't get that impression from reading it. I also find
| the TDD approach discussed to be high inertia.
| hakunin wrote:
| 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 wrote:
| I'd love for you to expand on this!
| hakunin wrote:
| Short version: when designing new software, you don't have
| its architectural picture in the beginning. So when
| starting from scratch, the architecture shouldn't be
| screaming, but rather, it has to be non-committal/non-
| speculative to allow wiggle room for the future. (How to
| achieve non-committal architecture is the biggest topic I'm
| interested in, and I find 1 good tactic every few years).
| Specifically, the architecture should ephasize entry points
| and outputs. That's exactly what frameworks like Rails
| provide. You go by entry points until some sort of custom
| architecture starts emerging from the middle, which is when
| it can slowly begin "screaming" over time.
| aprilthird2021 wrote:
| 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.
| hansvm wrote:
| > 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.
| zbentley wrote:
| Thanks for the thoughtful response. I generally don't want to
| get into the _specifics_ of what Martin advocates for.
| Whether to prefer or eschew comments, give methods a
| particular kind of names, accept a performance penalty for a
| refactor--those are all things that are good or bad in
| context.
|
| I think a lot of engineers hear "there's a time and a place"
| or "in context" and assume that I'm saying that the approach
| to coding can or should differ between _every contribution_
| to a codebase. Not so! It 's very important to have default
| approaches to things like comments, method length, coupling,
| naming, etc. The default approach that makes the most sense
| is, however, bounded by _context_ , not Famous Author's One
| True Gospel Truth (or, in many cases, Change-Averse Senior
| Project Architect's One True Gospel Truth). The "context
| boundary" for a set of conventions/best practices is usually
| a codebase/team. Sometimes it's a sub-area within a codebase.
| More rarely, it's a type of code being worked on (e.g.
| payment processing code merits a different approach from
| kleenex/one-off scripts). Within those context boundaries,
| it's _absolutely_ appropriate to question when contributors
| deviate from an agreed-upon set of best practices--they just
| might not be Martin 's best practices.
|
| Rather, the core of my critique is that Martin's approach
| lacks _perspective_. Perspective /pragmatism--not some
| abstract notion of "skill level in creating well-factored
| code according to a set of rules"--is the scarce commodity
| among the intermediate-seeking-senior engineers that Martin's
| work is primarily marketed toward and valued by.
|
| From there, I see two things wrong with Martin's stance in
| the Osterhout transcript:
|
| "Out of touch" was not an arbitrarily chosen ad-hominem. When
| Osterhout pressed Martin to improve and work on some code,
| Martin's output and his defense of it were really low-
| quality. I can tell they're really low quality because, in
| spite of differing _specific_ opinions on things like method
| length /naming/SRP, almost everyone here and to whom I've
| showed that transcript finds _something_ seriously wrong with
| Martin 's version, while the most stringent critique of
| Osterhout's code I've seen mustered is "eh, it's fine, could
| be better". That, and Martin's statements around the "why" of
| his refactors, indicate that the applicability of his advice
| for material code quality improvements in 2025 (as opposed
| to, say, un-spaghettification of 2005 PHP 5000-line god-
| object monstrosities) is in doubt. On its own, that in-
| applicability wouldn't be a massive problem, which brings me
| to...
|
| Second, Martin is a teacher. When you mention '"Uncle Bob
| devotees" vs "Uncle Bob"' and I talk about the _rigidity_ I
| see in evidence among people that like Martin, I 'm talking
| about him as a teacher. This isn't a Torvalds or Antirez or
| Fabrice Bellard-type legendary contributor discussing
| methodological approaches that _worked for them_ to make
| important software. Martin is first and foremost (and perhaps
| solely) a teacher: that 's how he markets himself and what
| people value him for. And that's OK! Teachers do not have to
| be contributors/builders to be great teachers. However, it
| does mean that we get to evaluate Martin based on the
| _quality of his pedagogical approach_ rather than holding the
| ideas he teaches on their own merit alone. Put another way,
| teachers say half-right things all the time as a means of
| saving students from things they 're not ready for, and we
| don't excoriate them for that--not so long as the goal of
| preparing the students to understand the material in general
| (even if some introductory shortcuts need to later be
| uninstalled) is upheld.
|
| I think Martin has a really poor showing as a teacher. The
| people his work resonates the most strongly with are the
| people who take it to the most rigid, unhealthy extremes. His
| instructorial tone is absolute, interspersed with a few
| "...but only do this pragmatically of course" interjections
| that he himself doesn't really seem to believe. His material
| is often considered, in high-performing engineering
| departments, to be something that leaders have to check back
| against being taken too far rather than something they're
| happy to have juniors studying. Those things speak to
| failures _as a teacher_.
|
| Sure, software engineers are often binary thinkers prone to
| taking things to extremes--which means that a widely regarded
| teacher of that crowd is obligated to take those tendencies
| into account. Martin does not do this well: he proposes dated
| and inappropriate-in-many-cases practices, while modeling a
| stubborn, absolutist tone in his instruction and responses to
| criticism. Even if I were to give his specific technical
| proposals the greatest possible benefit of the doubt, this is
| still bad pedagogy.
| valenterry wrote:
| > 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 wrote:
| > 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 wrote:
| "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 wrote:
| 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
| brodo wrote:
| > Why would you not focus on writing OO code in an OO
| language for example?
|
| Often people do this to deliver higher quality software.
| Most languages still have some OO features, and people
| don't use them because they know they lead to bad code.
| Inheritence (a core OO feature) comes to mind. Most
| professionals nowadays agree that it should not be used.
|
| OO designs are often over-abstracted which makes them
| hard to understand and hard to change. They lack
| "locality of behavior". Trivial algorithms look
| complicated because parts of them are strewn across
| several classes. This is why more modern langues tend to
| move away from OOP.
|
| My guess is that im the long term, what we will keep from
| OO is the possibility to associate methods with structs.
| lmm wrote:
| > Why would you not focus on writing OO code in an OO
| language for example?
|
| That's circular logic. I wouldn't focus on writing OO
| code because I know from experience that the result is
| usually worse. If I had to use a language that was
| oriented towards writing OO code, I'd still try to limit
| the damage.
|
| > There are programming paradigms for a reason
|
| Nah. A lot of them are just accidents of history.
| wglb wrote:
| > Why would you not focus on writing OO code in an OO
| language
|
| It should be the best solution to the problem direct
| whether or not use of OO is best, not the language.
| throw16180339 wrote:
| > Why would you not focus on writing OO code in an OO
| language for example? Would you start writing OO code in
| a functional language? No you wouldn't, because it would
| be pointless. There are programming paradigms for a
| reason
|
| I'm paid for efficiently solving business problems with
| software, not using a particular paradigm. If an FP
| solution is more appropriate and the team can support it,
| then that's what I'll use.
| motorest wrote:
| > "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.
|
| See, this is the sort of lazy ignorance that adds nothing
| of value to the discussion, and just reads as spiteful
| adhominems.
|
| Domain models are fundamentally an object-oriented
| programming concept. You model the business domain with
| classes, meaning you specify in them the behavior that
| reflects your business domain. Your Order class has a
| collection of Product items, but you can update an order,
| cancel a order, repeat an order, etc. This behavior
| should be member functions. In Domain-Driven design, with
| its basis on OO, you implement these operations at the
| class level, because your classes model the business
| domain and implement business rules.
|
| The argument being made against anemic domain models is
| that a domain model without behavior fails to meet the
| most basic requirements of a domain model. Your domain
| model is just DTOs that you pass around as if the were
| value types, and have no behavior at all. Does it make
| sense to have objects without behavior? No, not in OO and
| elsewhere as well. Why? Because a domain model without
| behavior means you are wasting all development effort
| building up a structure that does nothing and adds none
| of the benefits, and thus represents wasted effort. You
| are better off just doing something entirely different
| which is certainly not Domain-Driven design.
|
| In fact, the whole problem with the blend of argument you
| are making is that you are trying to push a buzzword onto
| something that resembles none of it. It's like you want
| the benefit of playing buzzword bingo without even
| bothering to learn the absolute basics of it, or anything
| at all. You don't know what you're doing, and somehow
| you're calling it Domain-Driven design.
|
| > Why would focusing on OO be a goal?
|
| You are adopting a OO concept, which the most basic
| traits is that it models business domains with objects.
| Do you understand the absurdity of this sort of argument?
| valenterry wrote:
| > Domain models are fundamentally an object-oriented
| programming concept
|
| They are absolutely not. In fact, they are not even
| specific to even just programming, let alone OOP.
| lmm wrote:
| > Domain models are fundamentally an object-oriented
| programming concept.
|
| They are not.
|
| > You model the business domain with classes, meaning you
| specify in them the behavior that reflects your business
| domain.
|
| I have better tools for doing that.
|
| > In Domain-Driven design, with its basis on OO, you
| implement these operations at the class level, because
| your classes model the business domain and implement
| business rules.
|
| You're still not explaining the "why". You're just
| repeating a bunch of dogma.
|
| > a domain model without behavior means you are wasting
| all development effort building up a structure that does
| nothing and adds none of the benefits, and thus
| represents wasted effort.
|
| I know from experience that this is completely false.
|
| > You don't know what you're doing, and somehow you're
| calling it Domain-Driven design.
|
| I don't call it domain-driven. You can call it domain-
| driven if you want, or not if you don't want. I don't
| care what it's called, I care whether it results in
| effective, maintainable software with low defect rates.
| wglb wrote:
| > I care whether it results in effective, maintainable
| software with low defect rates.
|
| This is what it is about. All the other things that have
| been invented need to be in service of this goal.
| mrkeen wrote:
| > Your Order class has a collection of Product items, but
| you can update an order, cancel a order, repeat an order,
| etc. This behavior should be member functions.
|
| This is how to fuck up OO and give it a bad name:
| order.update(..) // Now your Order knows about the
| database. order.cancel(..) // Now your Order
| can Email the Customer about a cancellation.
| order.repeat(..) // Now your Order knows about the
| Scheduler.
|
| What else could Order know about? Maybe give it a JSON
| renderer .toJson(), a pricing mechanism .getCost(),
| discounting rules .applyDiscount(), and access to
| customer bank accounts for .directDebit(); Logging and
| backup too. And if a class has 10+ behaviours you've
| probably forgotten 5 more.
|
| An Order is a piece of paper that arrived in your
| mailbox. You can't take a sharpie to it, you can't tell
| it to march itself into the filing cabinet. It's a piece
| of paper which _you.read()_ so that _you.pack()_
| something into a box and take it to the post office.
| _You_ have behaviours and _the post office_ has
| behaviours. The Order and the Box do not. At best they
| have a few getters() or some mostly-static methods for
| returning aggregate data - but even then I 'd probably
| steer clear. For instance: if the Order gave me a nice
| totalPrice() method, it simplifies things for later
| right? Well no, because in TaxCalculator (not
| order.calculateTax()) I will want to drill down into the
| details, not the aggregate. Likewise for DiscountApplier.
|
| > Does it make sense to have objects without behavior?
| No, not in OO and elsewhere as well.
|
| It does, just like in the Domain (real-world Orders).
| Incidentally, I believe objects-without-behaviours is one
| of the core Clojure tenets.
|
| Since this is HN's monthly UB-bashing thread, I should
| point out that I learnt most of this stuff from him.
| (It's more from SOLID though, I don't think I have much
| to say on about cleanliness.)
|
| The above examples violate SRP and DI.
|
| "Single reason to change": If order.cancel(..) knows
| about email, then this is code I have to change _if the
| cancellation rules change_ or _if the email system
| changes_. What if we don 't notify over email anymore?
| Order has to become aware of SMS or some other tech which
| will cause more reasons for change.
|
| "Dependency inversion": People know what Orders are,
| regardless of technical competence. They can exist
| without computers or any particular implementation. They
| are therefore (relative to other concerns here) _high-
| level_ and _abstract_. Orders are processed using a
| database, Kafka and /or a bunch of other technologies (or
| _implementation details_ ). DI states that abstract
| things should not depend on concrete things.
| valenterry wrote:
| Aw, you described it so much nicer than me. I feel bad
| now.
| Kerrick wrote:
| We have a disagreement about the core of OOP. In English,
| a simple sentence like "The cat eats the rat" can be
| broken down as follows:
|
| - Cat is the subject noun
|
| - Eats is the verb
|
| - Rat is the object noun
|
| In object-oriented programming, the subject is most often
| the programmer, the program, the computer, the user
| agent, or the user. The object is... the object. The verb
| is the method.
|
| So, imagine the sentence "the customer canceled the
| order."
|
| - Customer is the subject noun
|
| - Canceled is the verb
|
| - Order is the object noun
|
| In OOP style you do not express this as
| customer.cancel(order) even though that reads aloud left-
| to-right similarly to English. Instead, you orient the
| expression around the object. The order is the object
| noun, and is what is being canceled. Thus,
| order.cancel(). The subject noun is left implicit,
| because it is redundant. Nearly every subject noun in a
| given method (or even system) will be the same
| programmer, program, computer, user agent, or user.
|
| For additional perspectives, I recommend reading Part I
| of "Object-Oriented Analysis and Design with
| Applications" (3rd edition) by Grady Booch et. al, and
| "Object Thinking" by David West.
|
| ---
|
| That said, I think you're right about the single
| responsibility principle in this example. A class with
| too many behaviors should usually be decomposed into
| multiple classes, with the responsibilities distributed
| appropriately. However, the object should not be left
| behavior-less. It must still be an anthropomorphized
| object that encapsulates whatever data it owns with
| behavior.
| valenterry wrote:
| > So, imagine the sentence "the customer canceled the
| order."
|
| > - Customer is the subject noun
|
| And this is wrong. Because the customer did not cancel
| the order. The customer actually _asked_ for the order to
| be canceled. And the order was then canceled by "the
| system". Whatever that system is.
|
| And that is the reason why it is not expressed as
| customer.cancel(order) but rather system.cancel(order,
| reason = "customer asked for it").
|
| > Thus, order.cancel(). The subject noun is left
| implicit, because it is redundant.
|
| Ah, is that so? Then, I would like you to tell me: what
| happens if there are two systems (e.g. a legacy system
| and a new system, or even more systems) and the order
| needs to be sometimes cancelled in both, or just one of
| those systems? How does that work now in your world?
| Kerrick wrote:
| > The customer actually asked for the order to be
| canceled.
|
| This is why many object-oriented programmers prefer to
| talk about message passing instead of method calling. It
| is indeed about asking for the order to be canceled, and
| the order can decide whether to fulfill that request.
| projektfu wrote:
| mrkeen mentioned dependency inversion (DI). I think it
| makes sense in oop for an order to have a cancel method,
| but the selection of this method might be better as
| something configured with DI. This is because the caller
| might not be aware of everything involved, as well.
|
| If the system is new and there's only one way to do it,
| it's not worth sweating over it. But if a new requirement
| comes up it makes sense to choose a way to handle that.
|
| For example, an order may be entered by a salesperson or
| maybe by a customer on the web. The cancellation process
| (a strategy, perhaps) might be different. Different users
| might have different permissions to cancel one order or
| another. The designer of the website probably shouldn't
| have to code all that in, maybe they just should have a
| cancel function for the order and let the business logic
| handle it. Each order object could be configured with the
| correct strategy.
|
| If you don't want to use OO, that's fine, but you still
| have to handle these situations. In what module do you
| put the function the web designer calls? And how do you
| choose the right process? These patterns will perhaps
| have other names in other paradigms but the model is
| effectively the same. The difference is where you stuff
| the complexity.
| mrkeen wrote:
| The comparison to English grammar is unnecessary. I
| didn't use it in my argument and you said it doesn't work
| that way either, so when you arrive at
|
| > The order is the object noun, and is what is being
| canceled. Thus, order.cancel()
|
| You've just restated the position I argued against,
| without an argument.
| valenterry wrote:
| > it's not object-oriented programming. That's it.
|
| Yes, exactly. And this "classical" object-oriented
| programming is an anti-pattern _itself_.
|
| (That being said, OOP is not well defined. And, for
| example, I have nothing against putting related data
| structures and functionality into the same namespace. But
| that's not what OOP means to him here)
| valenterry wrote:
| I'll reply here with a very quick example why the anemic
| domain model is superior in general, no matter if you do
| OOP or anything else.
|
| You used the example of an "order" yourself, so I'll
| built upon it.
|
| I would never combine functionality to update an order
| with the data and structure of the an order. The reason
| is simple: the business constraints _don 't always live
| inside the order_.
|
| Here's an example why such an approach inevitably must
| fail: if the business says that orders can only be made
| until 10000 items have been ordered in a month, then you
| cannot model that constraint _inside_ of the order class.
| You _must_ move it outside - to the entity that knows
| about _all_ the orders in the system. That would be the
| OrderRepository or however you want to call it.
|
| Remember, here is what you said in your other post:
|
| > Your Order class has a collection of Product items, but
| you can update an order, cancel a order, repeat an order,
| etc. This behavior should be member functions.
|
| So your Order should have a repeat function? But how can
| the order know if it can be repeated? It might violate
| the max-monthly-items constraint. The only way for the
| Order to do it is to _hold a reference to the
| OrderRepository_.
|
| And this is a big problem. You have now entangled the
| concept of an OrderRepository and of an Order. In fact,
| Orders could totally live without an OrderRepository
| alltogether, for example when you build an
| OrderSimulation where no orders are actually being
| executed/persisted. But to do so, now you have this
| OrderRepository, even if you don't need it.
|
| The rule of the thumb is: if the business says "we don't
| need feature A anymore, remove it" then you should be
| able to remove that feature from the code _without
| touching any unrelated feature_. If you now remove the
| OrderRepository and cause a bug in the Order class due to
| your code changes, the business will probably wonder how
| that could be, because while the OrderRepository cannot
| exist without Orders, Orders can exist without an
| OrderRepository.
|
| And if that seems a bit unrealistic, think of users: A
| user can easily exist without a UserRepository, but not
| the other way around.
|
| That makes clear, that you the rich domain model is an
| unsuitable and generally suboptimal solution to modeling
| the domain of a business. The anemic domain model on the
| other hand matches it perfectly.
|
| And one more thing: even natural language disagrees with
| the rich domain model. Does _an order repeat itself_? No!
| An order _is repeated_ and that is, it is repeated _by
| something or someone_. This alone makes clear that there
| is an entity beyond the Order that is responsible for
| such action. And again, the anemic domain model is a
| great solution for expressing this in code.
|
| But if you disagree, I'd like you to explain what you
| believe the disadvantages of the anemic domain model are.
| Kinrany wrote:
| Links to any existing articles on this topic would be
| greatly appreciated.
| valenterry wrote:
| This is the original article from Fowler:
| https://martinfowler.com/bliki/AnemicDomainModel.html
|
| By searching for that term, you'll easily find lots of
| other takes on the matter.
| Kinrany wrote:
| > I'll reply here with a very quick example why the
| anemic domain model is superior in general, no matter if
| you do OOP or anything else.
|
| I can search for it of course but results that aren't
| about OOP purism appear to be rare.
| mrkeen wrote:
| I highly recommend a video if you don't mind the format:
| https://youtu.be/zHiWqnTWsn4?t=3134
|
| The slide at 52:14 is on the SOLID principles, the first
| one is on SRP which gives pretty understandable advice
| about whether Order should have behaviours.
| samiv wrote:
| You made a great example here and I absolutely agree with
| you.
|
| In fact I find this type of accidental / unneeded
| coupling is the number one cause of problems, bugs and
| limitations of re-use and thus development velocity in
| any software product. Concepts where a single way
| dependency is turned into a cycling dependency are really
| hard to evolve, maintain, test and understand.
|
| In fact I'd go as far as to say that as a general rule of
| thumb if you have a situation where your class A depends
| on class B that depends on class A you've made a big doo
| doo and you should really seriously re-consider your
| design.
|
| (Adjacent to this rule is that classes that exist in the
| same level of of the software hierarchy and are thus
| siblings should also not know about each other).
|
| In fact when you structure your code so that the
| dependencies only go one way you end up with a neat
| lasagna code base and everything can easily slotted in.
| (Combined with this a secondary feature which is to
| eliminate all jumps upwards in the stack, i.e. callbacks)
| overgard wrote:
| 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 wrote:
| 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?
| wglb wrote:
| > I haven't seen a lot of evidence that Martin really has the
| coding chops to speak as authoritatively as he does
|
| From what I can deduce, his major coding work was long in the
| past, and maybe in C++.
| jbm wrote:
| 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 wrote:
| I don't see how it is uncle Bob's fault that your friend
| misunderstood his book.
| jbm wrote:
| Judging from this thread, it seems like a lot of people
| have similar issues with UB's work.
| kreetx wrote:
| It might just be that the divide of a getting-things-done
| developer and a bloat developer isn't really caused by
| Uncle Bob but merely correlates with it. I.e, good
| developers also agree with Uncle Bob, though apparently
| with a different interpretation of what he said.
| randomNumber7 wrote:
| Smart people read a book and critically think about it.
| The others think it was written by a superhuman and turn
| everything into religious beliefs.
| kreetx wrote:
| I meant that the book is interpreted differently by
| different people. (That no-one takes it as religion, but
| that some read it as recommending to "create a mountain
| of unnecessary abstractions", and others read it that
| "add necessary abstractions".)
| Cthulhu_ wrote:
| Not so much UB himself, but a developer being told a book
| or person is authoritative / has the final word on a
| subject isn't healthy.
| motorest wrote:
| > 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 wrote:
| > 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
| motorest wrote:
| > 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.
|
| I have to call bullshit on your argument. Either you aren't
| even looking because you have the misfortune of only
| looking at bad code written by incompetent developers, or
| you do not even know what it looks like to be able to tell.
|
| The core principles are quite simple, and are pervasive.
| Take for example replacing comments with self-descriptive
| names. Isn't this something obvious? I mean, a member
| function called foobinator needs a combination of comments
| and drilling down to the definition to be able to get a
| clue on what it does. Do you need a comment to tell what a
| member function called postOrderMessageToEventBroker does?
|
| Another very basic example: predicates. Is it hard to
| understand what a isMessageAnOrderRequest(message) does?
| What about a message.type == "command" &&
| type.ToUpperCase() == "request" && message.class ==
| RequestClass.Order ? Which one is cleaner and easier to
| read? You claim these examples are contrived, but in some
| domains they are more than idiomatic. Take user-defined
| type assertions. TypeScript even has specialized language
| constructs to implement them in the form of user-defined
| type guards. And yet you claim these examples are
| contrived?
|
| I'm starting to believe all these vocal critics who
| criticize Uncle Bob or Eric Evans or any other author are
| actually talking out of sheer ignorance about things they
| know nothing about. They read some comment in some blog and
| suddenly they think they are an authority on a subject they
| know nothing about.
|
| So much noise.
| manmal wrote:
| > Do you need a comment to tell what a member function
| called postOrderMessageToEventBroker does?
|
| Which event broker? Will I get a response via some
| callback? What happens if the sending fails, is there a
| retry mechanism? If yes, how many retries? What happens
| when the retry count is exceeded? Will the order's ID be
| set by this method? Is the method thread-safe? Which
| errors can be thrown? ,,Don't call this before the event
| broker has warmed up / connected". Etc etc
| crackrook wrote:
| > Do you need a comment to tell what a member function
| called postOrderMessageToEventBroker does?
|
| Obviously not and the comment you're replying to hasn't
| asserted otherwise. They say, clearly, that comments
| should explain the _why_, postOrderMessageToEventBroker
| explains only the _what_ (which is reflected in the
| verbiage of your question). Fortunately comments are
| practically free and we're not limited to doing the
| reader one-favor-per-statement, we can explain _both_ the
| why with a comment (when it's not obvious) and the what
| with clear function names.
| Mossy9 wrote:
| What I was refering to was the "why", not the "what" or
| "how". This is not a good function name to my eye, but
| YMMV: get-station-id-working-around-vendor-limitation-
| that-forces-us-to-route-the-call-through-an-intermediary-
| entity.
|
| Instead, a comment can clearly and succintly tell me why
| this implementation is seemingly more complex than it
| needs to be, link to relevant documentations or issues
| etc.
| wglb wrote:
| > I'm starting to believe all these vocal critics who
| criticize Uncle Bob or Eric Evans or any other author are
| actually talking out of sheer ignorance about things they
| know nothing about.
|
| I've been programming for 60 years in many different
| fields. I was programming long before he was. It is
| possible that I have written more code than he has in
| more languages (36 at last count), so my criticism of his
| are based on real-world experience.
| sirwhinesalot wrote:
| Code like Uncle Bob suggests is not easier to read and
| understand, it is harder, IMO and that of many others. Since
| the disagreement starts from this any further discussion is
| impossible.
| manmal wrote:
| > 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.
|
| This mentality sounds like a recipe for building leaky
| abstractions over the inherent traits of the von Neumann
| architecture, and, more recently, massive CPU parallelism.
| Bringing with it data races, deadlocks, and poor performance.
| A symptom of this mentality is also that modern software
| isn't really faster than it should be, considering the
| incredible performance gains in hardware.
|
| > Comments is a self-admission you failed to write readable
| code
|
| I'm not buying this. It's mostly just not possible to
| compress the behavior and contract of a function into its
| name. If it were, then the compiler would auto-generate code
| out of method names. You can use conventions and trigger
| words to codify behavior (eg bubbleSort, makeSHA256), but
| that only works for well-known concepts. At module
| boundaries, I'm not interested in the module's inner
| workings, but in its contract. And any sufficiently complex
| module has a contract that is so complex that comments are
| absolutely required.
| motorest wrote:
| > This mentality sounds like a recipe for building leaky
| abstractions over the inherent traits of the von Neumann
| architecture, and, more recently, massive CPU parallelism.
| Bringing with it data races, deadlocks, and poor
| performance.
|
| No,not really. Just because you think about how to name
| functions and what portions of your code should be easier
| to read if the were extracted to a function,that doesn't
| mean you are creating abstractions or creating problems.
|
| The rest of your comments on von Neumann architecture etc
| is pure nonsense. Just because your code is easy to read it
| doesn't mean you're writing poetry that bears no
| resemblance with how the code is executed. Think about what
| you're saying: what is the point of making readable code?
| Is it to look nice at the expense of bugs, or to help the
| developer understand what the code does? If it's the
| latter, what point do you think you're making?
| zbentley wrote:
| I'm not going to spend a long time responding to your
| comment, since it seems accusatory and rude; if you modify it
| to be more substantive I'll happily engage more.
|
| The one specific response I have is: it's not that I
|
| > say nothing specific or concrete: [I] only throw blanket ad
| hominems that sound very spiteful
|
| ...rather, it's that I'm criticizing Martin's approach to
| _teaching_ rather than his approach to _programming_. I
| expand on that criticism more in an adjacent comment, here:
| https://news.ycombinator.com/item?id=43171470
| spacechild1 wrote:
| > What machines do with it is of lower priority. Why? Because
| a programmer's time is far more expensive than any
| infrastructure cost.
|
| This assumes that code runs on corporate infrastructure. What
| if it runs on an end user device? As a user I certainly care
| about my phone's battery life. And we aren't even talking
| about environmental concerns. Finally, there are quite a few
| applications where speed actually matters.
|
| > 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.
|
| Self-explaining code is a noble goal, but in practice you
| will always have at least some code that needs additional
| comments, except for the most trivial applications. The world
| is not binary.
| AllegedAlec wrote:
| > 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 is not the way I wanted to do this, but due to bug
| #12345 in dependency [URL to github ticket] we're forced to
| work around that.
|
| # TODO FIXME when above is done.
|
| Oh no, I so failed at making self-descriptive code. I'm
| sorry, I totally should've named the method DoThisAndTHatButA
| lsoIncludeAnUglyHackBecauseSomeDubfuckUpstreamShippedWithABug
| .
| lmm wrote:
| > 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.
|
| Funny, I find the opposite. In my experience people that are
| willing to take a "dogmatic" position on code style are those
| who are able to actually get on with implementing features and
| bugfixes. It's the ones who think there's a time and place for
| everything and you need to re-litigate the same debates on
| every PR who tie themselves in knots getting nothing done.
|
| Do I agree with absolutely everything Martin writes? In
| principle, no. But I'd far rather work on a codebase and team
| that agrees to follow his standards (or any similar set of
| equally rigid standards, as long as they weren't insane) than
| one that doesn't.
| mkoubaa wrote:
| I can just tell that John Ousterhout works with much better
| developers on average than UB and that probably informs their
| biases.
| Jach wrote:
| 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.
| tikhonj wrote:
| 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 wrote:
| 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.
| WillAdams wrote:
| What definition of complexity in the context of
| discussing software development and architecture would
| you put forward instead?
| allemagne wrote:
| He could have chosen a different word besides
| "complexity" but I don't really think it would have
| affected much. The subjective easy/hard is specifically
| what Ousterhout is trying to talk about.
|
| Ultimately the problem he is (and all of us are) facing
| is that "good software design" can't really be measured
| with the right linting ruleset or static analysis. So if
| you're trying to break the concepts down each level,
| while still maintaining a scope that should include all
| software, that probably means it's impossible not to come
| off as squishy and non-specific at several points. I
| still think he strikes a really good balance in general
| here.
|
| I agree that there could be more discussion around
| context and audience. Ousterhout says "if you write a
| piece of code and it seems simple to you, but other
| people think it is complex, then it is complex", but then
| what can possibly be done if everyone on my team was
| replaced with new hires who had next to no experience
| writing code? Did the same codebase go from simple to
| complex?
| colonCapitalDee wrote:
| If you dismiss all the parts of APOSD that you agree with
| as straightforward and trivial, then obviously the only
| parts left for consideration are the parts you disagree
| with. APOSD is not an academic paper, it does not claim
| to be wholly and truly original. You are presumably an
| expert programmer, so it makes complete sense that much
| of the content discussed in APOSD appears to be
| "straightforward platitudes". To you, the content is
| trivial and obvious. But to the new grad with one year of
| work experience, the content is novel and informative.
| Perhaps you should take your own advice and consider the
| context.
| WillAdams wrote:
| 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.
| sudobash1 wrote:
| 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`.
| mbo wrote:
| 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.
| tikhonj wrote:
| There are a few Haskell functions with names like
| reallyUnsafePtrEquality# or accursedUnutterablePerformIO, and
| you _know_ something interesting is going on :P
| hakunin wrote:
| 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)
| ninetyninenine wrote:
| This doesn't happen in reality. Your program does so many
| things that practically speaking short names work for a lot
| of functions in the program. It's like English. There are
| big words and there are small words and usually to
| communicate a combination of big and small words are used.
|
| Nobody practically communicates with big words. A long
| function name only pops up when needed.
| hakunin wrote:
| It happened in the article we're discussing, and seems to
| be something Robert advocates for.
| ninetyninenine wrote:
| Happened in a contrived example.
| Pxtl wrote:
| I used to work this way, but I found that every non-trivial
| method involves edge-cases and workarounds documenting them
| the method name destroyed readability.
| hakunin wrote:
| The only point I was making is that short name signals
| that nothing unusual is going on, and long name signals
| that you have to pay extra attention. I never suggest to
| replace a comment with a long name. Here's my 4 reasons
| to leave a comment: https://max.engineer/reasons-to-
| leave-comment Comments are crucial for "why", and
| additional context. Name shouldn't go beyond "what". More
| on that here: https://max.engineer/maintainable-code
| (Check the "What" section that focuses on naming).
| zbentley wrote:
| > 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 wrote:
| > 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.
| colddevil wrote:
| Upvote for mentioning ADRs! ;)
|
| I really like the approach and as other comments already
| mentioned, this is a nice way to capture the "why" of
| specific decisions that go beyond the "how" in the code.
|
| Here is a good starting point for people not familiar with
| ADRs: - https://cognitect.com/blog/2011/11/15/documenting-
| architectu... - https://adr.github.io/
| slotrans wrote:
| > 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.
| Cthulhu_ wrote:
| And the described use case - USB stuff with very specific
| exception - makes a strong case for literate programming,
| that is, more prose than code.
| lompad wrote:
| Does everything have to be pushed into a structure-
| prescribing set of rules?
|
| Can't we just say "comments are useful here" without trying
| to make it into a case for $methodology?
| kragen wrote:
| Literate programming isn't a structure-prescribing set of
| rules or a methodology. It's just making the prose
| primary and the code secondary.
| ninetyninenine wrote:
| Why not put the prose in the name of the function?
| SAI_Peregrinus wrote:
| Function names are limited. E.g. can't provide a circuit
| diagram of what you're controlling in a function name. But
| you can do that in a comment (either with ASCII art or an
| image link).
| ninetyninenine wrote:
| Agreed. So why not stuff as much as possible into the
| name before resorting to a comment? Prose looks ugly as a
| name but the utility is not diminished.
| SAI_Peregrinus wrote:
| That embeds the "why" into your API. If it ever changes,
| the function no longer serves as an abstraction over that
| underlying reason & changing the function name breaks
| your API.
|
| That's not to say embed _nothing_ into the names. I 'm
| quite fond of the "Long Names are Long" blog post[1]:
| names need to clearly refer to what the named thing does,
| and precise enough to exclude stuff it doesn't do. Names
| can certainly get too short, e.g. the C "sprint fast"
| function `sprintf` is probably too short to be easily
| understood.
|
| [1] https://journal.stuffwithstuff.com/2016/06/16/long-
| names-are...
| ricree wrote:
| In addition to that, if the Why ever changes (maybe the
| issue was in an external dependency that finally got
| patched), you'd have to update the name or else leave it
| incorrect. Mildly annoying if just in one codebase, but a
| needlessly breaking change if that function is exported.
| Mawr wrote:
| 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.
| kragen wrote:
| They're invalid states inside the USB device, not inside the
| driver code. So nothing you do to the driver code can make
| them unrepresentable. The best you can do is avoid frobbing
| the device in the problematic ways.
| marcosdumay wrote:
| The GP is making those invalid states unreachable by writing
| a device driver.
| bch wrote:
| > 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.
|
| I believe in general there is a case for this (your case sounds
| like a perfect candidate). The implementation of Dtrace is
| another example[0] full of good description, including ASCII
| diagrams (aside: a case for knowing a bit of Emacs (though I'm
| sure vim has diagramming too, which I would know if I pulled
| myself out of nvi long enough to find out)).
|
| [0]
| https://github.com/opendtrace/opendtrace/blob/master/lib/lib...
| kragen wrote:
| Have you thought about distilling your hard-earned information
| about the device's behavior into a simulator for the device you
| could test your code against?
| ninetyninenine wrote:
| I don't see anything wrong with those names. A bit hard to
| parse but the name moves with the function call while a comment
| does not.
|
| It's annoying to look at but when you actually read the
| function you know what it does. A more elegantly named function
| is less annoying to read but less informative and doesn't
| provide critical information.
|
| The name just looks ugly. But it's like people have this ocd
| need to make things elegant when elegance is actually
| detrimental to the user. Can you actually give a legitimate
| reason why a method name like that is stupid other then its
| "hard to parse". Like another user said... use snake case if
| you want to make it easier.
| klysm wrote:
| Encoding temporal dependencies (or exclusions) between methods
| is hard. You can get partially there by using something like a
| typestate pattern (common in rust).
| marcusbuffett wrote:
| 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 wrote:
| 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.
| abhis3798 wrote:
| This is a good rule of thumb, but what would be a good
| response to have interfaces because, "what if a new scenario
| comes up in the future"?
| lmm wrote:
| "We'll extract interfaces as and when we need them - and
| when we know what the requirements are we'll be more able
| to design interfaces that fit them. Extracting them now is
| premature, unless we really don't have any other feature
| work to be doing?"
| Copenjin wrote:
| The scenario NEVER comes up in the future as it was
| originally expected. You'll end up having to remove and
| refactor a lot of code. Abstractions are useful only used
| sparingly and when they don't account for handling
| something that doesn't even exist yet.
| kragen wrote:
| If you own the code base, refactor. It's true that, if
| you're offering a stable interface to users whose code you
| can't edit, you need to plan carefully for backward
| compatibility.
| narnarpapadaddy wrote:
| When doing the initial design start in the middle of the
| complexity to abstraction budget. If you have 100 "units of
| complexity" (lines of code, conditions, states, classes,
| use cases, whatever) try to find 10 subdivisions of 10
| units each. Rarely, you'll have a one-off. Sometimes,
| you'll end up with more than 20 in a group. Mostly, you
| should have 5-20 groups of 5-20 units.
|
| If you start there, you have room for your abstraction to
| bend before it becomes too brittle and you need to
| refactor.
|
| Almost never is an interface worth it for 1 implementation,
| sometimes for 3, often for 5-20, sometimes for >20.
|
| The trick is recognizing both a "unit of complexity" and
| how many "units" a given abstraction covers. And, of
| course, different units might be in tension and you have to
| make a judgement call. It's not a silver bullet. Just a
| useful (for me at least) framing for thinking about how to
| manage complexity.
| kragen wrote:
| Maybe some examples would clarify your intent, because all
| the candidate interpretations I can think of are absurd.
|
| The sin() function in the C standard library covers 264
| cases, because it takes one argument which is, on most
| platforms, 64 bits. Are you suggesting that it should be
| separated into 260 separate functions?
|
| If you're saying you should pass in boolean and enum
| parameters to tell a subroutine or class which of your 5-20
| use cases the caller needs? I couldn't disagree more. Make
| them separate subroutines or classes.
|
| If you have 5-20 lines of code in a subroutine, but no
| conditionals or possibly-zero-iteration loops, those lines of
| code are all the same _case_. The subroutine doesn 't run
| some of them in some cases and others in other cases.
| narnarpapadaddy wrote:
| Think of it more like a "complexity distribution."
|
| Rarely, a function with a single line or an interface with
| a single element or a class hierarchy with a single parent
| and child is useful. Mostly, that abstraction is overhead.
|
| Often, a function with 5-20 lines or an interface 5-20
| members or a class hierarchy with 5-20 children is a useful
| abstraction. That's the sweet spot between too broad
| (function "doStuff") and too narrow (function
| "callMomOnTheLandLine").
|
| Sometimes, any of the above with the >20:1 complexity ratio
| are useful.
|
| It's not a hard and fast rule. If your complexity ratio
| falls outside that range, think twice about your
| abstraction.
| narnarpapadaddy wrote:
| And with respect to function behavior, I'd view it
| through the lens of cyclomatic complexity.
|
| Do I need 5-20 non-trivial test cases to cover the range
| of inputs this function accepts?
|
| If yes, function is probably about the right level of
| behavioral complexity to add value and not overhead.
|
| If I need only 1 test or if I need 200 tests it's
| probably doing too much or too little.
| kragen wrote:
| That's not what cyclomatic complexity is, and if you
| think 5-20 test cases is enough for sin(), open(), or
| Lisp EVAL, you need your head examined.
| narnarpapadaddy wrote:
| You're right, I suggested two different dimensions of
| complexity there as a lens into how much complexity a
| function contains. But I think the principle holds for
| either dimension.
|
| I don't think you need only 20 test cases for open().
| Sometimes, more than 20 is valid because you're saving
| across some other dimension of complexity. That happens
| and I don't dispute it.
|
| But the fact that you need >20 raises the question: is
| open() a good API?
|
| I'm not making any particular judgment about open(), but
| what constitutes a good file API is hotly contested. So,
| for me, that example is validation of the principle:
| here's an API that's behaviorally complex and disputed.
| That's exactly what I'm suggesting would happen.
|
| Does that help clarify?
| kragen wrote:
| Yes, open() is a good API. I can't believe you're asking
| that question! It's close to the Platonic ideal of a good
| API; not that it couldn't have been designed better, but
| almost no interface in the software world comes close to
| providing as much functionality with as little interface
| complexity, or serving so many different callers or so
| many different callees. Maybe TCP/IP, HTTP, JSON, and SQL
| compete along some of these axes, but not much else.
|
| No, 20 test cases is not enough for open(). It's not even
| close. There are 36 _error cases_ for open() listed in
| the Linux man page for it.
|
| What constitutes a good file API is not hotly contested.
| It was hotly contested 50 years ago; for example, the
| FCB-based record I/O in CP/M and MS-DOS 1.0, TOPS-20's
| JFN-based interface, and OS/370's various access methods
| for datasets were all quite different from open() and
| from each other. Since about 35 years ago, every new
| system just copies the Unix API with minor variations.
| Sometimes they don't use bitwise flags, for example, or
| their open() reports errors via additional return values
| or exceptions instead of an invalid file descriptor.
| Sometimes they have opaque file descriptor objects
| instead of using integers. Sometimes the filename syntax
| permits drive letters, stream identifiers, or variables.
| But nothing looks like the I/O API of Guardian, CP/M,
| Multics, or VAX/VMS RMS, and for good reason.
| tremon wrote:
| That function covers 264 inputs, not cases. It handles only
| one case: converting an angular value to (half of) a
| cartesian coordinate.
| kragen wrote:
| Sounds like you haven't ever tried to implement it. But
| if the "case" you're thinking of is the "case"
| narnarpapadaddy was referring to, that takes us to their
| clause, "Any fewer [cases], the additional abstraction is
| unneeded complexity." This is obviously absurd when we're
| talking about the sin() function. Therefore, that can't
| possibly have been their intended meaning.
| tremon wrote:
| The alternative and more charitable interpretation, of
| course, is that a single function like sin() is not what
| said GP meant when using the word "interface". But hey,
| don't let me interrupt your tilting at straw men, you're
| doing a great job.
| getnormality wrote:
| 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?
| Scubabear68 wrote:
| 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.
| nyarlathotep_ wrote:
| 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.
| MobiusHorizons wrote:
| 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.
| monksy wrote:
| Add in Go and C++ code bases to that as well.
| PlunderBunny wrote:
| 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.
| WalterBright wrote:
| 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.
| Copenjin wrote:
| And a lot of people doesn't understand how dangerous
| shuffling parameters is, especially in languages that do not
| have named parameters...
| Pxtl wrote:
| Powershell is an _awful_ language but it has made me fall
| in love with named parameters. Name all the things.
| mrkeen wrote:
| If you have a 2-4 line function and you spot this, you can
| trivially remove it.
| js8 wrote:
| I have seen such code too - with just S,K and I combinators.
| It wasn't readable.
| monksy wrote:
| 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.
| dionian wrote:
| 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.
| lmm wrote:
| Yes, I've worked on a couple of codebases like that. It's
| glorious, you break everything down little by little and every
| step makes sense and can be tested individually. Best jobs I've
| had.
| MrJohz wrote:
| But are those steps actually doing anything that can be
| tested? My experience with these sorts of codebases was
| always that most of the functions aren't doing much other
| than calling other functions, and therefore testing those
| functions ends up either with testing exactly the same
| behaviour in several places, or mocking so heavily as to make
| the test pointless.
|
| Or worse, I've seen people break functions apart in such a
| way that you now need to maintain some sort of class-level
| state between the function calls in order to get the correct
| behaviour. This is almost impossible to meaningfully test
| because of the complex possible states and orders between
| those states - you might correctly test individual cases, but
| you'll never cover all possible behaviours with that sort of
| system.
| CyberDildonics wrote:
| These large compound statements look nice if they are
| perfect, but when you make giant expressions without
| intermediate variables, it is much more difficult to test.
|
| When you have small expressions that have incremental results
| stored in variables, you can see the result in a debugger so
| you can see each stage.
| ninetyninenine wrote:
| Yes. This works but only if the functions are pure and using
| pure function composition.
|
| Uncle bob doesn't mention this.
| createspecialString(y) = Capitalizefirstletter .
| MakealllowerCase . AddNumberSuffix .
| removeLetterA . removeLetterB .
| ConcatwithWord(x) CapitalizeFirstLetter(a) =
| a[0].upper() + a[1:] MakeAllLowercase(a) = map(a, (t) =>
| t.lower()) Addnumbersuffix(a) a + 3.toString()
| RemoveLetterA(t) = filter(t, (s) => s.lower() == "a")
| RemoveLetterB(t) = filter(t, (s) => s.lower() == "b")
| ConcatenateWithWord(x) = (y) => y + x
|
| There see? It's mostly doable in pure functional composition
| where the dot represents function composition. I program like
| this all the time. No way anyone can pull this off while
| mutating state and instantiating objects. F .
| P = (x) => F(P(x))
|
| Forgive some inconsistent formatting and naming im typing this
| on my phone.
|
| People who complain about this style tend to be unfamiliar with
| it. If you had knowledge about procedural coding styles and a
| function composition approach like this then usually this style
| is easier as the high level function literally reads like
| English. You don't need to even look at the definitions you
| already know what this complicated string formatting function
| does.
|
| No comments needed. And neither author tells you about this
| super modular approach. They don't mention the critical thing
| in that this style requires functions to be pure.
|
| Thus to get most of your code following this extremely modular
| and readable approach... much of your code must be minimizing
| IO and state changes and segregating it away as much as
| possible.
|
| The Haskell type system, the IO monad is pushing programmers in
| this direction.
|
| Again neither author talks about this.
| LudwigNagasena wrote:
| `createspecialString` is seven lines long though.
| ninetyninenine wrote:
| Then split it. All pure functions are easily decomposed
| into the most primitive units so even the most dogmatic ass
| hole can't talk shit. createSpecialString
| = createFormattedString . createNewString
| createFormattedString = Capitalizefirstletter .
| MakealllowerCase . AddNumberSuffix .
| createNewString(y) = removeLetterA .
| removeLetterB . ConcatwithWord(x)
|
| Or put it all on one line.
| createspecialString(y) = Capitalizefirstletter .
| MakealllowerCase . AddNumberSuffix . removeLetterA .
| removeLetterB . ConcatwithWord(x)
|
| The amount of lines becomes off topic once you get into
| this style. It's a completely orthoganol concept as it's
| completely irrelevant to readability and modularity.
|
| Lines doesn't makes sense for pure non imperative
| functions. Lines ONLY make sense for imperative functions
| because each line represents an instruction.
| mplanchard wrote:
| Based on his blog, Martin has been getting into Clojure in
| recent years. I was kind of hoping that the experience with a
| functional lisp would shift some of opinions that he
| previously stood by in Clean Code, but based on this
| discussion, it doesn't seem like it.
| CyberDildonics wrote:
| John Carmack would disagree with Uncle Bob and John Carmack
| actually programs.
|
| My own experience is that with an IDE that can collapse a new
| scope in the middle of a function, you can make large functions
| that accomplish a lot and are very clear by writing a comment
| and starting a new scope.
|
| If something is going to be called multiple times a new
| function makes sense, but this idea that anything that can
| eventually return a single value needs to be it's own function
| is a giant pain that creates more problems than it solves.
|
| Just makeing a new scope in the middle of the functions lets
| you use all the variables in the outer scope, do
| transformations without introducing new variables and
| ultimately "return" a new variable to the outer scope.
|
| I've never understood why polluting namespaces with dozens or
| hundreds of names (most of which may not be very descriptive
| since naming a hundred small things is already going to be
| confusing) is seen as a good idea. You look at a list and you
| have no idea what is important and what was being shoved in
| there to satisfy some do nothing public speaker's arbitrary
| rules.
| layer8 wrote:
| The problem with collapsing is that you need to know a priori
| which sub-scopes are independent and hence collapsible and
| which aren't. Meaning, you have to analyze the unfamiliar
| code first in order to know which sub-scopes you might want
| to collapse. And, given an already-collapsed sub-scope, due
| to it being collapsed you can't see if it reads or mutates
| some local variable. The benefit of extracted functions is
| that you _know_ that they are independent of the
| implementation details of the caller (i.e. can't possibly
| depend on or modify local variables of the caller other the
| ones passed as arguments).
|
| Too many arguments can become a problem. Nested functions can
| help here, because they allow you to move their
| implementation "out of the way" while still having access to
| shared variables. And sometimes a collection of parameters
| can sensibly become its own class.
|
| IDE affordances are fine, but I'm opposed to _requiring_
| reliance on them for reading and understanding code, as
| opposed to writing.
| CyberDildonics wrote:
| _you need to know a priori which sub-scopes are independent
| and hence collapsible and which aren't._
|
| What does independent mean? I would just collapse them all
| because they were meant to be collapsed in the first place.
|
| _you have to analyze the unfamiliar code first in order to
| know which sub-scopes you might want to collapse_
|
| Unfamiliar? I wasn't refactoring and collapsed them all.
|
| _The benefit of extracted functions is that you know that
| they are independent of the implementation details of the
| caller (i.e. can't possibly depend on or modify local
| variables of the caller other the ones passed as
| arguments)._
|
| That's true to an extent, but this is more of a way to make
| monolithic functions simple, which then makes the program
| simpler over all because you can avoid lots of tiny little
| functions. What you can end up with is programs that do non
| trivial things but don't have tons of functions confusing
| the issue.
|
| Pragmatically this isn't really a problem. The whole "it
| isn't exactly a 1:1 replacement" isn't the point. You can
| still put in comments and const references if you really
| want to.
|
| _IDE affordances are fine, but I'm opposed to requiring
| reliance on them for reading and understanding code, as
| opposed to writing._
|
| Why would it be required? The alternative is that you still
| have these commented sections with their own scope but they
| aren't collapsed. You can always work on it without the IDE
| and when you go back to the IDE it still works.
|
| The reality of it is that you can see a broad overview of a
| function then see details one section at a time and you
| don't even have to go skipping around to other parts of the
| file or other files to do it.
| wglb wrote:
| It is a bit weird.
|
| However, a friend of mine was a professional Smalltalk
| programmer. He claims that his median line count of methods,
| over his 17 year career, was 4.
|
| It is harder to do in other languages--it seems that C would be
| on the order of 10.
|
| Clearly it is a rule that can lead to complexity of too many
| methods, compromising whatever gain smaller methods give you.
| igouy wrote:
| > median line count of methods
|
| Auto-generate getters and setters for every instance variable
| and that will drag the average down. (Maybe a lot of those
| getters and setters should not have existed.)
| igouy wrote:
| fwiw Lines-of-Code / Method (Digitalk V/286 image, 1989) = 7
|
| https://dl.acm.org/doi/10.1145/74878.74904
| emtel wrote:
| Related: https://news.ycombinator.com/item?id=27276706
| namuol wrote:
| I've come full-circle back to my junior engineer attitude with
| respect to coding "best practices": Avoid anything resembling
| dogma.
| ctrlp wrote:
| 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 wrote:
| > 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 wrote:
| 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 wrote:
| 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.
| namuol wrote:
| Forget about the code itself and focus on the results.
|
| What I mean by that: Good code is code that has proven
| itself by surviving quietly in a long-living project that
| has changed a lot over many cycles of new engineers
| (experienced or otherwise) being onboarded. The less you
| hear people complain about it but the more you find people
| using or relying on it in some way, the better the code. If
| people are loud about how much they like it, it's either
| new, or it's something they've convinced themselves to like
| but know in their hearts is bad. It's the stuff that just
| works that's good - it's so good people don't even notice
| it.
| tcfhgj wrote:
| Not really, long-living projects don't adapt their
| complete code base with gained experience, much like the
| Linux Kernel probably will never be rewritten in Rust,
| C++ projects never transformed to C++14+, etc.
| regularfry wrote:
| The interesting thing to look for here is the parts of
| the codebase that _don 't need_ to adapt with gained
| experience. That's the key. If people aren't changing it,
| they haven't needed to, and that's a useful signal.
|
| Conversely, looking for the parts of a codebase with the
| highest churn will tell you _immediately_ what all the
| devs on that codebase will complain about, if you ask
| them. This has worked for me extremely well across a
| number of projects.
| yxhuvud wrote:
| It can also mean "We have not changed this because we
| don't dare to do that, or it is too much work and we just
| have to live with the bad decisions made 25 years ago".
| And that is the last code you want to copy.
| namuol wrote:
| It's interesting that we just assume a newer language
| produces "better code"
| yxhuvud wrote:
| No, because then you end up reading old C-code that are
| IFDEF mazes and think that is good code. No, to see good
| code you usually have to look at what experienced people
| write when they get to greenfield something new.
| namuol wrote:
| So you think code that is ugly is bad code? Or is it that
| it uses janky/outdated features? What makes it good if
| not its lifetime value?
|
| Surely you don't just presume the quality of code based
| on the person who wrote the code, right?
| yxhuvud wrote:
| What makes it good is the tradeoff between how well it
| solves the problem compared to how easy it is to
| maintain. And people learn how to write better code as
| they get more experienced, but old projects are seldom
| rewritten using the learnings - it is often just easier
| to start over from scratch.
| bluGill wrote:
| You have to read a lot of different code. Everyone thinks
| their code is good when they write it. Often old ugly
| code has a beautiful design still hidden behind many many
| requirements changes that didn't fit with the original
| design. Other code looks nice and beautiful but it will
| stand the test of requirement changes even worse than the
| other.
| wglb wrote:
| > Forget about the code itself and focus on the results.
|
| This reminds me of what Dijkstra said (paraphrasing): the
| computation is the important thing, not the code.
| rswail wrote:
| 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.
| tremon wrote:
| _Every if statement is a chance of a bug because the code
| has two or more paths to follow_
|
| This is known as the cyclomatic complexity of a program:
| https://en.wikipedia.org/wiki/Cyclomatic_complexity
|
| A corollary to this is that it is also beneficial to
| converge separate paths as quickly as possible (e.g. using
| non-nullable types and default values) or converge them all
| to the same place (e.g. nonlocal exception handling).
| wglb wrote:
| I often abbreviate that to "Psychosomatic Complexity"
| because more complex code is likely to give the
| programmer a headache.
| golol wrote:
| >Each individual function eventually does zero things.
|
| Lambda calculus, basically :)
| mplanchard wrote:
| > You are left sifting through the ashes of your program
| wondering "Where did I go wrong?"
|
| Brilliantly phrased metaphor, thank you.
| kraftman wrote:
| it has been years since I read the book, but I'm surprised that
| there's so much hatred for it here. From memory it seemed like
| fairly harmless things like give things good names, try to make
| the code readable, dont comment what the code does but why, use
| consistent formatting, avoid duplication.
|
| Other than people going overboard with empty classes and
| inheritance Ive not really seen a problem of people breaking
| down functions too far.
|
| Which parts are important to grow out of?
| InvisibleUp wrote:
| There's a good overview of the faults of Clean Code at
| https://qntm.org/clean.
| WalterBright wrote:
| 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 wrote:
| I also fixed the disassembler to also add a clickable link to
| the instruction spec page for each instruction.
| wglb wrote:
| I did that back in the day (before we could click on
| anything) about what the compiler was thinking as it
| generated the code. That was fun.
| vishnugupta wrote:
| While on this topic, one book I really enjoyed is "Beautiful
| Code"[1]. It is not preachy or prescriptive but a diverse set of
| programmers showing the code they enjoyed writing.
|
| [1] https://www.goodreads.com/book/show/405790.Beautiful_Code
| hakunin wrote:
| 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.
| seanwilson wrote:
| 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 wrote:
| 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.
| seanwilson wrote:
| Why is that convincing though? Students aren't experienced
| coders, aren't working in large teams, and student
| assignments aren't like long-term large commercial projects.
|
| If you mean the additions here
| https://web.stanford.edu/~ouster/cgi-bin/book.php, I read
| these and it still sounds like general rules of thumb you'll
| only really learn and understand by practicing a lot e.g. "In
| my experience, the sweet spot is to implement new modules in
| a somewhat general-purpose fashion" "Having good taste is an
| important part of being a good software designer".
| WillAdams wrote:
| It's better credentials and experiential basis than most
| other programming books.
|
| Moreover, it is the students' inexperience which give this
| text credence --- since it results in their making errors
| and poor architectural/design choices it affords the chance
| of correction.
|
| I think it is remarkable that the author switched from
| "modules should be specialized" to "modules should be
| generalized" (rough paraphrasing, mailed my copy to Brazil
| and waiting to buy a replacement).
|
| If you know of other books which you merit recommendation
| and which have a similar or better context for their
| authorship and exposition, I would be glad to hear of them.
| seanwilson wrote:
| > It's better credentials and experiential basis than
| most other programming books.
|
| When considering coding advice, I just don't find
| credentials or the results of a coding experiment matter
| much, especially if it involves students. I run through
| the scenarios in my head and pick the option that makes
| sense given the context and competing priorities.
|
| > I think it is remarkable that the author switched from
| "modules should be specialized" to "modules should be
| generalized" (rough paraphrasing, mailed my copy to
| Brazil and waiting to buy a replacement).
|
| The link I posted has a PDF with the content I think. I
| guess I don't find the limited example involving a few
| function signatures compelling (a student assignment to
| write a basic text editor) or understand why I need to
| pick whether to trend towards modules being specialized
| or generalized... you treat it on a case-by-case basis,
| pick the one that has the most benefits given the context
| and be open to changing later when it makes sense?
| Outside of a few rules, it's boring but "it depends"
| really is the answer to most of these debates. Similar
| with how long functions should be, writing comments and
| how to name variables.
|
| > If you know of other books which you merit
| recommendation and which have a similar or better context
| for their authorship and exposition, I would be glad to
| hear of them.
|
| Software Engineering at Google is probably relevant for
| large projects: https://abseil.io/resources/swe-book
|
| The rest probably best comes from practice, that's how I
| learned most of what I know here. I'm didn't for example
| become a fan of strong static types because of advice
| based on credentials or experiments, but from experience
| coding with and without types.
| WillAdams wrote:
| Thanks.
|
| At a quick glance, that book seems to align well with
| APoSD --- what aspects do you believe run counter to it?
| seanwilson wrote:
| The books aren't that similar I found. The Google one is
| more about practical tips on the dev process of scaling
| and maintaining software in teams, rather than focused on
| code.
| WillAdams wrote:
| Okay.
|
| What book that covers a similar range of topics as APoSD
| would you suggest?
| jghn wrote:
| Because the pendulum of typing hadn't swung back to static
| being in vogue when the Philosophy of Software Design came out.
| At the time you had mostly the Scala & Haskell people standing
| in a corner screaming until they (well, we as I was one of
| them) were blue in the face about reducing "certain types of
| bugs", and making impossible states impossible.
|
| Since then, everyone and their brother is on the static typing
| train. And from that lens you're right. It seems like an
| omission. Give it another 10 years and people will probably
| think the opposite.
| pclmulqdq wrote:
| Type systems and type-based coding patterns are very hip right
| now, but they weren't 6 years ago. That is partly because the
| type systems in the main languages in use 6 years ago were hack
| jobs (to put it politely).
|
| I do expect the pendulum to swing against type systems at some
| point soon for the same reasons it swung against OOP: Too much
| heavy lifting done by something that's hidden from the
| programmer, encouraging people to be "too clever," etc. Like
| OOP, algebraic types are a tool that have to be used well, and
| the current users are people who really like type systems and
| do use them well. It's only a matter of time before the tool
| gets into the hands of the average programmer, and then we will
| see how terribly a great type system can hurt you.
| dionian wrote:
| "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
| overgard wrote:
| 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 111112222233333444445555
| 5666667777788888999990000011111222223333344444 3579135
| 79135791357913579135791357913579135791357913579135791357913579135
| 79 !!! !! !! ! !! ! !! ! ! !! ! !! ! ! ! ! !!
| !! ! 3
| |||-||-||-||-||-||-||-||-||-||-||-||-||-||-||-||-||-||-||-||-||-
| 5 |||||||||||-||||-||||-||||-||||-||||-||||-||||-||||-||||-||||-
| 7 |||||||||||||||||||||||-||||||-||||||-||||||-||||||-||||||-||||
| ||- 11 ||||||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||-||||||||||- 13 ||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||| ... 11
| 3||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ||||||||||
|
| 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.
| seabombs wrote:
| Lol, this reminded me of those engravings we put on spacecraft.
| Like, if we had to communicate the algorithm to an alien
| civilization then sure, this might be the best way to do it!
|
| https://en.wikipedia.org/wiki/Pioneer_plaque
| lynguist wrote:
| The juxtaposition of how the original comment starts, then
| the appearance of the verbatim "good comment", then the
| spacecraft engravings made me laugh tears.
|
| Especially the buildup from how bizarre the understanding of
| UB of comments is to actually seeing one "in the wild".
| nvlled wrote:
| > 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.
| badmintonbaseba wrote:
| The code is there to explain the comment.
| cjfd wrote:
| Once you notice that the primes are in the top rows, it becomes
| a pretty good comment.
| xeyownt wrote:
| Just learned that 9, 15, 21, ... are primes. Excellent
| comment ^^.
| froh wrote:
| well, ackchyually, 'technically' the primes _are_ in there
| in that top row
|
| just not _only_ primes ^^
| Terretta wrote:
| > _so bizarre ... what the hell is that supposed to tell
| someone?!_
|
| I liked this bizarre comment. It was like seeing a physical
| geometry proof for trig. Or like thinking about primes while
| riding a bike for an hour.
|
| In 10 - 15 seconds this comment offered a flash of appliable
| intuition into primes I'd not appreciated before.
|
| Granted, the bulk of that was first gathering that the top 3
| rows of digits were a series turned sideways (printing them
| rotated would have made that instant). Joys of plaintext.
|
| But then the pattern popped, and the code, including the
| optimization, made sense, but now from the "grok", with
| MTOWTDI.
|
| Neither their commentary nor their function names and comments,
| caused the grok. I could "accept" the assertions, but to me
| neither naming nor comments were _intuitively self-evident_ the
| way the diagram was.
|
| Both of them commented on having to dwell on what the code was
| doing to consider refactoring. Once this flash happens, one no
| longer needs reference code at all, it's just another property
| of primes.
| wglb wrote:
| I'm pretty much in agreement with you on this, however I'm
| always aware of the possibility of comments being bugs. If code
| gets moved around, there is the very real possibility that the
| comment is now attached to the wrong method or line of code.
|
| I now comment on method or function basis, describing what the
| method does. The how should be evident in the body itself.
|
| He doesn't seem to often concede to being wrong.
| jillesvangurp wrote:
| 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.
| imjonse wrote:
| 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 wrote:
| Let's not forget that Uncle Bob, by the time of writing "Clean
| Code" had 4 decades coding experience.
| kragen wrote:
| My middle school English teacher had 4 decades of experience
| writing. What she wrote was lesson plans. That doesn't make
| her Stephen King.
| WillAdams wrote:
| Do not make the mistake of the craftsman who claims to have
| 20 years of experience, but in truth only has 1 year of
| experience repeated 20 times.
| wglb wrote:
| Are there large code bases that he has written that we know
| anything about?
| intelVISA wrote:
| Software is results driven, there's no value in simply
| warming a seat for X YOE, talking about code instead of
| actually executing.
| throw16180339 wrote:
| What has he shipped, though?
| mbonnet wrote:
| Kenneth Copeland has been a pastor for 50 years and his
| theology and pastoral practice is still terrible. Years of
| experience is not a useful metric when you could instead look
| at results.
| j_san wrote:
| Biased against the approach of your former coworker and thus
| the "Clean Code" way? I assume it did not work out well,
| because you needed to move fast to build an MVP before trying
| to do it right?
| imjonse wrote:
| yes, biased against knowing 'the best way do write software'
| and applying it regardless of what the current requirements
| and constraints are. And arguing for their position by
| sending people links to Uncle Bob videos for 'enlightenment'.
| LunicLynx wrote:
| 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.
| pjmlp wrote:
| 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.
| nickm12 wrote:
| 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
| nickm12 wrote:
| 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.
| ninetyninenine wrote:
| Cleanliness AND Design is Highly correlated with IO, side effects
| and state.
|
| Most programmers know about this in 2025 but they didn't back
| then. Looks like the authors don't even mention it.
| dgunay wrote:
| I find it funny how much people obsess over Clean Code. In my
| opinion Robert Martin's Clean Architecture is a much more
| valuable and realistic idea than all this madness about 3 line
| functions, no comments, do one thing, etc. I would take the
| ugliest code that followed Clean Architecture over any "Clean
| Code" that didn't bother sensibly separating business logic and
| I/O.
|
| I don't like the guy very much, but for web development even just
| mostly following Clean Architecture does so much to keep things
| from devolving into chaos long term.
| blt wrote:
| The prime number code hurts to read. I feel like Bob is living in
| a different reality than most of us.
| jonashus wrote:
| Yes, no, I think he has different mental capabilities than most
| (most of the commenters here at least) and by that actually are
| living in a different reality. Human brains function vastly
| different. Two examples stood out to me.
|
| 1) UB said he reads the code in its full from left to right
| with the if(isTooHot) example. I only resort to reading code in
| that way as a last resort if I really can't figure out what the
| code is doing. I mean I look at a block or row and take it in
| more as a whole.
|
| 2) UB said comments are annoying because he has to read them
| and keep the whole of the comment text in his mind. This again
| says he reads everything left to right, and he can likely store
| everything that he has read up to a certain amount.
|
| My mind works nothing like that. I can hold very few words in
| my working memory but can instead hold concepts/ideas. For that
| to work good I need to see as much of the involved code as
| possible and my mental image evaporates if I have to navigate
| too far where I started.
| myst wrote:
| Where can I find Martin's code? I would like to see and compile
| it.
| brodo wrote:
| https://github.com/unclebob/fitnesse
| sharas- wrote:
| Whoes uncle is he anyways?
| jacobsenscott wrote:
| I was around before the clean code movement, and like all
| software movements, it was a reaction to real problems in the
| software industry. Massive procedural functions with deeply
| nested conditionals, no structure, global variables, no testing
| at all. That was all the norm.
|
| Clean Code pushed things in a better direction, but it over-
| corrected. In many ways APOSD (published in 2018) is a correction
| against the excesses of Clean Code (published in 2008).
|
| Will people swing too far back, to giant methods, deeply nested
| conditionals, etc? I don't know. But probably.
| matsemann wrote:
| I think learning extremes can be useful, just don't take any
| one paradigm as gospel. Practicing Clean Code forces you to
| think in a special way, and when you've tried it, you start to
| get a feeling for where you should draw the line. Doing CC
| makes you a better programmer, but you have to figure out
| yourself where the tradeoffs are.
|
| Other examples are TDD. Forcing myself to write tests for
| everything for a period has made all my code since better, even
| though I don't practice TDD now.
| lyu07282 wrote:
| I feel the same way, the benefit of testing is that it forces
| you to write code that can be tested, which tends to make
| code better just in general.
| k__ wrote:
| If you don't nest that much, big functions aren't so bad.
|
| You can just scroll down and see what happens in a linear
| fashion.
| pclmulqdq wrote:
| This is the Linux kernel approach, and is a big part of why
| the kernel uses 8-space tabs. It's generally very effective
| for understanding what is happening. I'm happy with a
| 200-line straight-line-with-error-handling function, while a
| monstrosity of 10 20-line functions that all do if-else is
| quite a bit harder to read. The latter is "clean code."
| abirch wrote:
| As Ben Franklin wrote "the best physician that knows the
| worthlessness of the most medicines."
| regularfry wrote:
| I believe that there is a genuine physiological effect that
| makes it a good idea to have the area of code that you need to
| think about fit entirely on one screen, without scrolling.
| There is probably an upper limit to the screen height where
| that limit is useful: I would believe a 100-line function to be
| above it and a 24-line function to be safely below it, but I
| wouldn't want to hazard a guess in the middle.
|
| It's all to do with how your brain processes what it's seeing,
| and the planning processes involved in getting to the next bit
| of information it needs. If that information is off-screen,
| then the mechanisms for stashing the current state and planning
| to move your hands in whatever way necessary to bring it
| onscreen will kick in, and that's a sort of disfluency.
|
| Similarly with tokens too far from whatever you're currently
| focused on. There's likely to be a region (or possibly a number
| of tokens) around your current focal point within which your
| brain can accurately task your eyes to scan, and outside that,
| there's a seeking disfluency.
|
| I think this is why you get weird edge cases like k and j,
| where they pride themselves on having All The Code in one 80x24
| buffer, and it _actually works for them_ despite breaking all
| the rules about code legibility.
| tremon wrote:
| The term you're looking for is cognitive load. It's a
| qualitative term used to represent the amount of information
| a person has to keep in working memory while working on a
| task.
| coopykins wrote:
| As someone who's recently started to read a philosophy of
| software design, I have to say that a lot of the points the
| author makes are things that I've come to learn with experience,
| which feels pretty good. As opposed to clean code, which I read
| when I was starting, and although at that time it felt good to
| have some guidelines--I still think having some guidelines is
| better than having nothing at all.
|
| I think you grow out of that advice very soon, because it's not
| very practical, it feels out of touch. The result is not code
| that is easier to read, quite the contrary. I think the Java
| world has been influenced for worse by him.
|
| But I don't have anything against him, as other comments say, the
| problem is dogmatism and trying to follow these authors blindly
| instead of thinking about it.
| wg0 wrote:
| The arguments from staunch clean code zealots have wasted so much
| time on PRs that I have lost count. Hours and hours and sometimes
| weeks - PRs having ideological discussions on something that
| neither the underlying machine cares nor the end user.
|
| Multiply that across the industry and that probably easily
| reaches in hundreds of millions of dollars productivity wasted.
|
| Ps: Not advocating cowboy coding or spaghetti code either.
| Copenjin wrote:
| You just need to work on one project built by someone that
| implemented Uncle Bob recommendations blindly when the books came
| out to know how much they are worth. There were some low hanging
| fruits to pick at the time regarding trying to be better at
| software engineering and he generated some text about them.
|
| Full of terrible advices, he never wrote anything significant (in
| scope and notoriety) during his time as a software engineer like
| many other prominent authors at the beginning of the agile era.
| The success is only the result of a wave of junior devs searching
| for some sort of guidance, something that there is a never-ending
| need for.
|
| Horrible recommendations that produced a lot of code that is a
| pain to work on with the abundant amount of indirection it has.
| Really painful guys.
| __loam wrote:
| A Philosophy of Software Design on the other hand is concise,
| excellent, and based on decades of teaching experience.
| k__ wrote:
| The world isn't binary
| mbonnet wrote:
| what's your point?
| k__ wrote:
| I interpreted the comment as sarcasm.
| kragen wrote:
| More importantly, experience writing great software.
| mdaniel wrote:
| If I win the lottery, I don't want a building named after me
| I want to donate a copy of that book to every university
| computer science[1] student and make it required reading
|
| 1: I'm aware it's a _software engineering_ book, but since
| there are very few B.S. Software Engineering programs out
| there, You Know What I Mean ™
| wiether wrote:
| > The success is only the result of a wave of junior devs
| searching for some sort of guidance, something that there is a
| never-ending need for.
|
| The issue is that, some never grown out of it. I interviewed
| with companies where they give the book to any new
| intern/junior. Then, during the hiring process, they don't even
| ask if you read it, they straight up ask questions about your
| knowledge of it. Like "What does Uncle Bob says about X in his
| book Clean Code?". And they constantly refers to it. Some
| people go as far as quoting it in PR.
|
| The worst part being that once they leave their company, since
| they don't know anything else, they'll apply the same stuff
| elsewhere & convert their new company to it.
| jbreckmckye wrote:
| (English tip: advice isn't a countable noun, so you don't
| pluralise it)
|
| I agree entirely. My encounters with Uncle Bob were as a junior
| developer receiving advice [no "s"] from other junior
| developers.
|
| And yes, I too find it suspicious how many mavens of the "Agile
| era" never really managed to ship anything.
| disgruntledphd2 wrote:
| It's important to note that Kent Beck is not one of those
| people, as he shipped the first unit testing library, as well
| as a bunch of ones in other languages later.
|
| Like, I personally prefer the bare assert style of testing
| (like pytest), but the junit style is basically everywhere
| now.
| machine_ghost wrote:
| Kent Beck is just as bad as Uncle Bob! He drank his own
| proverbial Kool-Aid and went all in on the crazy XP
| programming fad he started (... which contains brilliance
| like requiring pair programming for every line of code
| written).
|
| Look, both authors are very smart people who have great
| insights into development that we can all learn from ...
| but both also have the failing of being way too in love
| with their own ideas.
|
| It blinds them to the flaws in those ideas, and makes it so
| when you read their work you _have_ to be skeptical and
| evaluate each individual idea on their own.
| Copenjin wrote:
| Thanks for the correction, my opinion on the lack of
| credentials is that in the early days you just didn't need
| them to become popular, so little content that no one
| checked. I bit like it's happening nowadays with the anime
| profile pic twitter accounts acting like they invented AI,
| with zero code or achievements being shown.
| dgb23 wrote:
| Clean code, design patterns etc. were also picked up by
| teachers, professors and course instructors.
|
| I think these paradigms and patterns often operate on the wrong
| layer of abstraction, while mostly ignoring the things that
| matter the most, like efficiency, error handling and debugging.
|
| But getting good at these things requires a lot more blood,
| sweat and tears, so there's no easily teachable recipe for
| that.
| bluGill wrote:
| Clean Code is trying to operate at a layer far more important
| than efficiency: code maintenance. In the vast majority of
| cases computers are fast enough that you don't need to worry
| about efficiency. (part of this is any modern language
| provides all the common algorithms that are already highly
| optimized and easier to use than the writing them by hand and
| so the common places where you would want to worry are
| already efficient).
|
| Of course error handling and debugging are part of
| maintenance. However there is a lot more than those two that
| need to be considered as well.
|
| There is reason to hate Clean Code, but the worst adherents
| to the rules are still producing far better code than some of
| the impossible stuff that happened before. "Goto considered
| harmful" is one of the early steps in fixing all the bad
| things programmers used to do (and some still do), but you
| can follow the "rules" of goto considered harmful and still
| produce really bad code so we need more.
| dgb23 wrote:
| From personal experience, the most time consuming
| maintenance issues arise because of the following things:
|
| - third party dependencies, compatibility issues, breaking
| changes
|
| - code that is bloated with abstractions and indirection
|
| - performance issues, especially when worked around via
| caching etc.
|
| - bad error handling
|
| - inconsistent data
|
| Simpler code that can be followed and stepped through in a
| straight forward manner avoids 3/5 of these from the get
| go. Patterns and abstractions that emerge over time are
| sometimes beneficial. Legacy code or third party code that
| overuses abstractions is really more of a hindrance and
| significantly slows down how fast I can understand, own and
| fix things.
| bluGill wrote:
| It sounds like you have been lucky enough to avoid some
| of the worst code practices of history. Good for you.
|
| I hope you can come up with a good answer to fix the
| problems you cite. I haven't seen anything I have
| confidence in.
| Scubabear68 wrote:
| It is very instructional to read the source code to FitNesse
| framework.
|
| https://github.com/unclebob/fitnesse
|
| You can see how all his ideas come together into a ball of
| hundreds of almost empty classes, and gems such as "catch
| Throwable".
| lynguist wrote:
| This was such a riveting and literary read, I enjoyed it and
| couldn't put it away, like a novel where I was invested in the
| characters!
|
| Are there any other such reads in the software engineering field?
| WillAdams wrote:
| Knuth?
|
| He has argued in the past that the concept of Literate
| Programming
|
| http://literateprogramming.com/
|
| is the most important work he has done, and I highly recommend
| his various collections of lecture notes/papers including:
|
| https://www.goodreads.com/book/show/112245.Literate_Programm...
| wglb wrote:
| A Discipline of Programming, Dijkstra
|
| The architecture of Concurrent Programs, Per Brinch Hansen
|
| Literate programming--see http://www.literateprogramming.com/
|
| I don't recommend Design Patterns, as these are elements needed
| if your programming language is inadequate.
|
| There are many more.
| ilitirit wrote:
| It still blows my mind how dogmatic some people can be about
| things like this. I don't understand why anyone takes these
| things as gospel.
|
| Who else has had to deal with idiots who froth at the mouth when
| you exceed an 80 line character margin?
|
| And it's not just programming styles, patterns and idioms. It's
| arguably even worse when it comes to tech stacks and solution
| architecture.
|
| It's super-frustrating when I'm dealing with people in a
| professional setting and they're quick to point out something
| they read in a book, or even worse - a blog - with very little
| else to add.
|
| This was especially bad during the NoSQL and Microservice hype.
| Still somewhat feeling it with PAAS/SAAS and containerization. We
| have so many really really basic things running as Function Apps
| or lambdas, or simple transformations running in ADF or Talend
| that add zero value and only add to the support and maintenance
| overhead.
|
| Always keep in mind that sometimes the only difference between
| yourself and the person writing the book/blog/article is that
| they actually wrote it. And that their opinions were written down
| don't make them fact. Apply your own mind and experience.
| hdkrgr wrote:
| >> Always keep in mind that sometimes the only difference
| between yourself and the person writing the book/blog/article
| is that they actually wrote it.
|
| Well said!
| abirch wrote:
| Remember when most people give presentations about a
| technology, they're in the honeymoon stage
| raverbashing wrote:
| > Who else has had to deal with idiots who froth at the mouth
| when you exceed an 80 line character margin?
|
| Honestly, no better indication of a very mediocre developer
| einpoklum wrote:
| My experience is that being fastidious about code formatting
| is independent of one's ability as a developer. i.e. not a
| good indicator either way.
| bena wrote:
| I've noticed the worse someone is in a language, the worse
| they format it.
|
| People then develop fastidious code formatting rules
| because they realize well formatted code is easier to read
| and extend.
|
| Then people realize it's the organization of the code, not
| the rules themselves. They have preferences, but don't
| treat those preferences as "the one true way".
|
| So people with fastidious rules are in that middle ground
| of becoming less bad, and that's a wide swath of abilities.
| raverbashing wrote:
| > Then people realize it's the organization of the code,
| not the rules themselves. They have preferences, but
| don't treat those preferences as "the one true way".
|
| Yup, I agree with this
|
| It's not about, let's say, where your curly braces stay,
| but being consistent
|
| Though in some cases I'd argue that things like a very
| strict 80 character limit actually results in worse code
| (or at least worse to read code)
| ninetyninenine wrote:
| Disagree. Highly disagree.
|
| Smarter people write shittier code.
|
| Clean code is for stupider people.
|
| Think about it. It's because smart people don't need
| clean code. It's so trivial to them and so readable that
| they really don't need things to be ultra clean and well
| formatted.
|
| So the tendency to have this ocd need to write clean code
| among smart people is random. They either have it or they
| don't give a shit.
|
| But among stupid people it's not random. They need clean
| code because they are not smart enough to understand code
| that isn't clean.
| holoduke wrote:
| Reality is that you have to work with different levels of
| intelligence. Your stack must be understandable also for
| the "common" programmer. Otherwise goodluck finding
| people.
| ninetyninenine wrote:
| True. But what I said is still true. The tendency exists.
|
| Smart people don't often know how smart they are and
| don't realize how unreadable their code is until code
| review time and the stupid person points out what the
| smart person considered "obvious"
| Ma8ee wrote:
| Or maybe the smartest people understand that it is as
| important that less smart/experienced people than them
| can work with the code.
| ninetyninenine wrote:
| No. This what stupid people who think they are smart tend
| to think.
|
| Smart people often don't realize how smart they are and
| they don't recognize there code as unclean. To them it's
| trivial.
|
| A lot and I mean a lot of people on HN think they are
| smart but they are actually average or stupid. The amount
| of smart people operating at that level is rare. Really
| rare. I've been at entire companies where there isn't one
| person who is actually "smart" at the level I describe.
| Most people are just average.
| jjj123 wrote:
| Okay so your definition of "smart" sounds different than
| the definition everyone else in this thread is using.
| Sounds more like you're talking about "genius" to me,
| specifically in a savant type way where they are
| incapable of relating to average people.
| ninetyninenine wrote:
| No. I'm talking about genius. Not savant. Savants likely
| can't relate to your emotions. Geniuses can. The
| difference is just if it takes them 1 second to parse
| what takes you 5 minutes to do the same they often don't
| realize this unless you tell them.
|
| That being said what I talk about lives on a gradient.
| The smarter you are the greater degree of tendency you
| have to write shitty code.
|
| The cleaner your code the higher possible chance you are
| stupider. It's not a definitive sign but there is a
| correlation.
| ddejohn wrote:
| This is the silliest thing I've ever heard
| ninetyninenine wrote:
| Probably because you think you're smart AND you write
| excessively clean code and are excessively anal about it.
| Whether you actually are smart is a different story.
| ddejohn wrote:
| You have constructed a representation of me in your head
| that in no way reflects reality. Good luck in life.
| ninetyninenine wrote:
| It's just a lucky guess.
| dkarl wrote:
| I've been trying for years to track down a quote I lost,
| and it sounds like something you might know, because I
| think it would have resonated with you.
|
| It was from Charles Simonyi, talking about how as he got
| older, his prodigious ability to juggle large amounts of
| information in his head declined, and as a result, he
| started writing better code. Do you know it?
|
| Also, I half agree with your point, but I see it happen
| in two different ways. When writing ad hoc code for
| research purposes, I see very gifted people write
| seemingly sloppy, to-the-point code because it's the
| quickest way to the result. I say _seemingly_ sloppy
| because another programmer would see an intricate
| mechanism that in so many places is a hair 's breadth
| from being wrong, and they would want to reorganize it to
| make it more obvious that the code is correct. The savant
| who wrote the code is like, it's already 100% obvious,
| how could any change make it more obvious than that?
|
| In the software development context, I sometimes see very
| gifted people write incredibly complex code because they
| enjoy flexing their intellectual muscles and seeing the
| ornate towers they can create. But I also see average
| programmers and dumb programmers do the same thing, the
| only difference being that the gifted people can get away
| with more before it starts to hurt them. What's more, I
| see very good engineers, gifted but not _as_ gifted, try
| to follow the example of a savant and end up
| accomplishing far less than they could if they cut
| themselves a break and wrote plain code without all the
| flourishes and ornaments. A gifted programmer usually
| gets tired of this and grows out of it, but some of them
| enjoy it so much they commit to fooling themselves and
| other people that it 's the right way to write software.
|
| > So the tendency to have this ocd need to write clean
| code among smart people is random
|
| It is if they work entirely alone and their work doesn't
| depend at all on the success of others using their code.
| However, when it comes to big software projects, my
| experience is that it's not random: the smartest people
| do end up writing good code, unless they have ulterior
| motivations or a severe social blind spot.
| ninetyninenine wrote:
| Yeah they learn. But the tendency is still there. They
| make an attempt to dumb down their code but often they
| prioritize speed and what works.
| bena wrote:
| That's definitionally untrue.
|
| Shitty code doesn't run or doesn't do what the author
| thinks it's supposed to do. You can't write genuinely
| shitty code and be smart.
|
| I've seen smart people get caught in trying to write
| "clever" code. Abusing features of a language to make the
| code "look" smart. And I've never seen someone I've
| considered smart write completely unformatted code where
| it matters.
|
| I may not agree with all of their choices, but the
| smartest people I've worked with tend to have the
| structure of the code reflect the structure of the
| problem as they see it in their head. And yes, that
| tracks, you begin to use the code itself as an assistant
| to your own thinking. You don't think about where things
| are because they are where they should be.
|
| Forcing yourself to remember a bunch of pointless
| minutiae in order to write software isn't a mark of
| intelligence, it's a mark of someone who wants to be seen
| as intelligent.
| ninetyninenine wrote:
| >Shitty code doesn't run or doesn't do what the author
| thinks it's supposed to do. You can't write genuinely
| shitty code and be smart.
|
| By shitty code I mean aesthetically shitty. Not
| intrinsically shitty. So definitionally true, depending
| on your definition. Obviously I'm talking and I
| established context so most readers can figure out that
| I'm utilizing MY definition and NOT your own.
|
| >I've seen smart people get caught in trying to write
| "clever" code. Abusing features of a language to make the
| code "look" smart. And I've never seen someone I've
| considered smart write completely unformatted code where
| it matters.
|
| Then you've never been around the smartest people. Likely
| you've been around smarter then average people.
|
| >I may not agree with all of their choices, but the
| smartest people I've worked with tend to have the
| structure of the code reflect the structure of the
| problem as they see it in their head. And yes, that
| tracks, you begin to use the code itself as an assistant
| to your own thinking. You don't think about where things
| are because they are where they should be.
|
| Yeah and the smartest people structure the problem in
| their head in a way normal people can't easily
| understand. They can hold much more in their head so the
| structures can be complex.
|
| >Forcing yourself to remember a bunch of pointless
| minutiae in order to write software isn't a mark of
| intelligence, it's a mark of someone who wants to be seen
| as intelligent.
|
| Isn't that my point? Formatting rules are a bunch of
| pointless minutiae to intelligent people. It doesn't
| assist them in readability because their intelligence
| allows them to parse even the shittiest code with
| complete ease. And I mean aesthetically shitty, not
| intrinsically shitty.
| bena wrote:
| Then say ugly. "Shitty" can be ambiguous as you see. Most
| people would classify buggy code as shitty code.
|
| > Then you've never been around the smartest people.
| Likely you've been around smarter then average people.
|
| This is essentially using your own belief as proof that
| your belief is correct. You say I haven't been around the
| smartest people because I say the smartest people don't
| do what you claim. You are saying "I'm right therefore
| you are wrong". Maybe _you_ haven 't been around the
| smartest people.
|
| > Yeah and the smartest people structure the problem in
| their head in a way normal people can't easily
| understand. They can hold much more in their head so the
| structures can be complex.
|
| Complex is easy. Simple is hard. And yes, some things are
| inherently more complex than others. But the goal is to
| hold the _important_ things in your head. Offload as much
| as you can so you can focus on what matters.
|
| > Isn't that my point? Formatting rules are a bunch of
| pointless minutiae to intelligent people. It doesn't
| assist them in readability because their intelligence
| allows them to parse even the shittiest code with
| complete ease. And I mean aesthetically shitty, not
| intrinsically shitty.
|
| No. It's not the point you are making.
|
| Also, look at to everything I said. Strict adherence to
| any one style is not a marker of intelligence. I
| explicitly said that strict adherence is essentially for
| people in a wide range of skills. But the best have
| preferences, but realize that they are more guidelines
| and readability matters more than the rules.
|
| And the rules should be logical and essentially second
| nature. Like indenting is completely optional in most
| languages. But proper indenting allows you to better
| visualize the flow of the code. Nobody reads/writes
| minified JavaScript.
| ninetyninenine wrote:
| >This is essentially using your own belief as proof that
| your belief is correct. You say I haven't been around the
| smartest people because I say the smartest people don't
| do what you claim. You are saying "I'm right therefore
| you are wrong". Maybe you haven't been around the
| smartest people.
|
| I have quantitative evidence of this. There IQs were
| above 150.
|
| >Complex is easy. Simple is hard. And yes, some things
| are inherently more complex than others. But the goal is
| to hold the important things in your head. Offload as
| much as you can so you can focus on what matters.
|
| complex is not easy. And simple is not necessarily always
| hard. The story is obviously more complex then this.
|
| >No. It's not the point you are making.
|
| It is. It was a rhetorical question.
|
| I looked at everything you said. First off I never said
| anything about strict adeherence to a style. Smart people
| have there preferences.
|
| >And the rules should be logical and essentially second
| nature. Like indenting is completely optional in most
| languages. But proper indenting allows you to better
| visualize the flow of the code. Nobody reads/writes
| minified JavaScript.
|
| I've seen smart people who can do this. They don't even
| really care.
| bena wrote:
| You are just making more claims. You _claiming_ their IQs
| were above 150 does not mean they were. Or that you aren
| 't just straight up making wild claims to try and bolster
| your point.
|
| Also, how would you even know their IQs? I went to the
| best high school in my state, one of the best high
| schools in the nation, that became the template for an
| entire class of high performing high schools today. I
| don't say this to brag. I say this to qualify my next
| statement. I couldn't tell you what the IQ was of anyone
| there. It is not something that ever comes up.
|
| > First off I never said anything about strict adeherence
| to a style. Smart people have there preferences.
|
| This is directly counter to your other claims. You say
| that smart people just write ugly code and don't care
| about formatting. You even say that later in this post.
| It's almost like you are saying whatever you think will
| make you right in the moment.
|
| You also claim to have looked at everything I said, but
| your statements here contradict that. Because I said the
| best have preferences and follow a style, but know that
| there are times when the rules are counter to the goal.
|
| And you may actually believe you've seen smart people who
| can do this. However, at this point, I doubt your ability
| to accurately judge anyone's skill or intelligence. Or
| the ability to judge the veracity of their claims.
| ninetyninenine wrote:
| It came up because we talked about Mensa and he was part
| of it. I asked his iq and he told me. He claimed it and I
| believe him. Then the other guy also said he was offered
| to join Mensa but didn't. Take from that what you will.
| colonCapitalDee wrote:
| > Then you've never been around the smartest people.
| Likely you've been around smarter then average people.
|
| This is totally unfalsifiable. I claim that the smartest
| people around always wear clown shoes to work. If you
| disagree, it's simply because you haven't met any of the
| people I'm talking about. QED
| Pxtl wrote:
| When you're writing it you have the help of the compiler
| and various other tools, plus you have the model of what
| the code is doing fully-formed in your head, and you have
| the recent memory of various other approaches you took
| and how and why they failed. When you're reading it you
| have none of those things.
|
| So, code is harder to read than it is to write.
|
| So if you write code that uses your full intellect to
| write it out, you are therefore by definition too dumb to
| read it.
| ninetyninenine wrote:
| I never said smart people are writing code with their
| full intellect.
|
| They are likely writing code with a fraction of their
| intellect and that code is still too complicated for
| normal people to comprehend.
| ChrisMarshallNY wrote:
| The best developer that I ever worked with, is "on the
| spectrum."
|
| His code was _really_ anal.
|
| I have come to learn that there are no "rules," only
| heuristics.
| amoss wrote:
| I can't remember the last time I worked on a team without
| automatic linting enforced on check-in. Why would people
| choose to waste time arguing over that can be automated?
| Lyngbakr wrote:
| > It still blows my mind how dogmatic some people can be about
| things like this. I don't understand why anyone takes these
| things as gospel.
|
| IMO, this is one of the key differences between the two books.
| CC has a vibe of hard and fast opinion-based rules that you
| must obey, whereas APoSD feels more like empirically-derived
| principles or guidelines.
| pclmulqdq wrote:
| APoSD is written by a highly respected computer scientist
| with a tremendous list of technical achievements and also a
| strong teaching history as a professor, while CC was written
| by someone whose resume is primarily related to writing about
| software, not writing software.
| wangvnn wrote:
| CC was written by a man who worked with a highly respected
| man .. let that sink :)
| wesselbindt wrote:
| > idiots who froth at the mouth
|
| That seems like an unnecessarily harsh way to refer to people.
| codesnik wrote:
| but... they do froth!
| ahoka wrote:
| Well, except "Clean Code" advocates.
| felizuno wrote:
| Clean Code zealots are consistently some of the least
| likable, least productive, least pragmatic people I have ever
| worked with. I've had multiple clients where the whole team
| is threatening to quit unless the CC zealot is fired. And
| when they are fired guess what - bugs go down, shipped
| features go up, and meetings become productive. "Idiots who
| froth at the mouth" is an understatement IMO
| wesselbindt wrote:
| This too seems like a fairly hardline stance to take. I
| think it's not surprising that you'd have a hard time
| collaborating with people you'd refer to as unlikeable,
| unproductive, unpragmatic, overzealous, frothy idiots.
|
| It reminds me of the standard joke about veganism: "how do
| you know someone is vegan? Don't worry they'll tell you"
|
| It's a very ironic joke, because the people I hear talking
| about veganism the most are non-vegans complaining about
| veganism. In this thread too. All I see is people
| complaining about how dogmatic clean code people are, and I
| see no examples of that in this thread. The only strong and
| absolute language I see is from those who are complaining
| about CC people.
|
| Bear in mind, I don't have a dog in this fight. I'm not
| vegan, my methods are sometimes longer than four lines, and
| I do occasionally write a comment. But if this thread is
| anything to go by, the clean code folks seem a lot nicer to
| work with than the reactionaries.
| ramon156 wrote:
| On top of that, the argument was "i hate clean code
| people because they use bad reasoning (read something in
| a blog)". These are exclusive from each other. The OC
| basically argued there are no good reasons for clean
| code.
|
| I prefer readable code, but I wouldn't call myself a
| "clean code" person.
| felizuno wrote:
| I am in here taking a strong stance against CC, but I am
| happy to agree with you and steel-man your point: I think
| Clean Code is perfectly fine and workable in academic and
| single-developer software projects.
|
| I think most of this pushback (certainly all of mine) is
| about it creeping into production environments and
| exacerbating personality traits that tend to be
| problematic in team settings, which does not invalidate
| the abstract idea and should instead be scoped to its
| practice.
| felizuno wrote:
| I'm not seeking these people out to hate on them, but
| when I encounter them the social and code environments
| around them always exhibit the same dysfunctions. I've
| seen it multiple times. When your team is threatening to
| quit because they can't stand working with you, the
| problem is _probably_ with you and not them. And when you
| get fired and bugs go down, velocity goes up, and the
| morale problems disappear, it's now obvious that the
| problem was you. It's not a hand wavy theoretical take,
| it's a consistent pattern from dozens of instances at a
| variety of companies.
| arp242 wrote:
| Well I am vegan, and let me tell you, some vegans are
| completely insufferable. While it's true that the people
| ranting about vegans outnumber the insufferable vegans,
| there is a core of truth to it.
|
| I didn't read all 416 comments in this thread, but I've
| definitely worked with some people who religiously follow
| Clean Code to the point of toxicity. Perhaps the most
| bizarre example I encountered was the person who insisted
| that they're a backend dev, that they should never have
| to open the UI to test anything as tests should always be
| sufficient, and would continue pushing bugs in to
| production because the early "startup days" had produced
| some pretty crappy code with limited (or no!) tests. It
| was completely unworkable. The team literally had a party
| after he left. That was after two people had quit in
| large part due to this person.
|
| I have also worked with some people who generally liked
| _Clean Code_ but didn 't follow it religiously in spite
| of what works for this specific project. That's fine:
| that's just a normal type disagreement like Python vs.
| Ruby or where to put the braces or whatever: you talk to
| each other, and reach some solution that reasonably works
| for everyone.
|
| And the "reactionaries" are mostly just normal folks who
| want to get stuff done.
| cluckindan wrote:
| I've seen someone take a _glance_ at a codebase, declare it
| too complex, and suggest reading Clean Code.
|
| The entirety of the complexity was essential and dictated
| by an external data model used nation-wide for
| interoperability.
|
| Based on my experience and the OP dialogue, Uncle Bob is a
| vanity-driven narcissist and an infectious fraud.
| yakshaving_jgt wrote:
| Maybe they had mistaken "code" for "teeth"?
| wesselbindt wrote:
| Oh my goodness it took me 5 hours to get this. I'm glad I
| finally did!
| nicce wrote:
| > Always keep in mind that sometimes the only difference
| between yourself and the person writing the book/blog/article
| is that they actually wrote it. And that their opinions were
| written down don't make them fact. Apply your own mind and
| experience.
|
| But that difference is actually huge. I think you are
| downplaying the value of the writing process. Assuming that
| writer is acting in good faith and truly tries to provide the
| best possible information.
|
| But when you start writing, you start noticing that this idea
| might not be that good after all. Maybe I need to read more
| about this? Did you note everything? This idea conflicts with
| this other topic than I just wrote? What is correct? And the
| list goes on. When you structure all your thoughts as written
| text, it is easier to detect all conflicting ideas and
| mistakes. Not all writers are that good, but you should
| understand what I mean.
| __mharrison__ wrote:
| Writing is an excellent way to determine your opinions.
| There's a large gap between ideas and those formed when
| writing said ideas.
| hliyan wrote:
| To restate something I've said here last month:
|
| I'm fond of saying that anything that doesn't survive the
| compilation process is not design but code organization. Design
| would be: which data structures to use (list, map, array etc.),
| which data to keep in memory, which data to load/save and when,
| which algorithms to use, how to handle concurrency etc. Keeping
| the code organized is useful and is a part of basic hygiene,
| but it's far from the defining characteristic of the craft.
| leidenfrost wrote:
| My take is that the book also works as a source of authority
| for aspiring SSR and SR devs.
|
| Comments about code style are usually subjective, and, they
| can be easily dismissed as a personal preference, or, in the
| case of a Jr dev, as a lack of skill.
|
| Until they bring up "The Uncle Bob book". Now, suddenly, a
| subjective opinion from a Jr dev looks like an educated
| advice sourced from solid knowledge. And other people now
| have a reason to listen up.
|
| All of this is totally fabricated, of course. But it's like
| the concept of money. It's valid only because other people
| accept it as valid.
| tempodox wrote:
| What are "SSR and SR devs"?
| leidenfrost wrote:
| Semi Senior and Senior devs
| __mharrison__ wrote:
| Is this a common usage?
| mjr00 wrote:
| I had never heard it and assumed it was gacha
| terminology, with SSR devs as the top 1-2% and SR devs
| top 20%.
| nuancebydefault wrote:
| Semi senior?
|
| I usually tend to take people who add prefixes like
| senior to their function title, less seriously. I've seen
| young devs who write better code than so called senior
| devs.
| dkarl wrote:
| > Keeping the code organized is useful and is a part of basic
| hygiene, but it's far from the defining characteristic of the
| craft.
|
| I'm with you, but I don't think it makes sense to elevate one
| absolutely over the other as the "defining characteristic."
| Either one can tank the development of a piece of software
| and prevent it from coming into being in a useful way.
|
| Arguments about which aspects of software are more important
| than others usually arise between people who have personally
| suffered through different ways that projects can fail. Any
| aspect of software development will feel like the "defining
| characteristic" if it threatens to kill your project.
| geodel wrote:
| > Any aspect of software development will feel like the
| "defining characteristic" if it threatens to kill your
| project.
|
| That does not make sense to me. There can be thousand
| things that can kill project. One has to consider _what are
| the odds_ for them.
| dkarl wrote:
| How would you define the odds for the industry as a
| whole? The odds depend on the project, the team, the tech
| stack, and the organizational environment.
|
| No matter how long I work (twenty-five years so far) I
| think my personal experience is only enough to know that
| if I've seen something, it probably happens fairly often.
| If I've never seen something, it still might be common
| for all I know.
| analog31 wrote:
| Granted, while I program a lot, I'm not employed as a
| programmer per se. My impression is that programming is easy
| and fun, but software develoment is hard and laborious.
| Things like hygiene are among the differences between the
| two.
| jolt42 wrote:
| 100%. Dealing with legacy issues is much more laborious and
| also complicates hygiene.
| tikhonj wrote:
| I disagree entirely. Design is fundamentally a human-oriented
| discipline, and humans work almost exclusively with code
| _before_ it is compiled. A strong shared mental model for
| whatever we 're doing is as much a part of software
| development as any code that runs on a computer.
|
| Programming languages can (should!) be _amazing tools for
| thought_ rather than just tools for making computers do
| things; using these tools to figure out what we 're doing is
| a critical part of effective development. The highest-
| leverage software engineering work I've seen has involved
| figuring out better ways of thinking about things: developing
| better tools and abstractions. Tools and abstractions
| _compound_ since they fundamentally impact everything built
| on top of them. A good high-level design is the difference
| between a team that can add some specific capability in a
| day, a team that would take six months and a team that would
| say it cannot be done.
| mattmanser wrote:
| I agree, I recently keep having the thought that by far the
| hard part of programming is code organisation. Whether
| that's where the files go, or how you've wrapped up
| commonly used idioms like validation or data access in easy
| to use abstractions.
|
| It's so easy to get it spectacularly wrong and end up in a
| mess.
|
| And it's seems so deceptively pointless at the start. It's
| easy to throw together a greenfield project and get
| something working, but make a complete mess of
| organisation. But then it becomes so expensive so quickly
| to then make changes to that code.
|
| I've joined quite a few projects after 1/2 years of someone
| else making the project. And so often it's such an imposing
| mass of code that basically does sod all. Bad architects
| who don't understand why they're even using the patterns
| they are or mid/junior-level coders making projects is
| basically a recipe for the project just grinding to a halt
| just when it looks like you're getting near the end.
|
| It's when 1,000s of lines are easily refactored to 100s
| that you start thinking, how can these people honestly
| believe they have the ability to lead a project? They are
| so clearly completely out of their depth it's depressing.
|
| We seem, as an industry, to have a complete inability for
| management to distinguish genuine senior developers from
| people who will never be.
| Pxtl wrote:
| > code organization
|
| It's also the code documentation.
|
| Having documentation that is legible is good, right? And so a
| reviewer is reasonable to say "this is hard to read" since
| it's failing at its primary purpose.
| yuliyp wrote:
| Systems need to be able to handle all kinds of stresses
| placed on them during their useful life. The runtime
| bytecode/machine code/config is what deals with the actual
| running of the system. The code is what deals with the
| engineers making future modifications to it. The monitoring
| system deals with being able to allow operators to ensure the
| system stays up. All of these affect the reliability and
| performance of the deployed system during its lifetime. All
| of them are a part of the design of the system.
| ninetyninenine wrote:
| Well I mean they wrote books about it and one guy had the
| audacity to call his opinion a "philosophy" even though it's
| just an arbitrary opinion.
|
| Most of software is about assigning big words and over
| complicated nomenclature to concepts and these things
| masquerade as things with deeper meaning when in reality it's
| just some made up opinion.
|
| Software design is an art. It is not engineering and it is not
| science. That's why there's so much made up bullshit. The irony
| is we use "art" to solve engineering problems in programming.
| It's like ok we don't actually know the most optimal way to
| program a solution here so we make up bs patterns and
| philosophies. But then let's give this bs pattern some crazy
| over complicated name like Scientology or inversion of control
| and now everyone thinks it's a formal and legitimate scientific
| concept.
|
| Well cats out of the bag for Scientology. Not yet for a lot of
| the bs in software. A "philosophy" is the biggest utter
| bullshit word for this stuff I've ever seen.
| NeutralForest wrote:
| But there are typical practices we agree are good: using a
| VCS, writing tests, write comments when needed, separate
| different level of abstractions, etc. Right? This comes from
| years of common experience in software.
|
| Over time we get to find patterns, common issues and ways to
| fix them, etc. It doesn't have to be strict patterns but
| overall strategies.
|
| If we don't do that then it's just vibes right? Where's the
| engineering part?
| ninetyninenine wrote:
| Nothing is fixed in stone. If you have strong typing and
| program with pure functions and immutability while
| utilizing union types and matching to the full extent you
| typically need very few unit tests for your code to work.
| You just need integration and e2e tests.
|
| I write very little unit tests as my coding style that
| employs static checks as viciously as possible doesn't
| necessitate it.
|
| I would say only 30 percent of patterns are good and
| shared. The other stuff is just artistry and opinion. Like
| method name length or comments or OOP.
| NeutralForest wrote:
| I don't really agree, unit test should test behavior,
| having types of not should not be a defining factor in
| the coverage.
|
| I don't think patterns as a whole are good but there are
| known issues and structures to existing problems so
| boiling it down to art seems reductionist imo.
| ninetyninenine wrote:
| You don't agree because you likely aren't utilizing
| static checks to the extent that I do. Like there are no
| strings or numbers in my code. Everything is operating on
| strict union type boundaries. The only place where you
| have unbounded types like strings is on the interface to
| IO or state.
|
| I can code and not test behavior and have that behavior
| work reliably without tests. Key word is the unit trst.
| Typically IO and things that live outside these
| boundaries need integration tests.
|
| Most of web programming today actually doesn't need much
| unit testing. You're not doing much processing. The web
| layer functions as a router and that layer is a meta
| layer that writes code that executes somewhere else.
|
| Over half the code executes as sql. Integration tests are
| by far more important.
|
| Boiling it down to an art is not reductionist. It's true.
| Where is the scientific method in programming? How was a
| pattern deduced using the scientific method? If it was
| not deduced using the method then was it created from
| axioms and logic like math? Is it a theorem?
|
| No. It's all just made up. And we have no quantitative
| way of verifying why one design is better than another
| design. That's why software technology often moves
| horizontally. There's no way to verify the current design
| was better than the last.
|
| Even both you and I have a disagreement and are at a
| stalemate. Can you prove your unit testing is superior to
| my static testing? Not really. Actually tbf static
| checking is provably better if you don't count the
| dimension of effort required to use dependent types.
| NeutralForest wrote:
| That's an interesting approach, I'd like to see an
| implementation of what you're talking about. What
| language are you using that has such an expressive type
| system?
|
| Oh, I agree that there usually isn't a scientific method
| to programming. I think there could be though. Not for
| everything of course, some things will always be up to
| personal taste and interpretation but the cursor could
| probably be moved with some effort in analyzing existing
| codebases at scale, doing surveys, internal testing of
| different approaches in large companies. Something more
| akin to what you see in social sciences, even if it might
| be a bad word in some circles!
|
| We probably won't agree but I legitimately enjoy hearing
| about how people code.
| ninetyninenine wrote:
| Typescript is capable of dependent typing, union types,
| exhaustive matching and everything needed to achieve this
| style of programming. It's just not strict.
|
| The other language is rust. Though it's type system is
| not as expressive as typescript it is strict meaning
| nobody can really cheat their way out of it. In general
| Rust code requires less unit tests then typescript
| because of this.
|
| The other language is Idris and Haskell. But these
| languages are rarely used.
|
| This article can shed some insight into what I'm talking
| about: https://wiki.haskell.org/Why_Haskell_just_works#:~
| :text=The%...
| NeutralForest wrote:
| Thanks, I haven't touched Typescript in a while so it
| might be the occasion for that. When do you feel like you
| have a handle on the behavior, do you have complex
| integration tests then?
| yakshaving_jgt wrote:
| I write a big web application with a fairly type-oriented
| language, and I still write lots of unit tests. Mostly to
| do with parsing.
| ninetyninenine wrote:
| Yeah. That's where it should be. Usually though you don't
| need much parsing as it's coming in as json or a
| protobuf. But the interface between IO and your code
| program is where exceptions and errors can occur. Beyond
| this boundary your code should be pure and deterministic.
|
| Since you're doing your own parsing rather then using
| schema validators and existing formats like json, yes
| your code is doing A LOT of data processing and thus
| requires a lot of unit tests. Most of the time developers
| can trust the parsing libraries.
| yakshaving_jgt wrote:
| What you're describing isn't exactly new territory for
| me. Maybe you're writing for the room, and not
| immediately for my benefit.
|
| Parsing is kind of... everywhere. Path piece instances?
| Parsing. Forms? Parsing. The whole point of smart
| constructors is parsing. Deserialising from the
| persistence layer? Parsing. Sure, JSON and Protobuf also,
| but even when relying on a robust library like aeson, we
| still write tests. Why wouldn't you? The types you define
| can be serialised in different ways, and the way you
| deserialise needs to roundtrip with the way you (or an
| external system) serialise(s), which also necessitates
| more tests.
| ninetyninenine wrote:
| I wouldn't because the deserialization library is tested
| to death by the library maintainers.
| NeutralForest wrote:
| I don't really agree, unit test should test behavior,
| having types or not should not be a defining factor in
| the coverage.
|
| I don't think patterns as a whole are good but there are
| known issues and structures to existing problems so
| boiling it down to art seems reductionist imo.
| globnomulous wrote:
| Could you give an example where you've used a "static
| check" where someone else might be likelier to use a unit
| test? I'm curious.
| coliveira wrote:
| The issue is that programming is communication. Communication
| is indeed a form of art. Programming is not just giving
| instructions to machines, if that was the case we would be
| happily using binary code. So we have two dimensions, the
| first one is giving the binary instructions, but the other
| one is how to make these instructions understandable by
| humans, including ourselves.
| ninetyninenine wrote:
| No there are other dimensions to coding. Communication is
| ONE dimension only.
|
| There is optimization and there is modularity. All 3 of
| these dimensions are intimately tied and correlated.
| voidhorse wrote:
| I think it stems from fundamental misunderstandings about what
| it is one is actually trying to do when writing code.
|
| Coding is about building a _computable model_ of some facet of
| existence, usually for some business. When it comes to model
| building, comprehension and communication are paramount.
| Performance and other considerations are also important but
| these are arguably accidental features of machines and, in an
| ideal world, would not actually affect our model.
|
| Similarly, in an ideal world, we wouldn't even need programming
| languages. We'd be able to devise and explain computational
| systems in some kind of perfect abstract language and not need
| to worry about their realization as programs.
|
| I think a lot of these blanket philosophies confuse people by
| not emphasizing the higher level aspects of the activity
| enough. Instead people get hung up on particular patterns in
| particular paradigms/languages and forget that the real goal is
| to build a system that is comprehensible to the community of
| maintainers that need to work with it.
| gibibit wrote:
| It seems that each software design/development system,
| ideology, and practice has a good reason it was created, and
| has certain inherent benefits. Each may solve (or at least
| help with) some common problem.
|
| For instance, abstraction is good and short methods are good
| to some extent (who wants to read a 2000-line function?), but
| as John points out in the article, these can be taken too
| far, where they create new and perhaps worse problems.
|
| It seems there's a pendulum that swings back and forth. We go
| from big up front design, to Extreme Programming, to a
| pervasive object-oriented design culture, back to other
| paradigms.
| mlinhares wrote:
| Because its easy to be dogmatic, you don't need to think,
| consider the consequences or drawbacks, you just follow
| whatever the Supreme Leader told you to do.
|
| Its incredibly simple to just follow whatever someone is
| telling you to do, sometimes I wish I could live like this so I
| didn't have to fight with the people that do all the time.
| crabbone wrote:
| Professionals in other industries don't "just" write books. In
| a sense that usually the field has several acclaimed authors
| and they put some solid work into ensuring their books make
| sense. While there are disagreements in other fields, or some
| nonsense conventions, the conventional wisdom is usually at
| least good enough to make you a good professional.
|
| In programming it's the Wild West. Many claims are made based
| on nothing at all. It's very rare to see any kind of sensible
| research when it comes to the science part of CS. But following
| rules makes life easier. Even if rules are bad. That's kind of
| why conservatism exists as a political idea.
| wglb wrote:
| Yes, Uncle Bob is certainly capable of being pedantic. A friend
| of mine, a Smalltalk Consultant, partnered with him for a
| while. "With Uncle Bob, it's his way or the highway."
|
| His clean code work is certainly pretty dogmatic. As I recall,
| he says that Java is not object oriented.
|
| But if my memory serves me correctly, his book about C++
| (Designing Object-Oriented C++ Applications Using the Booch
| Method) has some excellent parts. His description of the
| difference between a class and an instance is one of the better
| ones.
|
| Then there is the famous sudouko puzzle incident, in which a
| student trying test-driven development can't get the solution.
| It is a very instructive incident which illustrates the TDD is
| unlikely to help you solve problems that are beyond incremental
| changes. Peter Norvig's solution makes that very clear. Uncle
| Bob does not seem to realize that.
|
| > Who else has had to deal with idiots who froth at the mouth
| when you exceed an 80 line character margin?
|
| But I admit in my youth, I was pretty dogmatic about languages
| and development practices, so I've been that guy.
| brianmcc wrote:
| >> ... TDD is unlikely to help you solve problems that are
| beyond incremental changes.
|
| Thank you for expressing this niggling problem with TDD.
| Personally I just cannot use it for "new stuff", I need to
| explore and create direct with "real" code for anything non-
| obvious.
| arcanemachiner wrote:
| I'm more of a DTT man myself: Develop, Then Test.
| brianmcc wrote:
| +1
|
| I think "code is carefully designed AND has a bunch of
| decent tests" places a codebase ahead of many tbh, even
| now, regardless of how it's produced
| switchbak wrote:
| Wasn't that Ron Jeffries who failed to solve that?
|
| I think that says more about the person at the keyboard and
| their lack of familiarity with the solution space than
| anything about TDD per-se. You still need insight and design
| with TDD, blind incrementalism was never a good idea.
| Crenshaw2 wrote:
| I agree.
|
| I have used TDD professionally in several development
| teams. It's useful in the right team. TDD works well when
| you are not too dogmatic about it. As with everything, you
| need people in the team that are experienced enough to know
| when and where. I think the same is true for any tool,
| coding standard, best practice or what have you. You have
| to know when to deviate.
|
| I've also held entry courses at university level teaching
| introductory programming. I believe that TDD can be a good
| tool teaching programming. Students tend to sit down and
| write a complete program and then start debugging. TDD
| teaches them to write small bits at a time and test as they
| go.
| wglb wrote:
| What UB's description of how to do TDD does not suggest
| that there are problems that require a different level of
| thinking and TDD as he describes, does not account for
| that.
| zamalek wrote:
| > Java is not object oriented.
|
| Java _technically_ isn 't OO in the strictest sense
| (Smalltalk, Ruby). It is OO in the modern sense (where modern
| >= 1980s, C++). Though I am not sure if this is what Bob is
| referring to - I don't have any respect for the man or his
| ideas, so my biased guess is his definition of OO is shared
| only between him and his fans.
| fuzztester wrote:
| >But if my memory serves me correctly, his book about C++
| (Designing Object-Oriented C++ Applications Using the Booch
| Method) has some excellent parts.
|
| If _my_ memory serves me correctly, Grady Booch himself had a
| book with roughly the same title, except that his name would
| not be in the title, of course, but would be there as the
| author. I think I read a good amount of it long ago, and
| liked it.
|
| Edit: I googled, the book is mentioned here under the section
| Booch method :
|
| https://en.m.wikipedia.org/wiki/Grady_Booch
| tqwhite wrote:
| Bob's had a long life with too much success. He really
| believes in himself. But, I have to say that the other guy
| was aggressive and bad even though I am more inclined to
| agree with him. He willfully misrepresented Bob's ideas. I
| thought he presented more misguided certainty than Bob. No
| Bueno.
| usefulcat wrote:
| The "other guy" is John Ousterhout, author of the Tcl
| scripting language.
|
| Although I can see why you might consider him more
| "aggressive", I personally think it matters much more that
| he was, in general, far more descriptive of his reasoning.
|
| Merely having an opinion is the easy part; being able to
| clearly articulate the reason(s) _why_ one has a particular
| opinion is far more important, especially in this kind of
| conversation, and I in that regard I repeatedly found UB
| lacking.
| iterateoften wrote:
| The worst engineer I worked with was one who believed if he
| read it in a book, that opinion trumped anything else. Once he
| got so flustered he started yelling "come back to the
| discussion when you've read 13 books on this topic like me!"
| And it was something super mundane like how to organize config
| files or something.
|
| Made every engineering planning session a pain in the ass.
| renewedrebecca wrote:
| The place I used to work at had a "architect" who would for any
| question to a decision he made would refer to whatever it was
| as a "best practice."
|
| Was often quite wrong and always infuriating.
| dominicrose wrote:
| Square people are never going to agree with cool people. You
| can be cool and code some monstruosity or you can be square and
| say "we have to rebuild this entire project from scratch"
| everytime you see a long method.
| trevor-e wrote:
| I cringe thinking about PR comments I left early in my career.
|
| "akshually this should try to follow more SOLID principles"
|
| But, coming from a formal engineering background, I thought
| this is what it meant to be a professional software engineer.
| Little did I know these "principles" were just the musings of a
| consultant lol. Turns out most folks have good intentions and
| want a standardized way to write code, but for some reason it
| always results in code that looks like the Enterprise FizzBuzz
| meme repo.
| mp05 wrote:
| The mark of a good engineer is knowing when this sort of
| handwaving is actually meaningful and helpful. Formality for
| its own sake is anti-pattern, but who am I telling?
| sunrunner wrote:
| For some reason in software there seems to be an incredibly
| large space for non-evidence based thinking and belief
| systems.
|
| I wonder if that's because in a lot of cases (depending on
| the domain) the space of possible valid/working solutions is
| near infinite, and if you don't have hard requirements that
| are backed up by measurements you're free to concieve of any
| valid system structure and justify it as 'better' without
| that ever being something that can be observed and measured.
| Aurornis wrote:
| > For some reason in software there seems to be an
| incredibly large space for non-evidence based thinking and
| belief systems.
|
| The secondary problem is that book authors have become
| extremely good at inventing pseudo-evidence to support
| their claims. It most commonly takes the form of "I talked
| to X companies with Y total number of employees over Z
| years and therefore I know what works best".
|
| If you cut out all of the grandstanding, it's nothing more
| than "just trust me" but in a world of social proof it
| sounds like it's undeniable.
| sunrunner wrote:
| > a world of social proof
|
| Which results in the idea of 'good practice', 'best
| practice' and 'bad practice', and nobody wants to be seen
| as the person doing things that are considered bad
| practice, because that would imply that you're a bad
| developer.
|
| And I almost always hesitate to use the term 'engineer'
| because as far as I know engineering is considered to be
| a practice/process that uses measurements and results to
| drive decision-making, unlike various areas in software.
| Can you imagine if the same kind of thinking was applied
| in civil engineering? "This new material has a lot of
| stars on GitHub and everyone is saying the old materials
| are bad practice."*
|
| * Which is a thing of course (see: Asbestos) but only in
| the places with measurable observable outputs.
| jsbg wrote:
| > Who else has had to deal with idiots who froth at the mouth
| when you exceed an 80 line character margin?
|
| Not once in my 11 year career. But almost every codebase I've
| worked on has had debilitating maintainability issues because
| the only principle other engineers seemed to follow was DRY, at
| the sacrifice of every principle in SOLID.
| nuancebydefault wrote:
| Most code that i clean up is a lot easier to maintain after
| making it a lot DRYer.
|
| The point is not about being DRY, on itself, though. The
| point is that the code then has better abstractions which are
| easy to reason about.
|
| UB seems to take abstractions a lot too far, replacing e.g. 2
| lines of very clear code with some cleartotals abstraction.
| TeMPOraL wrote:
| clearTotals() arguably made more sense than other
| "abstractions", on the grounds that if you have more than
| one piece of state to reset/initialize, you want to
| centralize the knowledge of _which variables_ must be set
| together - otherwise it 's too easy to add another piece of
| state and forget to set it everywhere it should be.
|
| Of course, a method is but one of several ways you could
| capture that information, and not always the best one.
| jsbg wrote:
| DRY is about ensuring that the same code doesn't have to
| change in two places because the engineer changing it in
| one place might not know that. But so many applications of
| DRY mindlessly violate the single responsibility principle
| and create coupling where there shouldn't be.
| Aurornis wrote:
| > It still blows my mind how dogmatic some people can be about
| things like this. I don't understand why anyone takes these
| things as gospel.
|
| I love reading books for different perspectives.
|
| However, I've come to despise people who read books and then
| try to lord their book knowledge over others. These are the
| people who think that they have the upper hand in every
| situation because they read some books. They almost always
| assume you haven't read them. If you point out that you have
| also read them, they switch the subject to another set of books
| they read because they don't like when someone tries to
| undermine their book knowledge superiority.
|
| It's even worse when the person reads books outside of their
| domain and tries to import that book knowledge into the
| workplace. The absolute worst manager I had was a guy who read
| a lot of pop-psychology books and then tried to psychoanalyze
| each of us according to those books.
| DeathArrow wrote:
| For many C#, Java and C++ engineers Uncle Bob is their savior
| and GoF are the apostles.
|
| Everything should follow SOLID and clean principles and be
| implemented using design patterns.
| jayd16 wrote:
| Game devs out here catching strays.
| monksy wrote:
| Good. The code I've seen from Game devs, the bad practices
| justified, and the ego is excessive.
| neonsunset wrote:
| Which is unfortunate as there are no (legitimate) reasons to
| write C#, a multi-paradigm language, like this.
| progmetaldev wrote:
| One of the best things I could do for myself is to go back in
| time and tell my younger self not to care so much about the
| "right" design pattern, or the perfectly DRY way to represent
| a piece of code. I was definitely my worst enemy for a long
| time, because I thought SOLID and the GoF design patterns
| were more important than writing code that is easy to
| understand without hopping across multiple files in case one
| day in the future your system needed to do something totally
| different with a new database or filesystem, etc. I started
| to look for places to add design patterns, rather than
| letting them develop naturally. Most of the software I built
| had no need for such heavy abstraction and complexity, and
| I've only ever had to switch database systems twice ever in
| 20 years, and the abstraction did not help reduce time or
| complexity all that much in the end. It definitely wasn't
| worth the up front planning compared to just rewriting the
| sections that directly handled the database.
|
| Maybe it's a right of passage to burn yourself badly enough
| over-architected solutions, where you finally start to
| understand you don't need all the complexity. Write the code
| for humans, as simple as you can. Keep large performance
| issues in mind, but only code around them when they become a
| problem or are extremely obvious. If anything, it's helped me
| to steer junior developers away from complex code, while
| encouraging them to try it out in their own time. Go ahead
| and figure things out on your own, but let's not do it on a
| shared codebase, please?
| soulofmischief wrote:
| On my Macbook Pro M2, having a browser window on one half of
| the screen, and my IDE on the other, with a file tree viewer
| pane and another pane for my LLM tools, a terminal pane at the
| bottom... I've never been more pressed for real estate for my
| actual code editing pane. Even 80 chars has me scrolling
| horizontally. Secondary monitors help but not when you
| frequently work away from your desk.
| ajross wrote:
| Coding on a laptop, even a name-drop-tier status shibboleth,
| is most of your problem. You write code on a 15" screen when
| you must for physical/location reasons. You shouldn't ever
| choose to do it or design your workflow around that
| constraint.
|
| A 42" 4k TV (got it for $2-300 at the start of the pandemic)
| gives me four 80-90 column text windows on a mid-tier
| chromebook. You could not pay me enough to do that same work
| on a laptop, even a $4k MBP.
|
| (But yes, even with lots of real estate 80 columns is still a
| net win)
| soulofmischief wrote:
| I have a 120" 4K monitor at home, and a 40" 2K. However,
| that entirely misses the point of my comment, which is that
| I am frequently away from my desk while working. I'm not
| sure what point you were trying to make.
| cluckindan wrote:
| Invest in the Vision Pro. It will change your life.
| soulofmischief wrote:
| I was also looking at the XREAL Air 2 Ultra, seems more
| practical for travel, but the idea of an ultrawide screen
| sounds really nice. I might take your advice.
| 0x20cowboy wrote:
| This is just how junior and intermediate devs behave. It's like
| a goth phase or something.
|
| It goes along with being into BJJ, chess, vim, keto, linters,
| and "the dominance hierarchy".
|
| It's annoying, but most everyone went through it. If you didn't
| know better, how could they?
| kragen wrote:
| Crucial context here: Ousterhout is one of the great programmers
| who built the free software world we live in today, and Uncle Bob
| is a faker. Ousterhout is not without his problems (Stallman
| famously called him a "parasite" on the free software community,
| as well as fervently disagreeing with his technical taste) but
| he's written truly world-changing software. By contrast, Uncle
| Bob is a windbag book author who has never managed to write any
| software worth using, to my knowledge.
|
| Ousterhout to Uncle Bob:
|
| > _maybe you were surprised that it is hard to understand, but I
| am not. Said another way, if you are unable to predict whether
| your code will be easy to understand, there are problems with
| your design methodology._
|
| This debate is full of treasures like this. What a brilliantly
| clear and understated way to expose charlatanism!
|
| What is this "world-changing software" I'm saying Ousterhout has
| shipped? Tcl. (Hold on, now, don't downvote just yet.) Tcl has
| been a crucial enabling technology for EDA and automated
| regression testing since literally the 01980s. Probably every
| VLSI chip in the computer you're reading this on was designed,
| verified, and tested with workflows involving unholy amounts of
| Tcl. GCC's test suite is also Tcl. Still.
|
| Automated testing in the 01980s? Yes. It's true that automated
| testing wasn't very prevalent in the software world until the
| Agile guys (Uncle Bob and his less incompetent compatriots)
| popularized it around the turn of the century, but EEs and
| compiler engineers have been pervasively automating testing a lot
| longer than that, and Tcl was for a long time the least awful
| option, believe it or not. And that was John Ousterhout's doing.
|
| Do you know what the SPICE developers did to make SPICE
| scriptable, before there was Tcl? They linked csh into it.
| Motherfucking _csh_. If you 've never tried to maintain a large
| script in csh, you do not know the meaning of suffering.
|
| Good programmers write good software; bad programmers write bad
| software, or no software. Ousterhout has written one of the few
| pieces of software that can be called great. (In its historical
| context. In 01978 csh was great software too.) What software has
| Uncle Bob written?
|
| Listening to Uncle Bob's programming advice over Ousterhout's
| would be like listening to your middle-school English teacher's
| writing advice instead of Stephen King's. It's not that King
| could never give you worse advice, but if you need your English
| teacher's advice, generally your judgment will not be good enough
| to distinguish the rare occasions King gets it wrong.
| WillAdams wrote:
| Curious what Stallman has to say about Robert C. Martin ---
| looked, but couldn't find anything....
| kragen wrote:
| Not about Martin. About Ousterhout. 27-30 years ago.
| WillAdams wrote:
| Right, I was curious if _in addition to_ that well-known
| comment there was an evaluation by Stallman of Bob Martin
| extant.
| kragen wrote:
| Unlikely. He mostly confines himself to commenting on
| political issues:
| https://www.stallman.org/archives/2024-nov-feb.html
| cmacleod4 wrote:
| I'ma big Tcl fan, but Ousterhout has created many other
| important things - see
| https://en.wikipedia.org/wiki/John_Ousterhout .
| okaleniuk wrote:
| It's sad that we demoted the field from engineering to
| philosophy. But it is what it is.
|
| Next step - fashion and belief.
| WillAdams wrote:
| It's an improvement over demagoguery and blind rule-following.
|
| Moreover, the book argues for engineering principles (in pretty
| much all possible senses of that phrase).
| okaleniuk wrote:
| Sure!
|
| I'm not saying that philosophy is bad. Maybe making software
| just never meant to become an engineering discipline. I mean
| making clothes, laws, and music isn't. And it's fine.
|
| But engineering does imply some rule-following.
| floydnoel wrote:
| philosophy is the basis of reason, math, and science. it's sad
| that "engineers" don't understand it or it's import.
| okaleniuk wrote:
| Engineers believe in definitions. By definition, philosophy
| is not a scientific discipline, because as soon as a
| discipline becomes scientific it... stops being philosophy.
|
| As Alexander Pyatigorsky famously wrote, "the value of
| philosophy is in that nobody needs it".
| cjfd wrote:
| PDSD is correct on length of methods. The methods given in an
| example in CC are ridiculously short. CC is more correct on
| comments than PDSD. Especially mandating comments in certain
| places leads to very low quality and, frankly, utterly disgusting
| comments point out, helpfully that the 'get_height' method 'gets
| the height'. CC is more correct on TDD than PDSD. The noticed
| danger of just focussing on implementation details over the
| structure of the API is always there but TDD has a refactor step
| to fix that. The general idea of working in small steps with
| there being a safe state between every small step is worth its
| weight in gold.
| samiv wrote:
| Instead of "Clean Code" I'd really suggest people read either
| - Code Complete - The Pragmatic Programmer
|
| https://en.wikipedia.org/wiki/Code_Complete
|
| https://en.wikipedia.org/wiki/The_Pragmatic_Programmer
| kragen wrote:
| I wouldn't recommend _Code Complete_ today; I think _The
| Practice of Programming_ covers most of the same material, is
| much shorter, is much better written, and isn 't tainted by
| McConnell's later embrace of snake-oil methodologies, some of
| which made it into the second edition of CC. TPOP didn't exist
| when CC changed my world.
| bena wrote:
| It's been a hot minute since I've read Code Complete. I don't
| have it on hand, but I'm pretty sure it was the second
| edition as it has the gray cover. And I'm pretty sure I got
| the second edition closer to when it was published than
| today.
|
| I remember it being pretty decent back in the day. I can't
| remember any takes that were too hot in it. Honestly, I can
| only remember a general sense of satisfaction(?) with the
| book. If you were to ask me what exactly I took from Code
| Complete and applied in my job today, I couldn't tell you.
|
| What would you classify as "snake oil" in it? Do they
| recommend Hungarian notation or something weird?
| kragen wrote:
| I read some of the more questionable parts of the second
| edition just now, and while I think there are a lot of
| things to criticize in it, I suspect that it's just rose-
| tinted hindsight, or ignorance, that made me not object to
| them in the first edition; I'm pretty sure most of these
| problems were already there:
|
| - All the time wasted on the dumb "construction" analogy.
|
| - The total lack of attention to open-source software,
| possibly because there's no such thing as a freely
| redistributable cabinet that's extra reliable because your
| house shares it with the local nuclear reactor, or a rotten
| floor joist you can't fix without negotiating a source
| license. (He does discuss _buying_ libraries.) Though this
| was surely also lacking in the first edition, it was a more
| forgivable oversight in 01994.
|
| - Very little attention given to automated testing; we
| don't get to "developer testing" until chapter 22, though
| there are a few offhand remarks in SS4.4 and SS9.4 about
| unit testing, with no explanation of what that means.
| Again, this was a more forgivable oversight in 01994.
|
| - Also, nothing about source control. Understandable in
| 01994, irresponsible in 02004, unthinkable today.
|
| - Although he pays lip service at the beginning of the book
| to the independence of project _phases_ and project
| _activities_ , he often conflates them later, often
| presuming a quasi-waterfall model (when he isn't outright
| advocating it), where a requirements-analysis phase is
| followed by an architecture phase, then a detailed design
| phase, then a "construction" phase, then a testing phase,
| and then finally a maintenance phase. This is obviously
| completely unlike the reality of projects like Microsoft
| Windows, Emacs, Linux, GCC, and Facebook. When did Facebook
| mostly move from detailed design to construction? Would it
| have been a better social-networking website if it had
| spent a year or two on architecture before beginning
| "construction"? He does kind of go back and forth on this a
| lot, though, sometimes advocating more incremental
| approaches and then contradicting himself a page later.
|
| - Relatedly, he advocates a division of labor where "the
| architect consumes the requirements; the designer consumes
| the architecture; and the coder consumes the design."
| (Traditionally, though he doesn't say this, the QA tester
| then consumes the code.) This division of labor has been
| tried many times, and the companies that have tried it have
| been mostly outcompeted by companies with less
| dysfunctional divisions of labor; they mostly survive only
| in niches where they have legally enforceable monopolies,
| such as DoD cost-plus prime contractors. None of them have
| been able to produce products of quality comparable to
| things like Linux, GCC, and Facebook. I think this is the
| snake-oiliest part of the book.
|
| - _Code Complete_ 's table of "Average Cost of Fixing
| Defects Based on When They're Introduced and Detected",
| table 3-1, is convincing, compelling, thoroughly footnoted
| with decades of literature, and completely made up. See htt
| ps://softwareengineering.stackexchange.com/questions/1637..
| . https://web.archive.org/web/20121101231451/http://blog.se
| cur... https://www.lesswrong.com/posts/4ACmfJkXQxkYacdLt/di
| seased-d... https://gist.github.com/Morendil/258a523726f187
| 334168f11fc83.... This made-up data is McConnell's major
| justification for advocating waterfall-like models. More
| recent research that investigates the question empirically
| instead of relying on made-up hearsay finds, by contrast,
| "We found no evidence for the delayed issue effect; _i.e._
| , the effort to resolve issues in a later phase was not
| consistently or substantially greater than when issues were
| resolved soon after their introduction."
| https://arxiv.org/pdf/1609.04886
| https://agilemodeling.com/essays/costofchange.htm
| https://buttondown.com/hillelwayne/archive/i-ing-hate-
| scienc....
|
| - The section about "user interface design" is cringe-
| inducingly bad. He thinks you can design a good user
| interface up front without having working software ("The
| user interface is often specified at requirements time. If
| it isn't, it should be specified in the software
| architecture,") rather than incrementally responding to
| usability feedback from people using a working system. It's
| a very short section, and that in itself is eyebrow-
| raising; usability is a central concern of most kinds of
| software, and one of the most challenging aspects of
| software. Really, almost everything in most software should
| be driven ultimately by user experience and grounded out in
| usability testing. Games, websites, browsers, and even
| compilers live and die on usability. But McConnell treats
| it as one minor detail among many.
|
| - The section about the "architecture prerequisite" sounds
| like it was written by IBM mainframe programmers in 01978,
| then decorated with some OO and WWW jargon. Yes, clearly
| the architecture should "describe the major files and table
| designs to be used". That makes sense. Yes, "Input/output
| (...) is another area that deserves attention in the
| architecture. The architecture should specify a read-ahead,
| read-behind, or just-in-time reading scheme." I mean,
| _seriously_? Note that words like "client", "server",
| "tier", "cache", "protocol", "network", "message", "queue",
| and even "process" are completely missing here. It's not
| that he uses different terms for them; he just doesn't talk
| about them at all, using any words.
|
| - He tries to discuss "fault tolerance" with a totally
| nonsensical example "the square root of a number",
| necessarily making complete hash of the topic as a result.
| He doesn't mention _any_ of the techniques that actually
| work for achieving fault-tolerance, such as statelessness,
| idempotence, the end-to-end principle, transactions,
| journaling, fail-stopness, checksums, disk mirroring,
| hardware trimodular redundancy, watchdog timers, ECC,
| anomaly detection, network timeouts, monitoring, alarms,
| etc. The only exception is that he sort of mentions
| granular restarts. I 'm restricting myself to techniques
| that were well-known when he wrote the first edition of the
| book here, excluding things like Paxos, eventual
| consistency, and Merkle graphs.
|
| - There are a lot of cases where he repeats something he's
| heard that he evidently doesn't understand. The muddled
| attempt to explain fault tolerance above is one example,
| but we could also mention, for example, his attempt in
| SS4.1 to describe Fortran programmers writing Fortran in
| C++, which completely misses the actual major difficulty
| (it's mostly about structuring the data as arrays, not the
| control flow), or his remark, "Assembler is regarded as the
| second-generation language," devoid of the historical
| context to provide any meaning to it.
|
| - One thing that I think is actually new in the second
| edition is its presumption that all software is object-
| oriented (despite paying lip service to the fact that
| Visual Basic [6] was the most popular language among
| professional programmers, many people were still
| programming in Ada and assembly and Cobol and C and
| Fortran, etc.) and that looks a bit snake-oilier from our
| perspective now than it did at the time. I think OO is a
| useful approach to software design, but if I'm writing a
| generic tutorial on how to design a program, I wouldn't
| have a step in it called "Level 3: Division into Classes"
| as McConnell does in SS5.2, because that makes my book
| completely inapplicable to programming in C, Go, Fortran,
| Rust, Racket, VB6, or Clojure, and inapplicable to much of
| what people do in Python, PHP, JS, Octave, and R. The snake
| oil here is not object-orientation but a totalizing
| ideology that everything _must_ be OO; the Chapter 6
| introduction says, "In the twenty-first century,
| programmers think about programming in terms of classes.".
| The way I remember it, the first edition didn't have this
| problem.
|
| - This totalizing OO outlook is somewhat exacerbated by the
| fact that he doesn't really understand object orientation
| at all, so he gives a lot of bad advice, like, "A large
| percentage of routines in object-oriented programs will be
| accessor routines, which will be very short," SS7.4. His
| whole chapter 6 is about designing classes, but he never
| mentions the actual core concept of object-orientation,
| which is polymorphic message sends, presumably because
| although he knows they exist, he isn't really comfortable
| with them and doesn't understand how central they are to
| the OO worldview. Instead he treats classes as a newfangled
| synonym for CLU's "clusters" or Ada "packages". Much of the
| chapter is devoted to workarounds for shortcomings of C++.
| This isn't really "snake oil," just incompetence.
|
| There's still much material in the book that's solid, and
| lots of references to good information, but it's mixed with
| a lot of serious misinformation, misleading analogies, and
| embarrassing incompetence. And it's a slog to get through
| so much verbiage. But it's certainly better than _Clean
| Code_. Still, now that _The Practice of Programming_ , _The
| Pragmatic Programmer_ , and _A Philosophy of Software
| Design_ are out, I think there 's no longer any reason to
| recommend _Code Complete_.
| mrkeen wrote:
| I read Clean Code and don't remember a single thing from it. To
| be fair it was a while ago.
|
| But the SOLID and Clean Architecture principles inform me
| almost daily.
| donatj wrote:
| I have worked with a couple of people over the years who instead
| of breaking functions out when something would say make sense to
| be reused or made some sort of logical sense as a unit, instead
| seemingly just bundle lines whose only real relationship was that
| they happened to be near each other when they decided to
| "refactor".
|
| Having read Clean Code back in college as it was assigned
| reading, it was absolutely the vibe I got from Uncle Bob
| generally. See any number of lines at the same indentation level,
| select them, extract method, name it vaguely for some part of
| what it does, repeat.
|
| I honestly think that it comes from this type of school of
| thought that a function should be X lines rather than a function
| achieving a _function_. Thinking about this now, it 's sort of
| the difference between "subroutines" and "functions".
|
| Working on their code, I thank god for modern IDEs ability to
| inline. I often go through and restructure the code just to
| understand the full scope of what it's doing, before restoring
| what I can of the original to make my changes as minimal as
| possible.
| zelos wrote:
| The warning sign I see when methods are split too much is that
| the method boundaries start to get messy: methods take too many
| arguments, or state is saved into confusingly named class
| members, or you end up returning some struct containing a grab
| bag of unrelated values.
| donatj wrote:
| All of this all the time
| kraftman wrote:
| It's been a long time since I've read the book but I took it to
| be less 'cut the function at X lines' and more 'long functions
| tend to be doing too many things at a time'. I think if you're
| able to give a good name to some sub section of a function,
| it's a good sign that it can be extracted out. At that point,
| you shouldnt need to look at the functions implementation
| unless its the specific function that you want to modify,
| because its name and arguments should be enough to know what it
| does and that you don't need to touch it.
|
| Are we talking about the same thing and you'd still find that
| hard to understand?
| ArchieMaclean wrote:
| My take on the prime example: import itertools
| def generate_n_primes(n): """ Generate n
| prime numbers using a modified Sieve of Eratosthenes.
| The algorithm keeps track of a list of primes found so far,
| and a corresponding list of 'multiples', where multiples[i] is a
| multiple of primes[i], (multiples[i] is initially set
| to be primes[i]**2, see the optimisations section below).
| The main loop iterates over every integer k until enough primes
| have been found, with the following steps:
| - For each prime found so far - While the
| corresponding multiple is smaller than k, increase it by steps of
| the prime - If the multiple is now the same as k,
| then k is divisible by the prime - hence k is
| composite, ignore it. - If, for EVERY prime, the
| multiple is greater than k, then k isn't divisible by any
| of the primes found so far. Hence we can add it to the prime list
| and multiple list! There are a few
| optimisations that can be done: - We can insert 2
| into primes at the start, and only iterate over every odd k from
| there on - When we're increasing the multiple, we can
| now increase by 2*prime instead of 1*prime, so that
| we skip over even numbers, since we are now only considering odd
| k - When we find a prime p, we add it to the prime
| and multiple list. However, we can instead add its
| square to the multiple list, since for any number between p and
| p**2, if it's divisible by p then it must be
| divisible by another prime k < p (i.e. it will be
| caught by an earlier prime in the list) """
| # Insert 2 into primes/multiples primes = [2]
| multiples = [4] # Iterate over odd numbers
| starting at 3 for k in itertools.count(3, 2):
| # If we've found enough primes, return! if
| len(primes) >= n: return primes
| # For each prime found so far for i in
| range(len(primes)): # Increase its
| corresponding multiple in steps of 2*prime until it's >= k
| while multiples[i] < k: multiples[i] += 2
| * primes[i] # If its corresponding
| multiple == k then k is divisible by the prime
| if multiples[i] == k: break
| else: # If k wasn't divisible by any prime,
| add it to the primes/multiples list
| primes.append(k) multiples.append(k ** 2)
| return primes
|
| Some might find the docstring as well as comments too much - I
| find the comments help relate the code to the docstring. Open to
| suggestions!
| aswerty wrote:
| While I enjoyed the discussion as an exercise in stripping back
| positions to underlying principles. I find it a great irony that
| the overarching reason why they diverge on what is "good
| practice" is not discussed.
|
| John sounds like he is about to start building a new type of
| database, and Bob sounds like he's knee deep in a 20 year old
| code base for a logistics company. Both of their positions are
| reasonable, and both optimized for specific contexts.
|
| I found Bob's responses more measured (which I value a lot), with
| John's at times being more compelling. I do agree that over-
| composition is a real problem that Bob is on the wrong side of
| the line on. But to be fair, Bob and Clean Code comes from a time
| where it was the opposite and his position on this feels like a
| philosophy that has an over-correction (albeit - not necessarily
| a flaw) at it's core.
| ptx wrote:
| UB says at one point:
|
| > _Would that we had such a crystal ball_
|
| And then it seems like he actually found his crystal ball,
| because in the very next question he refers to things that have
| not yet occurred in the conversation:
|
| > _interpreting your rewrite (below)_
|
| And later:
|
| > _In your solution, which we are soon to see below_
|
| This makes it somewhat confusing to read, with answers being
| based on counterpoints that will only have been made in the
| future. (Which, I suppose, is similar to the problem Ousterhout
| has with UB's PrimeGenerator example.)
| bonsaiKiller wrote:
| There's obviously a balance. Having worked in both environments,
| I tend to appreciate the code of someone who at least read the
| books, but treats it as suggestion rather than gospel. Contrast
| to someone who never read the books, has no clue what's "good"
| and hacks everything.
|
| On the one hand, the books are popular because a lot of people
| reading them think it makes a good point, and share that view. On
| the other hand, just because something is popular doesn't make it
| right! I think this is where AI gets so much wrong. GIGO! If you
| base all your code on whatever is most common, are you really
| really sure that common pattern is really the best? AI, and these
| book evangelist, often have no clue. Just parroting others.
|
| I'd rather deal with "principles" as opposed to "rules" every
| time. Glean the principles from the books, and at least try to
| write clean code!
| bob1029 wrote:
| I'm currently dealing with one of those codebases representative
| of the consequences of blindly following "Clean Code", et. al.
|
| My experience has taught me that you never want to be the first
| person to recommend a rewrite. Since I am a mere contractor on
| this one, I am strongly inclined to let it unwind on its own.
| There seems to be a lot of ego embedded in those pointless data
| access layer wrappers. I'd hate to get on someone's bad side
| right now. The market is quite rarified.
| bluGill wrote:
| Rewrite is only useful it you get something else that you can't
| get otherwise. Mixing Rust and C++ in a project is hard but
| doable - odds are if you try it you will find enough "friction"
| that eventually it will be worth rewriting to get rid of one.
| sam_bishop wrote:
| One of my beefs with Clean Code is its name.
|
| There is no objective measure of code cleanliness. So if "clean
| code" is your goal, then you have no meaningful criteria to
| evaluate alternatives. (Including those pitched by Bob Martin.)
|
| It gets worse, though. There's a subconscious element that causes
| even more trouble. It's obviously a good thing to write "clean
| code", right? (Who's going to argue otherwise?) And to do
| otherwise would be a moral failing.
|
| The foundation on which "Uncle Bob" tries to build is rotten from
| the get-go. But it's a perfect recipe for dogmatism.
| bpicolo wrote:
| Honestly that kind of makes the word "clean" seem like a good
| fit to me. I can't say that measuring the cleanliness of my
| house is objective.
| jjice wrote:
| Lots of negative comments about Uncle Bob in this thread. I
| personally didn't like Clean Code and really enjoyed A Philosophy
| of Software Design, but I do think that some of his other books
| are really solid.
|
| I accept that non-fiction books on anything will oversell the
| value of their way, and try to take what I can at a more moderate
| level. Through that lens, Clean Code didn't give me much, but
| Clean Architecture did. The Clean Coder is also an interesting
| read on professionalism in software, and Clean Agile is an
| interesting read on Agile roots. I don't know anyone that
| practices "true" agile (nor do I care to do so myself), but there
| are some really solid ideas in there.
|
| I get that Clean Code kind of had a cult-like following in that
| people followed it blindly, but damn some of these comments are
| just rude about Uncle Bob. I still think he's a pretty good
| author and has given me some advice through his other books that
| helped me a lot as a fresh faced dev.
| mangodrunk wrote:
| Uncle Bob has been a horrible influence on our industry, and
| we're expressing that. He has not actually worked on anything
| but yet he's been able to make some money selling his
| inexperienced opinions.
| Hasu wrote:
| > I bemoan the fact that we must sometimes use a human language
| instead of a programming language. Human languages are imprecise
| and full of ambiguities. Using a human language to describe
| something as precise as a program is very hard, and fraught with
| many opportunities for error and inadvertent misinformation.
|
| This quote from Uncle Bob is shameful, considering that he has
| made 100% of his career on writing _English_ , not code.
| WillAdams wrote:
| An interesting contrast to it is Ousterhout's observation:
|
| >If you can visualize a system, you can probably implement it
| in a
|
| >computer program.... This means that the greatest limitation
| in writing
|
| >software is our ability to understand the systems we are
| creating.
|
| Though interestingly it is in marked contrast to a different
| statement in the "Software Design Book" Google mailing list:
|
| >John Ousterhout, Aug 21, 2018, 12:30:15 PM
|
| >I've never felt that graphs are a particularly useful way of
| describing software structure.
|
| >The interactions between classes end up so complicated that
| the graph becomes an unreadable mess.
|
| >Also, I'm not sure that the complexity of a graph
| representation of software correlates with its
|
| >practical complexity (the graph representation might look very
| complicated, but the software might
|
| >still be pretty easy to maintain).
|
| and I'd be interested if someone knows of a
| text/video/interview which resolves that twain, or what sort of
| visualization is advocated for/recommended.
| Izkata wrote:
| Structure graphs are rarely useful for me, but visualizing
| the data flow is how I think about code in general. Sometimes
| it's graph-like, but more wishy-washy and I'm only holding
| the relevant parts for the task at hand in my head rather
| than everything.
| loganmhb wrote:
| Plenty of people are ragging (justifiably) on Clean Code, but I
| really admire by contrast Ousterhout's commitment to balanced
| principles and in particular learning from non-trivial examples.
| Philosophy of Software Design is a great and thought-provoking
| read.
| cowboylowrez wrote:
| Philosophy of Software Design seemed more pragmatic to me.
| 0xbadcafebee wrote:
| > For me, the fundamental goal of software design is to make it
| easy to understand and modify the system. I use the term
| "complexity" to refer to things that make it hard to understand
| and modify a system.
|
| This explains everything that's wrong with modern software.
|
| When you design a Formula 1 race car engine, the purpose of
| engine design is not to "make the engine easier to modify". It's
| to win races. And that depends on the race - a funny car engine,
| a formula 1 engine, a LeMans engine, Nascar engine, etc, are all
| different because the races are different.
|
| Another example: when you design a building, the goal isn't to
| make it easier to understand the building. The goal is to meet
| the requirements of the building, its uses, requirements,
| environment, etc. Sometimes a better building is just more
| complicated, and making the architect or builders' jobs easier,
| while nice, isn't the goal.
|
| Some things aren't supposed to be easy to understand, because
| ease of understanding is not the goal of the thing. Focus on the
| real goal of the thing, and achieving that; don't get distracted
| by ancillary goals.
| kraftman wrote:
| Most people aren't building Formula 1 cars. Buildings are a
| better analogy: they are designed to be maintained. You can
| replace a door handle without replacing the door or the wall,
| you can turn off the power to different sections to do repairs.
| Dangerous or complex parts are labelled, moved into their own
| rooms or cupboards, and locked.
| allemagne wrote:
| A genius architect/Formula 1 engineer can design a
| building/engine that fits all the requirements astonishingly
| perfectly, but if the builders have difficulties understanding
| it, or later contractors can't figure out how to maintain or
| fix anything, then it's only a perfect design in theory and an
| awful design in reality. It's not a nice-to-have to make
| people's lives a little easier, it defines the success of the
| project. The genius architect/engineer can insist that the
| complex design reflects the underlying domain as much as they
| want but at some point they will have to back that up to
| someone else who isn't a genius.
|
| Obviously, writing code such that a first year comp sci student
| can understand what's happening and can start contributing
| immediately is absurd, but at the same time nobody builds
| anything in a vacuum. There's a certain legibility required
| within any context you're designing something for.
| kragen wrote:
| Software is unusual in that it's never finished. This makes
| ease of modification a critical quality of software in a way
| that it isn't for Formula 1 race car engines or most buildings.
|
| Ease of modification _was_ one of the top priorities in the
| design of the Model T Ford, because cars break down and must be
| repaired, and a car that is difficult or impossible to repair
| will cost its owner large sums of money. Software doesn 't
| break down (though online services do) but for other reasons
| modification is a high priority.
|
| Perhaps short-lived buildings don't need to be easy to modify,
| especially if the architects have a very good understanding of
| the needs of the users over their lifetimes. Often that is not
| the case, though, and Christopher Alexander was famous in large
| part because much of his career was devoted to figuring out how
| to enable inhabitants of buildings to modify them more easily,
| so that their needs would eventually be met even if the
| architects guessed wrong decades in the past. Centuries-old
| stone farmhouses exist, too, and ease of modification is
| crucial for them; if they cannot be modified they cease to
| function in only a century or two at most.
|
| Whatever the goal of your software, it is crucial for the
| people who are modifying it over time to achieve that goal to
| be able to understand it.
| jpitz wrote:
| "Do One Thing" is to me maybe best understood in the context of
| the Single Layer Of Abstraction Principal - it has helped me
| numerous times to be very intentional about following SLAP in
| complex code, and Do One Thing seems to fall very naturally out
| of it.
| nadam wrote:
| I was just thinking about what AI assisted coding brings to the
| design discussion, especially as AI become more and more powerful
| and we rely on it more and more. You still want to make things
| modular and easy to understand so that AI understands it easily
| and the needed info to modify a module can fit in a relatively
| small context window, but the difference is that it is very easy
| to make large scale measurement about which code style is
| understood better by an LLM, so maybe some of these debates will
| be decided relatively objectively!
|
| For the topic: the discussed topics are relatively trivial
| surface level stuff, mostly I agree with POSD, but these will be
| handled by AI anyway. I guess humans will use the spare brain
| capacity to deal with the real deep design questions (for a
| while).
| zzzeek wrote:
| I've been programming since the early 80s and have never seen
| real world, production code that was done in so-called "clean
| code" style
| spacechild1 wrote:
| IMO the "PrimeGenerator" example from Clean Code is horrendous
| and completely unreadable! This would be so much better as a
| single method/function with a few interspersed comments that
| explain the algorithm. I mean, just look at this abomination:
| private static boolean isMultipleOfNthPrimeFactor(int
| candidate, int n) { return candidate ==
| smallestOddNthMultipleNotLessThanCandidate(candidate, n); }
|
| Not only is the method itself completely pointless, it also
| happens to have side effects! Who would expect this from the
| method name? So much for self-documenting code... Ousterhout
| rightfully calls him out on this bullshit.
|
| In fact, Ousterhout makes such great points that I really want to
| read his book. Conversely, I'm now even less inclined to read
| Clean Code.
| spacechild1 wrote:
| > This would be so much better as a single method/function with
| a few interspersed comments that explain the algorithm.
|
| I haven't read the whole article when I wrote that comment.
| Turns out that Ousterhout provides a rewritten version of
| "PrimeGenerator" that does exactly this. At least UB concedes
| that this version is indeed much better.
| pcblues wrote:
| On reflection, my attitude to books like these indicated where I
| was in my understanding of programming. They used to be useful
| life-buoys that one clung to for dear life early in one's career
| in a fast-moving and often-changing industry. Then they become an
| interesting side-note reminding one of what they clung to as the
| good precepts that served them well stand out from the rest of
| the books. And finally they become unnecessary and seemingly
| dogmatic when one has become adept at swimming. In other words,
| essential reading depending on where you find yourself :)
| Disclaimer: out of these two, I only read Clean Code.
| __mharrison__ wrote:
| This is actually a great read.
|
| I'm in the middle of designing a course for a client on teaching
| software engineering best practices for data scientists (and
| folks who live in Jupyter all day).
|
| There seems to be a huge lack of material for these types that
| aren't "programmers", don't live in an "IDE", and are essentially
| writing code all day.
| MetaWhirledPeas wrote:
| I think the reason most people have a problem with Uncle Bob is
| because they know their own practices are a far cry from his
| recommendations, and they take his prescriptive and
| uncompromising advice as a personal attack.
|
| I also wonder how many people interpret his advice as that of a
| mindless, pedantic dictator.
|
| My own introduction to UB was from some random YouTube video he
| made about programming languages, so my first impression of him
| included his humor and his ability to see both sides of an issue
| while being unafraid of having a strong opinion. I really enjoy
| speaking with and listening to people with strong, long-marinated
| opinions, regardless of whether I agree or not. At the very least
| it means they've put a lot of thought into it, which makes for
| better discussion and learning.
|
| I also lack a long history of code commits, being more of a
| dabbler here and there, so perhaps I have a smaller surface area
| for UB's jabs to land upon. Still, I acknowledge that a Clean
| Code Nazi would probably rip me to shreds for some of the
| practices I've followed and some that I continue to follow. But
| _improvement_ is a much more achievable goal than perfection, and
| gleaning valuable information is better than being dogmatic.
|
| In the end I _love_ listening to UB talk. I don 't follow all his
| practices but I _do_ keep them in the back of my mind. If not
| worth following strictly they are always worth considering,
| especially the intent behind them.
|
| So when I see his opinions on comments or his opinions on
| abstraction and variable naming my first instinct is not to
| lament about how he is poisoning our youth or insulting my code,
| but rather to ask myself how I can make use of his perspective.
| I'd encourage others to do the same; it's much more fun that way,
| not just for programming but for everything.
|
| As for those of you stuck in "Clean Code" hell with oppressive
| supervisors demanding strict adherence... that sounds like a
| personal failure, or a personal incompatibility, or both. I would
| blame the messenger there, not the message.
| jdmoreira wrote:
| Uncle Bob probably the biggest scammer in Software. What a
| complete pile of garbage. So much energy wasted in all these
| design patterns, SOLID and other OOP bullshit.
|
| Turns out you can just pass immutable data in and get immutable
| data out. Who would have guessed? The whole 90s - 00s Java OOP
| garbage still gives me nightmares
| ad_hockey wrote:
| Something I find odd about Uncle Bob's style is the preference
| for reading and modifying shared state over pure functions that
| take args. It makes me do a double take when I read a method
| registerTheCandidateAsPrime() (taken from UB's rewrite) that
| doesn't take a candidate arg.
|
| How would you unit test those methods? You'd have to directly set
| the field values, then call the method, then assert on the
| fields. If the answer is "you don't unit test private methods"
| then that's completely fine, because I agree with that (perhaps
| this is implicit from the private keyword, I don't know Java).
| But I'm struggling to imagine how you would get to those private
| methods with such a strict adherence to TDD as Bob recommends.
| Methods like increaseEachPrimeMultipleToOrBeyondCandidate() are
| quite complex, and would be tricky to build up using TDD if you
| couldn't exercise them directly.
|
| If nothing else, surely Bob's approach is not thread safe. Call
| PrimeGenerator3.generateFirstNPrimes() concurrently and they'll
| trample all over each other. John Ousterhout's stateless version
| doesn't have that problem.
| ben30 wrote:
| The primary goal of software design should be to facilitate
| understanding and modification for future developers, emphasizing
| the importance of code readability.
| beryilma wrote:
| "Uncle Bob" is not a software engineer (as he calls himself) and
| anything he says on the subject is theoretical at best, and snake
| oil at worst. Can anyone point to any substantial piece of code
| that he wrote before he can be taken seriously. The code pieces
| at his GitHub repos, other than style, etc., are just simplistic
| stuff.
|
| It is probably OK to be thinking on issues related to a field
| (i.e., software engineering) without being a practitioner in the
| field, but producing fads-du-jour and selling them as solid (pun
| intended) theories and expecting to be taken seriously is just
| ludicrous to me.
| pnt12 wrote:
| Some software gurus really grind my gears, and Robert Martin is
| one of them. When confronted with bad advice he gave, he's quick
| to say it's not meant to be taken literally. Then, gurus like
| Kent Beck, say that you cannot criticize their approaches if you
| don't implement exactly as they say. So, while this is not
| exactly a paradox (different people with different opinions), I
| feel like gurus make their livings on unfalsiable claims while
| shaping the world of software engineering.
|
| So, some kudos to Robert for accepting criticism and discussing
| it, but no cigar for downplaying his own advice when confronted -
| I also recall a different discussion, where someone confronts his
| statement "you don't practice tdd you're not a professional", and
| his answer "it was not meant to be taken seriously".
|
| These people had great ideas but they should be more critical of
| themselves, eg "here's when not to apply this", "here's where to
| bend this", not "you're doing it wrong" or "don't take it
| literally".
| dqft wrote:
| I don't understand how that works on people. Dog whistling,
| "Hey, hey, leave me to my grift."
| xiphias2 wrote:
| The more I tried to implement Clean Code, the more it helped me
| appreciate Worse is Better approach, which comes from an
| observation, not a dogma: while all programmers strive for
| simplicity both in implementation and interface, when they come
| into conflict, simple implementation usually wins over simple
| interfaces, as they are easier to modify.
|
| https://dreamsongs.com/RiseOfWorseIsBetter.html
| Applejinx wrote:
| It's always fascinating to me to see this subject talked about,
| because I've been programming for years in a niche field (audio
| plugin DSP development) and have interacted with Clean Code
| programmers, but I seemingly cannot grasp what they do at all.
|
| This is to the point that, in order to program and do the things
| I want to do, I have to essentially write nearly everything out
| longhand, to the point of unrolling things in repetitive fashion,
| and organizing things in blocks of code separated by comments
| about what's being done in each block. I can do this so
| predictably and regularly that my code gets parsed by other
| people's more Clean Code and ingested as sort of blocks of
| program behavior to be used in other software, to the point where
| it's an 886-star repo with 79 forks: not Bob-scale, but then I
| haven't written books or revolutionized corporate coding.
|
| I've had to learn useful things about where my approach doesn't
| take advantage of its hypothetical strengths: heedlessly
| unrolling everything doesn't give you speed boosts, and I've had
| to learn to declare variables nearer to where they're used. But
| I've also had to learn that I could do the opposite of Clean Code
| for performance gains. Back in the day, you could assign
| variables for calculations to avoid Repeating Yourself, but on
| modern processors it turns out... in addition to techniques like
| running calculations in parallel on wide data words that contain
| different data processed together... you can even take advantage
| of how eager CPUs are to do math, to avoid creating extra
| variables. It can be more efficient to just do the math a couple
| times rather than create a whole new variable just to skip the
| math.
|
| This world makes sense to me. It acts like assembly language,
| except it's C (not even C++). I don't know to what extent there
| are other people who think this way, or struggle to keep track of
| even simple abstractions.
|
| It's just the context with which I see Bob acolytes, rather than
| just declaring a variable to not do the math twice, breaking it
| off into about twelve different methods for seemingly purely
| semantic reasons, and insisting anything else is stupid. And
| there I am, producing and re-using reams of shockingly primitive
| code that seems to work and where I can return to it, even a
| couple decades later, and have no trouble figuring out what I
| did.
|
| There's something to be said for being SO stupid that your work
| just works.
| tdiff wrote:
| Is there still any apologet of Bob Martin nowadays?
| ptx wrote:
| I'm surprised that Ousterhout doesn't point out the huge problem
| introduced with the PrimeGenerator3 refactor: It stores state in
| static (!) fields, so it's completely unusable in the presence of
| threads, unless you add a global lock.
|
| Even if Uncle Bob thinks tiny methods are great, why would he
| introduce the pseudo-constructor "initializeTheGenerator" and
| make everything static if he needs state? If the helper methods
| were instance methods instead, the static "generateFirstNPrimes"
| method could simply construct a new instance to store the state.
___________________________________________________________________
(page generated 2025-02-25 23:01 UTC)