News for hackers. Stuff that matters.
Re:“Clean” Code, Horrible Performance by vore on Tuesday February 28, 2023 @04:11AM (#34967260)
This guy is so dogmatic about it it hurts. I would argue that clean code is a spectrum from how flexible vs how rigid you want your abstractions to be. If your abstractions are too flexible for good performance, dial them back when you see the issue. If your abstractions are too rigid for your software to be extendable, then introduce indirection.

We can all write code that glues a very fixed set of things end to end and squeeze every last CPU cycle of performance out of it, but as we all know, software requirements change, and things like polymorphism allow for much better composition of functionality.

Re:“Clean” Code, Horrible Performance by TheFattestNinja on Tuesday February 28, 2023 @04:38AM (#34967443)
Casey is a bit of a hardcore crusader on the topic, but I'd hardly call dogmatic someone who can provide you evidence and measurements backing their thesis.

The tests he put together here are hardly something I'd call a straw-man argument, they seem like reasonable simplification of real-cases.

Re:“Clean” Code, Horrible Performance by st3fan on Tuesday February 28, 2023 @07:19AM (#34968469)
Evidence in a micro benchmark of a single page of code.

The focus on performance here ignores the fact that most programs are large systems of many things that interact with each other. That is where good design and abstractions and “clean code” can really help.

Like all things it is about finding a balance and applying the right techniques to the right parts of a larger system.

Re:“Clean” Code, Horrible Performance by TheFattestNinja on Tuesday February 28, 2023 @08:21AM (#34968966)
True, the example is simplistic, but that's just to make it fit within reasonable exposition. The author has in the past shown (elsewhere) how his techniques can actually make dramatic differences in more concrete examples (he rose to some Internet fame for building a performant shell that could actually handle larger outputs orders of magnitude better than most available alternatives).

To me the interesting point is the reminder that there is an innate tension between going fast and being "clean" (i.e. maintanable/understandable). And once you are aware of it you can make your decisions in an informed way. Too often this tension is forgotten/ignored/dogmatically put to the back ("performance doesn't matter over cleanliness" and the likes).

Mind you, I'm also of the camp that performance is very secondary to cleanliness in modern enterprises, but I appreciate a reminder of just how much we are sacrificing on this altar.

Re:“Clean” Code, Horrible Performance by cma on Tuesday February 28, 2023 @09:35AM (#34969712)
It was Windows Terminal he wrote something faster than. Windows terminal was doing a whole GPU draw call per character (at 2x standard terminal height, 160x25, it was as many draw calls as a AAA game).
Re:“Clean” Code, Horrible Performance by gongle on Tuesday February 28, 2023 @04:44PM (#34975294)
No matter what design choices you argue for there are always ways to be an idiot about the implementation
Re:“Clean” Code, Horrible Performance by vkou on Tuesday February 28, 2023 @07:34PM (#34977109)
Which is an excellent argument for why the WT team should have done some benchmarking, identified that they have a really dumb O(M*N) bottleneck in their rendering code, and optimized it.

It is not an excellent argument for why 'clean code' is not a better fit for the other 99% of their codebase.

Re:“Clean” Code, Horrible Performance by gjadi on Tuesday February 28, 2023 @09:28AM (#34969642)
I'd say that it really depends on what the code needs to do.

For example, if the code is to be distributed and extended as a third-party library, then the class hierarchy is probably a better fit to allow extensibility.

But if the purpose of the API is to compute the area of given shapes (as in the example), then it makes sense to make it efficient and there is no use to provide extensibility to the outside world.

The advocates of "clean code" that Casey mentions will go for extensibility no matter the use.

I find it very interesting to have numbers to weight what you are leaving when you go the extensibility route instead of the non-pessimistic route.

Re:“Clean” Code, Horrible Performance by st3fan on Tuesday February 28, 2023 @10:43AM (#34970518)
> The advocates of "clean code" that Casey mentions will go for extensibility no matter the use.

Unfortunately this is just some catchy stereotyping that probably doesn't match reality.

Re:“Clean” Code, Horrible Performance by gjadi on Tuesday February 28, 2023 @10:58AM (#34970717)
I don't know. Before reading Casey, I'd say most, if not all, of my APIs would look like the "clean code" style.

The process was "think about the model, design a class hierarchy that fits with the model, add the operations". Even if I don't think about extensibility, that's how I thought my code.

Why? Because when I think about performance, I used to think about algorithms and I/O optimizations (for example batching).

Now I'll look into this data-oriented programming-thing and see how that applies to my platform (embedded Java) :D

Re:“Clean” Code, Horrible Performance by jstimpfle on Tuesday February 28, 2023 @04:29PM (#34975100)
The code examples with the abstract / virtual methods for the most straightforward concepts are a clown show. Not cleanliness but madness.
Re:“Clean” Code, Horrible Performance by loup-vaillant on Tuesday February 28, 2023 @06:45PM (#34976603)
That's what you get with SOLID. Madness.
Re:“Clean” Code, Horrible Performance by loup-vaillant on Tuesday February 28, 2023 @06:44PM (#34976580)
I've seen at least one embodiment of the stereotype 3 months ago. It wasn't pretty, I was able to shrink his code by a factor of 5, and make it more flexible in the process. Among other mistakes he had some idea of flexibility, put part of the infrastructure in place, and then utterly failed to use it, such that when it came to test he required a monkey patching framework for C (Ceedling) so he could mock what he almost already mocked in the source code.

That's a fairly rare breed for sure, but the real problem was that nobody called him out. Well I did, but I'm no longer working there. I couldn't.

Re:“Clean” Code, Horrible Performance by ajmurmann on Tuesday February 28, 2023 @04:27PM (#34975075)
Unfortunately, everything in our profession is a tradeoff. Faster and maintainable are two of the many quality metrics you can optimize for that will be at odds at times. What the right balance is for a given piece of code depends on so much context. It's a hard balance to get right.
Re:“Clean” Code, Horrible Performance by Barrin92 on Tuesday February 28, 2023 @04:34PM (#34975169)
> they seem like reasonable simplification of real-cases.

Paraphrasing Russ Ackoff, doing the right thing and doing a thing right is the difference between wisdom and efficiency. What Casey is doing here may be efficient, but calculating a billion rectangles doesn't present a realistic or general use case.

"Clean Code" or any paradigm of the sort aims to make qualitative, not quantitative improvements to code. What you gain isn't performance but clarity when you build large systems, reduction in errors, reduce complexity, and so on. Nobody denies that you can make a program faster by manually squeezing performance out if it. But that isn't the only thing that matters, even if it's something you can easily benchmark.

Looking at a tiny code example tells you very little about the consequences of programming like this. If we program with disregard for the system in favour of performance of one of its parts, what does that mean three years down the line, in a codebase with millions of lines of code?`That's just one question.

Re:“Clean” Code, Horrible Performance by vore on Tuesday February 28, 2023 @05:00PM (#34975542)
Performance measurements are only one dimension of code quality. Having a laser focus on it disregards why you would want to sacrifice performance for a different dimension of code quality, such as extensibility for different requirements.

You should check if your code is in the hot path before optimizing, because the more you couple things together the harder it is to change it around. For instance, in Casey's example, if you wanted to add a polygon shape but you've optimized calculating area into multiplying height x width by a coefficient, that requires a significant refactor. If you are sure you don't need polygons, that's a perfectly fine optimization. But if you do, you need to start deoptimizing.

Re:“Clean” Code, Horrible Performance by lmm on Tuesday February 28, 2023 @06:09PM (#34976235)
These examples are absolutely a strawman. He's imagining there's one specific access pattern that's executed thousands of times per second. In a realistic codebase you're accessing the data less often but in multiple different (often subtly so!) ways. Cache efficiency is everything for modern CPUs, so you can't "simplify" the access patterns without making your benchmarks unrepresentative.
Re:“Clean” Code, Horrible Performance by _dain_ on Wednesday March 01, 2023 @09:26AM (#34982723)
How is it a strawman when it's literally taken from a Clean Code textbook?
Re:“Clean” Code, Horrible Performance by lmm on Wednesday March 01, 2023 @05:28PM (#34989225)
His benchmarks aren't taken from the textbook. If you benchmarked the textbook's changes in a realistic context you'd get quite different results.
Re:“Clean” Code, Horrible Performance by mtrower on Thursday March 02, 2023 @02:48AM (#34993166)
What defines a codebase as realistic, exactly? There are many, many programs out there doing various things in various ways.
Re:“Clean” Code, Horrible Performance by athanagor2 on Tuesday February 28, 2023 @04:15AM (#34967301)
But is it true that "clean code" makes the adaptation to changing requirements easier? I saw a few testimonies saying otherwise.
Re:“Clean” Code, Horrible Performance by vore on Tuesday February 28, 2023 @04:19AM (#34967324)
I think it really truly depends. I think it's always good to do the minimal viable thing first instead of being an architecture astronaut, but if you've been asked for three (random ballpark number) different implementations for the same requirement it might be time to start adding some indirection.
Re:“Clean” Code, Horrible Performance by mattgreenrocks on Tuesday February 28, 2023 @04:37PM (#34975213)
The best idea in clean code is to stop coupling domain models to implementation details like databases/the web/etc. Once you grok that, then you're in a better position to work on eliminating unnecessary coupling within the model itself.

There's lots of ways to do this poorly and well. There's no process for it. That's a feature. I feel like a lot of the flak clean code gets boils down to, "I followed it dogmatically and look what it made me do!" It didn't make you do anything; it's trying to teach you aesthetics, not a process. Internalize the aesthetics and you won't need a rigid process.

Obviously when you do this you probably need more code than you'd normally write. That can be viewed as a maintenance burden in some situations, esp. when you don't have product market fit. Again, this shows that treating clean code like some process that always produces better code in every situation is extremely naive.

Re:“Clean” Code, Horrible Performance by anonymoushn on Tuesday February 28, 2023 @04:12AM (#34967273)
Is there any flexbility tradeoff at all here?
Re:“Clean” Code, Horrible Performance by vore on Tuesday February 28, 2023 @04:16AM (#34967305)
The shapes example is pretty contrived so I don't really have an opinion on it either way. But imagine you have something like a File interface and you have implementations of it e.g. DiskFile, NetworkFile, etc., and you anticipate other implementors. Why would you do anything other than have a polymorphic interface?
Re:“Clean” Code, Horrible Performance by saidinesh5 on Tuesday February 28, 2023 @04:37AM (#34967440)
I think the shapes example is more of a dig at various game engines where you end up with a long trees of inheritance (physicsbody -> usercontrollable physics body -> renderable user controllable physics body etc..) as opposed to the recent trend of using something like an Entity Component System.

Also I think he isn't specifically against "clean code" but how the first tool used by various "clean code advocates" seems to be polymorphism. I have seen this enough in lots of Java codebases and "Enterprise C++ codebases". "We need X." "Oh first I will create an Abstract Base class for X, then create X, so we can reuse X nicely elsewhere when we need it". It is still on the developers to understand that they may not even need it but for them it is "clean code".

Re:“Clean” Code, Horrible Performance by adamrezich on Tuesday February 28, 2023 @06:05PM (#34976196)
I wish he would've gone a bit more into why people reach for polymorphism instead of a struct with a variant enum: because it's how OOP is taught, and how it easily maps to human understanding of most problem spaces. like you're making an RPG, so you make an Item class, and then you make Armor and Weapon subclasses, and then you make Helmet/Chestplate/Leggings/Shoes and Sword/Polearm/Axe/Mace/Staff subclasses, etc. etc., just because it fits your mental model of the problem, when in actuality, you could've totally avoided all of that complexity, and the ensuing boilerplate, just by sticking it all in one struct and calling it a day. this is not always the solution, but more often than not it is.
Re:“Clean” Code, Horrible Performance by anonymoushn on Tuesday February 28, 2023 @04:18AM (#34967318)
I don't know, I've never done anything where code needed to have runtime dispatch on the kind of file it has without also knowing anything about what kind of file it has.
Re:“Clean” Code, Horrible Performance by vore on Tuesday February 28, 2023 @04:23AM (#34967348)
Have you never used C++ iostreams? Or the Python file abstraction? Or Rust std::io::Read/std::io::Write? Or Node.js streams? Or DOM Web Streams? Or Ruby files? Or Haskell conduits? Or hell, fopencookie/funopen in C?

The abstraction is super common and allows you to connect streams to each other without worrying about the underlying mechanism, which 99% of the time I don't really think you want to worry about unless you're sure it's a performance overhead. And that's great, because I surely don't want to write specializations by hand for all the different combinations of streams I need to use if I don't have to.

Re:“Clean” Code, Horrible Performance by anonymoushn on Tuesday February 28, 2023 @04:31AM (#34967400)
I've used open(2) and the io_uring openat :)

I use generic readers and writers every day, but they don't have any runtime dispatch. The question was "Why would you do anything except vtables and runtime dispatch?" One answer is that my code that uses generic readers and writers and gets monomorphized gets to also be generic over async-ness.

Re:“Clean” Code, Horrible Performance by vore on Tuesday February 28, 2023 @04:33AM (#34967415)
There you go, actually: you can have your clean code cake and eat it too if you have the right language abstractions (like parametric polymorphism).
Re:“Clean” Code, Horrible Performance by saagarjha on Tuesday February 28, 2023 @04:33AM (#34967411)
Except in the kernel, of course.
Re:“Clean” Code, Horrible Performance by zelos on Tuesday February 28, 2023 @04:44AM (#34967490)
That does depend on how the abstraction is defined, of course. I once worked on optimising a 2D Canvas C++ class which had a nice top level virtual interface so you could replace it with a different implementation. It was also crazily slow because it defined:

  virtual void setPixel(int x, int y, int color) = 0;
and then implemented flood fill etc in terms of that.
Re:“Clean” Code, Horrible Performance by int_19h on Tuesday February 28, 2023 @06:31PM (#34976464)
This isn't necessarily bad if all the other operations are also virtual. The idea is that you can quickly get something working (e.g. when porting) just by implementing setPixel(), and then gradually fill in other primitives with properly hardware-optimized versions. And you do need a virtual setPixel() in any case because some API client might need that one call.
Re:“Clean” Code, Horrible Performance by Arelius on Tuesday February 28, 2023 @07:33PM (#34977107)
I'm sorry, why do you need a virtual setPixel?

You can still easily get something working just by implementing setPixel without virtual dispatch, the linker has no problem inlining that call at compile time.

If some arbitrary API needs it to be virtual it's easy to implement the virtual call in just that specific case, instead of burdening your entire system with a virtual call that'll always be static in practice.

Re:“Clean” Code, Horrible Performance by int_19h on Tuesday February 28, 2023 @08:35PM (#34977618)
For the same reason why you need a virtual drawLine etc. Because some code wants to render something, and doesn't want to care if it's rendering onto an on-screen surface, into a file etc.

Your entire system will not be burdened with virtual calls in places where you use concrete implementations (so long as they're final/sealed, anyway). The overhead is only there if you try to use the abstraction generically, but why would you do that in the case where the virtual call "will always be static in practice"?

Re:“Clean” Code, Horrible Performance by mgaunard on Tuesday February 28, 2023 @04:02PM (#34974792)
Anything that yields data in chunks will not really be affected by runtime polymorphism much.

It's only a problem when it's done per datum.

Re:“Clean” Code, Horrible Performance by alfalfasprout on Tuesday February 28, 2023 @07:05PM (#34976788)
Right, but the point is you can avoid polymorphism within a given implementation but still keep it at a higher level.

Heck, even codebases used in trading can use polymorphism for very high level interfaces (or async tasks) but hot code paths don't use it.

Re:“Clean” Code, Horrible Performance by jasmer on Tuesday February 28, 2023 @04:50AM (#34967533)
I don't think rich abstracions necessarily contribute to 'clean code' in fact often the opposite.

Clean code means easy to read, maintain, not full of arbitrary things 'because performance'.

Re:“Clean” Code, Horrible Performance by hinkley on Tuesday February 28, 2023 @04:01PM (#34974787)
Spectrum or I believe more of a Venn Diagram.

There was a moment in grade school where I was sat down and it was explained to me that you don't have to take a test in order. You can skip around if you want to, and I ran so far with that notion that at 25 I probably should have written a book on how to take tests, while I could still remember most of it.

One of the few other "lightning bolt out of the blue" experiences I can recall was realizing that some code constructs are easier for both the human and the compiler to understand. You can by sympathetic to both instead of compromising. They both have a fundamental problem around how many concepts they can juggle at the exact same time. For any given commit message or PR you can adjust your reasoning for whichever stick the reviewer has up their butt about justifying code changes.

Re:“Clean” Code, Horrible Performance by Kukumber on Tuesday February 28, 2023 @04:30PM (#34975106)
0 responsibility developers

you have Japan infrastructure, and you have Turkey infrastructure

6.1 quake in Japan = nothing destroyed

6.1 quake in Turkey = everything collapses

The engineers in Turkey probably didn't value performance and efficiency

It's the same for developers, you choose your camp wisely, otherwise people will complain at you if they can no longer bear your choice

You act like innocent, but your code choice translate to a cost (higher server bill for your company, higher energy bill for your customers/users, time wasted for everyone, depleting rare materials at a faster rate, growing tech junk)

Selfishness is high in the software industry

We are lucky it's not the same for the HW industry, but it's getting hard for them to hide your incompetence, as more things now run on a battery, and the battery tech is kinda struggling

Good thing is they get to sell more HW since the CPU is "becoming slower" lol

So we now got smartwatches that one need to recharge every damn day

Re:“Clean” Code, Horrible Performance by ilyt on Tuesday February 28, 2023 @05:10PM (#34975631)
> The engineers in Turkey probably didn't value performance and efficiency

Uh, no. It was corruption. They were standards, that worked, but people didn't do it, plain and simple.

Re:“Clean” Code, Horrible Performance by TeMPOraL on Tuesday February 28, 2023 @06:22PM (#34976383)
Yeah, it's a bad and unnecessarily inflammatory (and arguably disrespectful) example. But the rest of the points GP makes are spot on.

A "blame systems over individuals" version would be that the industry is externalizing bad performance onto users, damaging environment, causing frustration, wasting lives, and occasionally even actually killing people (shitty ER/hospital software comes to mind) - because there's no good feedback mechanism to force software companies to internalize those costs.

Re:“Clean” Code, Horrible Performance by Kukumber on Tuesday February 28, 2023 @07:31PM (#34977076)
> Yeah, it's a bad and unnecessarily inflammatory (and arguably disrespectful) example. But the rest of the points GP makes are spot on.

I agree, i apologies for the mistake, i can no longer edit the post unfortunately

Re:“Clean” Code, Horrible Performance by overgard on Tuesday February 28, 2023 @05:49PM (#34976043)
I think part of the problem with supposed "clean" code is that it tends to be a matter of opinion. Is the polymorphic version cleaner than the switch statement version? I would argue the latter is actually easier to read. There's no real reason to think "clean" code is actually clean other than anecdotes and that someone wrote it in a book, but the performance is something that can be objectively measured.
Re:“Clean” Code, Horrible Performance by whstl on Thursday March 02, 2023 @10:42AM (#34997042)
The "Clean Code" that Casey is talking about is a book and a code philosophy that was explained in depth in talks and trainings and seminars, so I would disagree that it is a matter of opinion.
Re:“Clean” Code, Horrible Performance by alfalfasprout on Tuesday February 28, 2023 @07:00PM (#34976738)
Yes... but I'm also seeing dogmatism from the opposing camps here in the comments section.

The reality is that how flexible your interfaces and abstractions are and their design has to be a part of your original design considerations when building something. It's a bad move to just hand wave away performance concerns because you religiously adhere to some design patterns. It's also a bad move to drop down to using intrinsics for everything from the get-go and thinking you know better than the compiler when it's a codepath that isn't even computationally expensive or a bottleneck a priori.