Live data from Hacker News

"Clean" Code, Horrible Performance (2023)

computerenhance.com

111–120 of 192 posts

Re: "Clean" Code, Horrible Performance (2023)

#111
post #92

Earlier quoted context omitted.

> but harmful to late-stage developers who adopt it as dogma. Even Robert Martin, very often in his videos and blogs, espouses "engineering judgment" and is quite fine abandoning advice in his book when the situation calls for it. If performance is important and clean code is impacting it, he won't object to your breaking the rules. It's mostly with his TDD evangelism that he goes (a little) crazy.

I just think - in the book at least - he has really bad taste. The examples are full of “spooky action at a distance”. He writes the exact sort of class functions that make a lot of OO terrible to work with, where a function that should be pure has some weird hidden side effects. Code like that is really difficult to reason about and impossible to reuse safely. Somewhat ironic, given what he preaches in the rest of t…

Yeah - I mostly watched his videos (the first N of them), and liked it. But later I saw examples from his book and they were terrible.

Re: "Clean" Code, Horrible Performance (2023)

#112

Earlier quoted context omitted.

I think the rule that "functions should be small enough that they should be easily reasoned about" is a reasonable rule, and it makes sense to follow it 95% of the time. "Functions should be 5 lines or less" is a measure that approximates that rule, but isn't exactly the same thing - I hope you agree we could both come up with 4 line functions that are impossibly complex or 6 line functions that are easily reasoned a…

> "Functions should be 5 lines or less" This can’t really be a serious guideline unless you are writing APL, in which 5 lines can already be daunting to grasp. This guidance depends on the language. For Python, once you get over 50 lines it starts to look like you don’t actually know what you are doing anymore.

Sorry, you're right - 20 lines or less is the recommendation in the actual text of Clean Code. I have seen people try to push that down to 5 in Ruby on Rails development (IIRC, the most popular linter at one time tried to enforce 5 lines)

In any case, the point stands - there are 19 line functions that are too sense, and 21 line functions that are sensible.

Re: "Clean" Code, Horrible Performance (2023)

#113

Earlier quoted context omitted.

Indeed. The problem is trying to apply the principles of "Clean Code" or more generally of OOP everywhere. There are surely cases where having an interface as an abstraction and multiple implementations makes sense. There are case where it doesn't, and if you take as a dogma "everything shall be the implementation of an interface" you get more complex code and performance penalty for nothing. There is nothing wrong w…

> There are surely cases where having an interface as an abstraction and multiple implementations makes sense. I think most people aren't aware of the alternative, which is: A function that can call different implementations based on some other variable. E.g. instead of having RealDB and MockDB type have a createUser() (method), you have a createUser() (function) that switches part of it's logic based on what DB is s…

Yes, but there's not a chance that there's a material difference in performance between those options because of virtual functions.

Unless you're doing something really stupid, nothing other than the DB access is going to be worth optimizing. If those two options are accessing the DB in exactly the same way, then they will probably be within 1% of each other in performance.

Re: "Clean" Code, Horrible Performance (2023)

#114

Earlier quoted context omitted.

Indeed. The problem is trying to apply the principles of "Clean Code" or more generally of OOP everywhere. There are surely cases where having an interface as an abstraction and multiple implementations makes sense. There are case where it doesn't, and if you take as a dogma "everything shall be the implementation of an interface" you get more complex code and performance penalty for nothing. There is nothing wrong w…

> There are surely cases where having an interface as an abstraction and multiple implementations makes sense. A tried and true way solve problems is by adding more layers of indirection, starting with an interface makes it trivial to swap things out. I just did a rewrite of some old sound tool that was hard coded to OSS and Alsa. Now i wanted Pulse and Pipewire, this ended up requiring basically a rewrite because th…

I think about this like hinges in a door. For a door to move, it needs some hinges. Otherwise the door can’t move. But dont get carried away thinking more hinges is always better. We don’t cut door panels in half and reattach the pieces together with more hinges. That would make the door complex and weak.

Like a door, your software should have hinges (interfaces) in the places it needs to be able to change. And it shouldn’t have hinges in places where it won’t change. Rigidity allows for simpler code and better performance. Flexibility allows for changing requirements and modularity.

The mark of an experienced software engineer is having the judgement to know ahead of time where your code should be flexible and where it should be rigid. A good rule of thumb is to only add an interface when you have 2 or more implementations you want to code up. Until then, just call methods directly. If you don’t have 2 different case studies, you’re going to design the API badly because you don’t know the real requirements.

Re: "Clean" Code, Horrible Performance (2023)

#115

Earlier quoted context omitted.

Indeed. The problem is trying to apply the principles of "Clean Code" or more generally of OOP everywhere. There are surely cases where having an interface as an abstraction and multiple implementations makes sense. There are case where it doesn't, and if you take as a dogma "everything shall be the implementation of an interface" you get more complex code and performance penalty for nothing. There is nothing wrong w…

> There are surely cases where having an interface as an abstraction and multiple implementations makes sense. A tried and true way solve problems is by adding more layers of indirection, starting with an interface makes it trivial to swap things out. I just did a rewrite of some old sound tool that was hard coded to OSS and Alsa. Now i wanted Pulse and Pipewire, this ended up requiring basically a rewrite because th…

What if ALSA is that interface? AFAIK, it can load arbitrary .so's to implement snd_pcm, depending on configuration.

