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 (#collect:, #select:, #reject:, #detect:, etc.) are all implemented in terms of #do:. Ruby’s Enumerable mixin is similar, in that everything is implemented in terms of :each. #do: and :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, <=>. Again, <=> is a hub method.

Even Rails uses this pattern. One instance of it is in ActiveRecord::Persistence. Both :save and :save! are implemented in terms of :create_or_update. So if you wanted to use standard Ruby inheritance instead of ActiveRecord callbacks, you can override :create_or_update and your changes would affect both :save and :save!. Thanks to a helpful thread on the Ruby Rogues Parley forum for this last example.

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.