Summary: /* Substitution Principle */
[[OOP]] encourages code reuse and may lead to deep subclassing hierarchies. Beware of that when designing [[API]].
=== [[OOP]] Models the World ===
Classic [[OOP|object-oriented programming languages]] are said to be inspired by nature and its
[[evolution]]. Everyone knows the example defining a '''Mammal''' class with basic methods describing
the behavior of every mammal, and various subclasses such as '''Dog''' or '''Cat''' overriding the methods
to do what cats and dogs do differently. This example not only demonstrates what
object-oriented languages do best, but it also ''justifies the whole purpose of [[OOP]]''. By showing how
easy it is to describe nature, the object-oriented concept is also elevated to be the right programming
technique to describe the real world. [[OOP]] languages are supposed to be more suitable
than traditional ones for coding and capturing real-world concepts.
=== Just an Intricate Switch ===
After maintaining a [[NetBeans|framework in Java]] for more than fifteen years, I don’t buy this. Honestly, ''virtual method dispatch''
is nothing else than an
''intricate switch statement''! A method call isn’t a direct invocation of some code but rather a
switch that chooses from multiple implementations. The switch is based on the list of subclasses
and can potentially grow as various developers create more and more subclasses. But
it’s still a '''switch'''. Of course, explaining [[OOP]] as an ''enhanced switch'' is
much less fancy than presenting it as a technology that helps us model the real world. That’s
why computer courses are likely to stick with the '''Mammal''' example.
=== Switch with no Limits! ===
However, I’ll use the switch
explanation to reveal an important hidden catch: when writing an [[API]], ''the size and behavior
of the switch is unknown'' to the writer of the code. This can be seen as an advantage, increasing
the number of ways that a piece of code can be reused. However, a few releases later, if you
don’t know the actual participants in the switch, you can have a nightmare on your hands.
Simply allowing an unknown party to participate in your code “switch” can be too open to be
maintainable.
=== Substitution Principle ===
When writing an [[API]], the term ''subclass'' shouldn’t be used for someone who can ''participate
in a switch'', but for someone who ''behaves exactly like me'', plus adds some additional behavior.
True, many would agree that a '''Human''' is a subclass (a specialization) of a '''Mammal'''.
Nice, but simply exposing a [[DeepHierarchy]] of classes is unlikely to improve an [[API]]’s usability magically.
Especially [[GUI]] toolkits (full of widgets inheriting from each other) got this all wrong.
They like to claim that a {{JDK|javax.swing|JFrame}} is a specialization of {{JDK|javax.swing|JComponent}},
but try to use {{JDK|javax.swing|JFrame}} where you can use {{JDK|javax.swing|JComponent}}! It is going to fail.
That is not a failure of the usage, but a failure of the [[API]] designer!
== Do Not Expose Deep Hierarchies! ==
Rather than exposing [[DeepHierarchy]] separate [[APIvsSPI]] and stay as flat as possible! If you have to expose subtyping, remember [[wikipedia:Liskov_substitution_principle|Liskov's substitution principle]]: if something is a subtype, it has to inherently
be ready to be used in place of the original super class or interface.
[[Category:APIDesignPatterns]]
[[Category:APIDesignPatterns:Anti]]