Flaws in OOP practice: use flat composition and interfaces instead of hierarchical inheritance!

OOP is associated with Inheritance, Encapsulation and Polymorphism. These should enable maintainable and re-usable code. Let’s see how this ends up in practice and what are the solutions, so that you REALLY get maintainable and re-usable code. Based on an interesting and entertaining article on medium by Charles Scalfani. This article is a summary. If you need some explanations and examples you should read the original article.

Inheritance

  • “Banana Monkey Jungle Problem”: it is not easily possible to re-use a single class. In most cases you need the whole hierarchy of parent classes, so that you can use the single class (keyword: “implicit environment”). Charles describes is as “You wanted a banana but what you got was a gorilla holding the banana and the entire jungle“. Solution: Composition over Inheritance. Charles calls it “contain and delegate”
  • “The Diamond Problem”: Multi-inheritance which most languages don’t allow because of naming conflicts of inherited methods/attributes. Solution: Composition over inheritance.
  • “Fragile Base Class Problem”: changes in parent classes breaks subclass. The implementation of the parent class must be known (keyword: white box programming) Solution: Composition over inheritance. For simple composition over inheritance you can use a dependency injection container, which simplifies your developer experience a lot!
  • “Hierarchy Problem”: Inheritance is all about hierarchy; parent classes are more general and subclasses are specialised/concrete. But with wrong modelling the inheritance is broken if both classes can change position in the hierarchy. Solution: “tags” which means interfaces.

Encapsulation

  • “Reference Problem”: The passed object is not safe for changes in other objects which hold references. (Annotation: this is a flaw since it breaks expected encapsulation. However, this is a fundamental concept of OOP but not existing in functional programming).

Polymorphism

  • You don’t need OOP – you can use interface-based polymorphism.