Skip to content(if available)orjump to list(if available)

Clean Code vs. A Philosophy Of Software Design

zbentley

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.

hakunin

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.

the__alchemist

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.

frozenlettuce

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

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

> 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.

aprilthird2021

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.

NomDePlum

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)!

pinoy420

[dead]

marcusbuffett

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.

sudobash1

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

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

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

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

zbentley

> 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.

mbo

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

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

getnormality

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

PlunderBunny

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

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

Scubabear68

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

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

MobiusHorizons

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

nyarlathotep_

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.

ilrwbwrkhv

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

ziml77

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

> 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

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

OnionBlender

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

chillpenguin

"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

> no links

owl_vision

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

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”

mkoubaa

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

Jach

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

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

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

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

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

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

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

namuol

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

htk

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