Ramblings about the benefits and perils of polymorphism.
Use of virtual functions, function pointers, or other delayed function dispatch, distinguishes object oriented programming methods from others. This enables you to make abstractions to separate components (by which I mean coherent and tightly coupled sections of code) from each other. The ignorance of how services are provided strengthens the code by allowing you to make significant changes to one component without affecting others. Or that is how it is supposed to work . . .
Browsing online, I stumbled across instructions for how developers may contribute to the ffmpeg codec family and the Linux kernel. In both of these cases, the overall project is done in an object oriented fashion using C. From the documentation, structs with function pointers are used to define interfaces for how the kernel talks to a device driver or how codecs talk with other parts of the software. Based on the success of both of these projects, these would seem to be cases where polymorphism is used appropriately.
There are several ways polymorphism can be harmful:
- Poor judgment on how to make things polymorphic may cause a performance penalty.
- Poor choice of abstraction can make it very difficult for components to talk to each other.
- Modeling algorithms using objects with state may have unintended consequences.
There are two basic performance penalties from polymorphism:
- Calling functions indirectly might be slower than other function calls because it prevents inlining (http://en.wikipedia.org/wiki/Inlining) based optimizations.
- Each polymorphic object needs a pointer to a vtable. A design which requires many thousands of polymorphic objects to be built could take much more space to implement than the same design where nonpolymorphic objects are used.
These considerations argue for making polymorphism at as high a level as possible.
Poor abstractions may be the biggest problem with object oriented programming. The point of an interface is that it stays fixed while the components talking to each other evolve. Bad interfaces can leave both clients and servers trying to do things that the interface doesn’t allow, which commit thought crimes that maim both clients and servers.
Finally, there is a critique of object oriented programming that it pushes developers towards designs where the computation is done primarily through state change of objects. Advocates of functional programming effectively argue this is not a good idea. State change doesn’t mix well with multithreading. Current GPU programming interfaces. Designs based on state changes may lead to “secret handshakes” between components which makes software very hard to understand.
What do you think?