Why Classes are Bad
- Classes obscure prototypal inheritance
- Classes encourage inheritance, but you should prefer composition
- Class tend to lock you into the first bad design you came up with
Mitigation to Dangers
Resist making classes your public API
You can always hide your classes behind the factory functions
- People will inherit from them if they're exposed in all sorts of ways that make zero sense to you, but that you may break in the future
- Avoiding breaking people's classes is hard:
- they might use the method names you want to use in the future versions
- They might read your private state
- They might put their own state onto your instances
- They might override your methods without calling
super
which may work for a while, but break later
However, if there isn't back-and-forth interaction between base class and the derived class, exposing a base class may be a valid API choice
Don't inherit more than once
Problem with inheritance is that the descendents have too much access to the implementation details of every base class in the hierarchy, and vice versa
- When the requirements change, refactoring a class hierarchy is so hard that it turns into a WTF sandwich with traces of outdated requirements
Instead of creating a class hierarchy, consider creating several factory functions
- They may call each other in chain, tweaking the behavior of each other
- You may also teach the base factory function to accept a strategy object modulating the behavior, and have the other factory functions provide it
- Regardless of the approach, important part is to keep inputs and outputs explicit at every step
- "You need to override a method" is not an explicit API and is hard to design well, but "you need to provide a function as an argument" is explicit and helps you think it through
Don't make super
calls from methods
- If you override a method in a derived class, override it completely
- Tracing a sequence
super
calls are painful
- If you really need to transform the result of the super method, or perform it before or after doing something else, turn it into the factory functions and keep the relationship very explicit
Don't expect people to use your classes
- Even if you choose to provide your classes as a public API, prefer duck typing when accepting inputs
- Instead of
instanceof
checks, assert the existence of themethods you plan to use, and trust the user to do the right thing
Learn functional programming
- avoid using class by not thinking in it