6 ms·
> Our job is to write programs that run well on the hardware that we are given. The author seems to be neglecting the fact that the whole point of “clean code”
by nimih 4y ago
> Our job is to write programs that run well on the hardware that we are given.
The author seems to be neglecting the fact that the whole point of “clean code” is to improve the likelihood of achieving the first goal (code that runs well, i.e. correctly) across months/years of changing requirements and new maintainers. No one (that I’ve ever spoken to or worked with, at least) is under any illusions that you can almost always trade off maintainability for performance.
Admittedly, I think a lot of prescriptions that get made in service of “clean code” are silly or counterproductive, and people who obsess over it as an end unto itself can sometimes be tedious and annoying, but this article is written in such incredible bad faith that its impossible to take seriously.
- loup-vaillant 4y ago> The author seems to be neglecting the fact that the whole point of “clean code” is to improve the likelihood of achieving the first goal (code that runs well, i.e. correctly) across months/years of changing requirements and new maintainers. Yes that is the whole point of "clean code". Thing, is, it failed. Simplicity is better achieved with other methods. Forget Uncle Bob and SOLID, read John Ousterhout (A Philosophy of Software Design) instead.
- berkes 4y ago> it failed. That is a large statement you make there. It begs for backing up.
- loup-vaillant 4y agoBob Martin should back his claims up. He asserted many things in his book, without evidence, and with examples so bad most of them actually hurt his case. "Clean Code" is just a bad book, best ignored. Great speaker, though. --- As for SOLID, there's one good thing: Barbara Liskov. Her principle have mathematical underpinnings in type theory, shapes Haskell's type classes and likely Rust traits too. The rest however ranges from situational to just crap. Single responsibility is at best a heuristic for the real goal: keeping a nice and small API/implementation ratio. And it fails way too often, causing you to make tiny classes and one liner functions, whose implementations are so tiny they don't even pay for their interface. Pretty bad overall. The Open/Close principle is just crap. Don't use inheritance if you can help it, and don't bother with keeping your code open for this or closed for that. Just keep it simple, so that when requirements changes you can rewrite the parts you need to rewrite. Interface Segregation is a situational heuristic. Just keep your interfaces small, and you'll know when it makes sense to split an API in two or not. Finally Dependency Inversion is cancer. I mean that literally: it causes your code to grow unsightly appendages, makes everything it touch a tad bigger and more complex, and in most cases it doesn't even facilitates testing. Because surprise, the overwhelming majority of the time, code dependencies are fixed. So let them be. Don't complicate your program with interfaces that only have a single implementation. Let your code depend on the implementations directly. It will be simpler, easier to navigate, easier to modify, and just as easy to test. --- As I said, "Clean Code" failed. Miserably.
- berkes 4y agoStill sounds like your opinion vs his. That's not "failing" that's at most "it doesn't work for me", but without explaining why it doesn't work for you, it really is little more than a wild claim. I've had great success with "Clean code" practices. Though I implement it more according to Alistair Cockburns' "Hexagonal Architecture", it's overall very similar and strives for the same goals using the same methods. So in that sense, N=1 it hasn't failed. It has helped at least one person.
- loup-vaillant 4y ago> Still sound like your opinion vs his. Can't do much better in short HN comments. I've tried at times to be more rigorous than that, but so far I've only scratched the surface: https://loup-vaillant.fr/articles/good-code https://loup-vaillant.fr/articles/good-code
- nimih 4y agoI'm certainly not going to defend Uncle Bob here, but I don't think you have to be a SOLID cultist to think that preferring smaller functions, factoring out oft-repeated patterns, and relying on a language's abstraction features (e.g. polymorphism) are useful heuristics for managing complexity and maintainability in a codebase. Like, the article's author complains at length about the overhead of a virtual function call over a switch statement; I don't think their critique is really focused on the nuanced differences between the various schools of "how to make your code nicer to read" (at least, I didn't read it that way). That being said, A Philosophy of Software Design looks like a good read. Thanks for the recommendation.
- loup-vaillant 4y ago> I don't think you have to be a SOLID cultist to think that preferring smaller functions, factoring out oft-repeated patterns, and relying on a language's abstraction features (e.g. polymorphism) are useful heuristics for managing complexity and maintainability in a codebase. They look like reasonable heuristics indeed, but they're perfectible. Factoring out repeated patterns, that's good. Keep that one. But I would advise to wait for the pattern to emerge in the first place, so that when you factor it you know exactly what abstraction you need. https://caseymuratori.com/blog_0015 https://caseymuratori.com/blog_0015 (Semantic Compression) The size of functions is a fairly poor heuristic. The main size you want to minimise is that of the entire code base. At the function (and class/module) level, it's better to minimise API/implementation ratios. That's how you know the function (or class, or module) is useful: small easy to learn APIs that hide significant implementations give you leverage, and help you minimise what you need to keep in mind whenever you're writing a new piece of code. Relying on a language's abstraction features… yeah, I guess, though I generally avoid class based polymorphism. It's a bit heavy for my taste, especially when we have the ability to just pass closures around instead. Often that poor man's object is all you need. > I don't think their critique is really focused on the nuanced differences between the various schools of "how to make your code nicer to read" (at least, I didn't read it that way). It wasn't indeed, but you'll note his code ended up being quite a bit smaller than the original. All those abstractions are nice when they make your code shorter, or better organised but in this case they just didn't. We could blame the toy nature of the example, but still: all those one liners were terrible for the API/implementation ratio, it's no surprise they could be fused together so concisely.