Forgetting Super Sends

In object-oriented programming, it is common to extract a
superclass when two classes share some common behavior. There are
other ways to structure the code, such as using composition and
delegation, but for this post, I’ll use inheritance.

Simple Inheritance Hierarchy

classGuide

attr_reader:answer_to_life

defconfigure(options)

@answer_to_life=options.fetch(:answer,42)

end

end

classRestaurant<Guide

defconfigure(options)

super

@location=options.fetch(:location,:end_of_universe)

end

end

classGratitude<Guide

defconfigure(options)

super

@thanks=options.fetch(:thanks,:fish)

end

end

This is a pretty standard style of inheritance hierarchy, and we learn
to write code like this very early on. However, there’s brittleness
here, even though it may not be that obvious.

A new feature request comes in that requires another subclass in this
hierarchy:

New Subclass

classSummary<Guide

defconfigure(options)

@harmless=options.fetch(:harmless,:mostly)

end

end

Aaaaannd, I just introduced a bug. Did you see it?

The Bug

summary=Summary.new

summary.configure({})

summary.answer_to_life# => nil # WHAT!?!?

All of the Guide subclasses are supposed to know the answer to life,
the universe, and everything. Why doesn’t Summary?

The answer, of course, is that I forgot to send super in the new
configure method. This is an easy mistake to make, but of course
there are tests to catch things like this, right? Right?

I could leave things in this state, beat myself up for making this
simple mistake yet again, and move on to the next feature.

There is another way. I will apply some Poka-yoke. Poka-yoke is a
Japanese term meaning “mistake-proofing”, and it is well-known in lean
manufacturing. It’s a good technique to apply any time we find
ourselves making the same little mistakes over and over again, like
forgetting to send super.

When a subclass sends super it’s effectively declaring that it
knows the algorithm; it depends on this knowledge.

I hadn’t thought of it this way before, but it’s a fascinating thought.

Whatever you call it, it’s a handy way to make code a little less
brittle.

Afterword

I wrote the original draft of this post several days ago. Just before
I was going to post it, Sandi Metz tweeted a link to
another article
that makes this same point, but in a broader context. It’s an
interesting read.