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".
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.
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.
virtual void setPixel(int x, int y, int color) = 0;
and then implemented flood fill etc in terms of that.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.
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"?
It's only a problem when it's done per datum.
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.