Please Stop Abusing NotImplementedError

The purpose of NotImplementedError is defined in the Ruby docs:

NotImplementedError is raised when a feature is not implemented on the current platform. For example, methods depending on the fsync or fork system calls may raise this exception if the underlying operating system or Ruby runtime does not support them.

So whenever I see code like this:

class Vehicle def manufacture(n) n.times { create } end def create raise NotImplementedError, "subclass did not define #create" end end 1 2 3 4 5 6 7 8 9 class Vehicle def manufacture ( n ) n . times { create } end def create raise NotImplementedError , "subclass did not define #create" end end

I cringe. Raising NotImplementedError simply to signal that a subclass didn’t abide by the contract of its superclass is an abuse of the error. The error is intended to be raised when a method cannot be implemented due to a limitation of the underlying platform (OS or Ruby runtime).

Forget NotImplementedError

So what should you do when you write something in Ruby that relies on an abstract method? The “most Ruby” thing to do would be to not implement the method at all. Instead, document the expectation and if a subclass fails to meet it a NameError , or often its subclass NoMethodError , will be raised automatically.

class Vehicle def manufacture(n) n.times { create } end # @abstract Subclass is expected to implement #create # @!method create # Make a particular model of world class vehicle end 1 2 3 4 5 6 7 8 9 class Vehicle def manufacture ( n ) n . times { create } end # @abstract Subclass is expected to implement #create # @!method create # Make a particular model of world class vehicle end

If a subclass of Vehicle does not quack like a Vehicle then it’s not really a Vehicle, and the Ruby interpreter will let us know with a loud NameError. Keep your ducks in a row and you’ll find little need for NotImplementedError.

Get comfortable with ducks

I admit, I am guilty of abusing NotImplementedError. I did it a few times early in my Ruby career, after years of being a Java programmer. In Java, and many other languages, you must declare any abstraction that your code relies upon. If you don’t the compiler will yell at you. When I first started with Ruby it was uncomfortable to not declare my abstractions. I found comfort in empty body methods and NotImplementedError. After awhile, however, not declaring the abstraction at all started to make the most sense. Ruby relies on duck typing, and its only expectation is that the receiver of a message respond. If the receiver cannot respond then it’s the job of the interpreter to let you know. This gives us a lot of power. It allows the implementation of an abstract method to come from anywhere. In the example above it’s expected to be defined by a subclass. It could just as easily come from a mixin, a class redefinition, or runtime metaprogramming.

Conclusion

Next time you want to raise NotImplementedError please stop. 95% of the time it is not what you’re looking for. Instead consider documentation. You’ll get the comfort of declaring the abstraction and you’ll keep it real with Ruby.

Got questions or feedback? I want it. Drop your thoughts in the comments below or hit me @ccstump. You can also follow me on Twitter to be aware of future articles.

Thanks for reading!