When designing base classes, there are a number of guidelines and patterns that can impact the design. One of those is the idea of “hubs”. Thanks to my wife for the inspiration on the name.
There are several opposing forces at play when creating the base class. We often want to provide a rich API to clients of the class hierarchy, but we also want to be able to easily create subclasses without having to override a bunch of methods. How do we balance these forces?
One way is to create a small set of hub methods that everything else flows through. All of the rich API methods are implemented in terms of the hub methods. Subclasses only need to be concerned with implementing or customizing these hub methods.
Smalltalk and Ruby both use this pattern for collection enumeration.
Smalltalk’s enumeration methods (
#detect:, etc.) are all implemented in terms of
Enumerable mixin is similar, in that everything is implemented in
:each are hub methods.
Ruby also uses this pattern in the
Comparable mixin, where
all of the methods are implemented in terms of the spaceship operator,
<=> is a hub method.
Even Rails uses this pattern. One instance of it is in
implemented in terms of
:create_or_update. So if you wanted to use
standard Ruby inheritance instead of ActiveRecord callbacks, you can
:create_or_update and your changes would affect both
:save!. Thanks to a helpful thread on the
Ruby Rogues Parley forum for this
Next time you’re working on a base class, think about using hub methods as a way to balance the forces of easier subclassing and rich client APIs.