A quick search on YouTube with the query “Considered Harmful” is a revealing exercise. The number and variety of articles thereby returned is outstanding and, to a certain extent, hilarious. The day I wrote this article I had the following ones popping up, all of which were literally considered harmful for the purposes of the content: threads, enums, C++ generics, rand(), if, else, the UPDATE SQL statement, global variables, user stories, architecture, YAML (well, this one we can agree upon), IInterface, mocking frameworks, assemblers, abstractions, penetration testing, and yes, even programming itself. Among those search results there was even a talk by Alan Kay himself named “Normal Considered Harmful”.
(Small pause while I catch my breath.)
Have we reached the point where the phrase “Considered Harmful” itself has lost all meaning, or, even worse, it ends up signaling content of dubious quality or intentions? Maybe; there is still a part of me that tries to consume content with an open eye regardless of the title creators chose, and among all the chaff, there thankfully is some grain waiting to be found.
For this month’s Vidéothèque issue, we have chosen Phil Nash’s excellent talk titled “OO Considered Harmful”, delivered at CppCon 2020 (remotely, of course, as it used to be the case during the last pandemic).
Phil is a programmer, trainer, and a regular speaker in the C++ galaxy, and with reason: he is the original author the Catch2 unit test framework, highly regarded as one of the standard unit testing frameworks for C++. He is also co-host of the CppCast podcast, and has worked as developer advocate for various companies including JetBrains and SonarSource, delivering talks about programming and C++ for more than 20 years at the time of this writing.
In this magazine we are fervent fans of object-orientation; so it should not be a surprise that this talk would catch our attention (no pun intended, Phil).
Phil starts his video by explaining the connection to Dijkstra’s original paper, by exhorting developers to shorten the conceptual gap between the static code of a program and its dynamic representation in the computer, usually referred to as a process.
In this context, Dijkstra’s critique of the goto statement is akin to that of mutable state; the former complicating control flow, the latter complicating data flow. Mutable state is a burden that lengthens the debugging phase for any program, and hence, its complicatedness.
Phil then takes a historical perspective; another favorite angle of this magazine. And he does this through the examples of languages like Simula and Smalltalk, Objective-C and Eiffel, all pioneering the object-orientation paradigm among programmers. I bet you have never seen a snippet of Simula in your life; well, here is your chance.
And then he gets into the interesting part: the critique of core OOP concepts, like polymorphism, inheritance, and encapsulation, all within the context of modern C++.
Regarding polymorphism, Phil states that the standard approach (“vtables”) is usually avoided in performance-critical C++ code, and he proposes the use of type erasure (similar to Rust traits or Swift protocols) as a much better, non-intrusive, and inheritance-free alternative.
Regarding inheritance, he mentions something Rust and Go developers have noticed all along: you just do not need it, and mixins and traits are much more modern and flexible alternatives.
Finally, regarding encapsulation, he rightfully claims it to be the most valuable aspect of OOP, even though the implementation provided by C++ can be leaky sometimes (protected and friend, someone?) and does not reach the perfection of other languages like Erlang.
So, what is the road ahead? According to Phil, “Value-Oriented Design”; a multi-paradigm approach that marries OOP with Functional programming ideas, leading to stronger, safer code. And how is this achieved? Through two basic mechanisms. First, immutable value types, created through the Builder design pattern, and managed through persistent data structures, allowing modifications that avoid copying, for performance gains. And second, by encapsulating “components”, namely objects with internal state and processes, in such a way that they use clear interfaces to talk to one another.
In conclusion, the “harmful” part of OOP has to do with the use of shared mutable state and rigid inheritance hierarchies. Instead, build your software with immutable value types at the bottom, and encapsulated components on top of them.
So maybe, just maybe, the future of programming (besides the reliance on AI-based coding tools) is not just adhering to a single paradigm, but rather combining the strengths of many to make code that is safe and performant at the same time. Once again, we sense that idea floating in the air, that the most “harmful” thing we can do as programmers is to blindly swallow dogmas, not considering the various options that we have at our disposal, and how to make them work in harmony.
Watch this month’s Vidéothèque entry, “OO Considered Harmful” by Phil Nash, on YouTube.
Cover snapshot chosen by the author.