Re: "Clean" Code, Horrible Performance (2023)

#116

Earlier quoted context omitted.

This is the author's gripe, though. You're sacrificing end user experience for developer ergonomics.

No, it's a false dichotomy. When working on large applications, by far the single most important factor in performance is having simple and understandable code. Understandable but slow code can be fixed. Incomprehensible code can't, so it either stays slow or gets worked around with caching/async processing/etc. If you want fast software, you should write the simplest thing that isn't obviously stupidly slow, then me…

This is only true up to some point of skill & complexity. Hotspot optimisation only takes you so far. Eventually you can end up with a program that is fast everywhere but which is still somehow slow at the macro level. Like LLVM.

Truly fast software is made by thinking about data flow from the start. If you use the right data structures, the code takes care of itself.

But this is far beyond Clean Code. The examples in that book are neither readable nor performant. He uses bad data structures and hidden mutation everywhere. In the large, that approach leads to a buggy, fragile mess.

Re: "Clean" Code, Horrible Performance (2023)

#117

Earlier quoted context omitted.

In that case, you'd branch into a separate function/block that runs the calculation. Sure, it's slower than a simple array index to find a coefficient, but you're only incurring that cost when you actually need it and it's still much faster than using polymorphism everywhere instead.

The problem in both of these cases is to how prioritize the complexity of the domain vs. the cognitive overhead of the implementation vs. the computational complexity. If the domain is complex and best represented by modeling the domain, model the domain. If the domain is simple and the the complexity is low, make it simple. If the computational complexity is high and the domain is complex, then all solutions will be…

I think if you push your craft, most things become this sort of tradeoff between approaches. More performance at the cost of more code complexity and a harder to use API. Deep testing improves correctness but locks you in to your existing design choices and makes refactoring harder.

But most code is still nowhere near the Pareto frontier. Lots of code can be improved on one or multiple axes without sacrificing anything. For example, making functions pure when you can often results in easier to read code, better readability and better performance (with other changes). This is my main gripe with “clean code”. His examples are full of hidden side effects and latent performance problems. He over relies on classes, inner mutation, virtual functions and tiny functions spread out everywhere. It’s a pity, but he doesn’t seem to know how to actually practice what he preaches.

Re: "Clean" Code, Horrible Performance (2023)

#118
post #92

Earlier quoted context omitted.

> but harmful to late-stage developers who adopt it as dogma. Even Robert Martin, very often in his videos and blogs, espouses "engineering judgment" and is quite fine abandoning advice in his book when the situation calls for it. If performance is important and clean code is impacting it, he won't object to your breaking the rules. It's mostly with his TDD evangelism that he goes (a little) crazy.

I just think - in the book at least - he has really bad taste. The examples are full of “spooky action at a distance”. He writes the exact sort of class functions that make a lot of OO terrible to work with, where a function that should be pure has some weird hidden side effects. Code like that is really difficult to reason about and impossible to reuse safely. Somewhat ironic, given what he preaches in the rest of t…

The ugly reality is consultants like Martin have little production coding experience. Martin has posts going back to the early 90s showing he had little understanding of how software teams work and deliver value.

From what I have seen, his ideas were formed in a vacuum divorced from real coding. You can see it in the small amounts of open source he has released. The kind of guy who will always prefer 50 classes to 5. Who clutches his pearls at an if statement.

I remember he was invited to give a talk at Bloomberg and the majority of us were simply disgusted that an obvious hack like him was lecturing a group of software engineers who had really been there and done that.

Re: "Clean" Code, Horrible Performance (2023)

#119

Earlier quoted context omitted.

> There are surely cases where having an interface as an abstraction and multiple implementations makes sense. A tried and true way solve problems is by adding more layers of indirection, starting with an interface makes it trivial to swap things out. I just did a rewrite of some old sound tool that was hard coded to OSS and Alsa. Now i wanted Pulse and Pipewire, this ended up requiring basically a rewrite because th…

I think about this like hinges in a door. For a door to move, it needs some hinges. Otherwise the door can’t move. But dont get carried away thinking more hinges is always better. We don’t cut door panels in half and reattach the pieces together with more hinges. That would make the door complex and weak. Like a door, your software should have hinges (interfaces) in the places it needs to be able to change. And it sh…

maybe I am using interfaces the word differently. I mean interfaces as in a language construct, a library, or some programming mechanism to separate things out. Even if I only have -one backend- of something, it's still often a good idea to separate those concerns from the rest of your program, stack, etc, just to make things reason about. to have a mental boundary about where things are happening, or to debug, etc.

Re: "Clean" Code, Horrible Performance (2023)

#120
post #92

Earlier quoted context omitted.

> but harmful to late-stage developers who adopt it as dogma. Even Robert Martin, very often in his videos and blogs, espouses "engineering judgment" and is quite fine abandoning advice in his book when the situation calls for it. If performance is important and clean code is impacting it, he won't object to your breaking the rules. It's mostly with his TDD evangelism that he goes (a little) crazy.

I just think - in the book at least - he has really bad taste. The examples are full of “spooky action at a distance”. He writes the exact sort of class functions that make a lot of OO terrible to work with, where a function that should be pure has some weird hidden side effects. Code like that is really difficult to reason about and impossible to reuse safely. Somewhat ironic, given what he preaches in the rest of t…

You mean Clojure, and he did. He is very enthusiastic about it, vastly preferring it to Java.

Fyi.

Post reply on HN