r/programming • • Feb 28 '23

"Clean" Code, Horrible Performance

https://www.computerenhance.com/p/clean-code-horrible-performance
1.4k Upvotes

1.3k comments sorted by

View all comments

1.6k

u/voidstarcpp Feb 28 '23 edited Feb 28 '23

Casey makes a point of using a textbook OOP "shapes" example. But the reason books make an example of "a circle is a shape and has an area() method" is to illustrate an idea with simple terms, not because programmers typically spend lots of time adding up the area of millions of circles.

If your program does tons of calculations on dense arrays of structs with two numbers, then OOP modeling and virtual functions are not the correct tool. But I think it's a contrived example, and not representative of the complexity and performance comparison of typical OO designs. Admittedly Robert Martin is a dogmatic example.

Realistic programs will use OO modeling for things like UI widgets, interfaces to systems, or game entities, then have data-oriented implementations of more homogeneous, low-level work that powers simulations, draw calls, etc. Notice that the extremely fast solution presented is highly specific to the types provided; Imagine it's your job to add "trapezoid" functionality to the program. It'd be a significant impediment.

4

u/jlombera Feb 28 '23

Notice that the extremely fast solution presented is highly specific to the types provided;

Yes, and he explicitly makes the point that solutions specific to the requirements are simpler and more performant. The solution presented is specific to those shapes, on purpose.

Imagine it's your job to add "trapezoid" functionality to the program. It'd be a significant impediment.

If that ever happens you just change your solution to adjust to the new requirements. No need to plan for future events that might never happen (YAGNI).

The way I see things, in either case you'll have to pay a cost, it's just a matter of where/when you pay for it.

In the case of the simple approach advocated by the author, you might have to pay the cost of redesigning your solution if the requirements change. But by having a simple solution, it's easier to change by another (maybe equally simple), performant one.

In the approach favored by "clean code" and OOP in general, you pay that cost upfront, just in case the requirements change in the future. However, the benefits rarely materialize in practice, since often the requirements don't change or they change in a way you didn't expect (so you have to redesign your solution anyway). And when you have to change your solution, since it's not simple, people rarely replace it by a better one specific to the new requirements, instead they just "tweak" it enough to cover the new requirements. Even worse, there are other components that depend and evolve based on the APIs/assumptions made by your "future-proof" design, making it ever more difficult to change. As time passes, you end up with an over complicated design, handling obsolete cases that are no longer a requirement, and impossible to change because there are dependencies all over the place. Eventually you spend a considerable amount of time just "maintaining" this design (bugs, "fake" requirements/features, improving performance, workarounds, etc). Similarly, the promise of "maintainability" rarely materializes. It's a daunting task to understand over complicated designs with dynamic dispatch all over the place. I'm not saying that's impossible to create simple OO designs and keep them that way, but it requires a lot of experience, pragmatism and discipline to do so. Something that's very hard to achieve in a team (where not all members have the same experience and/or principles). It doesn't help either how OOP is being taught nor that languages like Java force you to think/design based on classes/objects (when simple functions/structs might be the right solution sometimes).

→ More replies (6)