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.