Unobtrusive Ruby

Mike Burns

Unobtrusive Ruby is any Ruby code that stays out of your way. It does not make you write lots of boilerplate, or stub methods, or open classes. It is decoupled. Its tests run quickly, its classes fit on one screen, its methods are tiny, and it is quickly refactorable.

Unobtrusive Ruby is a state of mind. Unobtrusive Ruby is what you want your friends to write.

Since you love your friends, here are some guidelines while you design your next gem or framework:

Take objects, not classes

All your arguments should be instantiated objects, where the caller has invoked the .new method herself. Leave the constructor up to the class author. Never force a calling convention on a constructor, or in any way force someone to look up how to instantiate her own class.

Never require inheritance

Object inheritance is one way to force the user—your friend—to do odd things with the constructor. When to call super, what the arguments are, and so on. This goes for mixins, too; they add complexity to the class’s namespace, increasing the cognitive overhead. All inheritance adds brittleness.

Inject dependencies

The contents of a class should mention no other classes by name. Pass in all objects that it must use. Not only will you thank yourself for the flexibility later, you’ll notice that your tests are better at the beginning.

Unit tests are fast

A unit test on a small class should be fast, and classes should be small. Mock objects, a lack of inheritance, and dependency injection will see to it. The tests for your friend’s code should not have the same dependencies as the tests for your own code. The ideal dependencies are nothing more than the test framework and the class under test.

Require no interface

Classes should care about composing instead of being composed. The best class will consume instead of being consumed. It makes its own rules. Maybe you can’t get there—something has to be consumed at some point—but it’s a useful goal. If it’s not possible, the required interface must be simple. One method, maybe two.

Data, not action

Data is easy to test: pass some values into a method, receive a value from the method, then verify that it’s the right value. Never force your friend to do anything more than this. Never force them to do database lookups, system calls, random number generation, and so on; do that for them.

Always be coding

The overall idea here is that your friend should always be able to just write code. You never want to stand in her way; never force documentation or change her classes or invent bizarre loopholes. You, as the gem author and framework designer, want your friends to build their system without noticing the system you’ve built.

Unobtrusive Ruby does what you expect.