Project Ramon

A learning journey from a Ruby noob perspective

Write Ruby that Embraces Change


Today’s post comes from Sandi Metz’ book entitled Practical Object-Oriented Design In Ruby. I’m re-reading this for the first time since I started AirPair. I really enjoyed reading chapter 2 recently, because it contains illustrations on writing flexible code from the viewpoints of class creation and management, method creation and abstraction and she even demonstrated a way to handle complex data structures with Structs. This book is excellent for someone like myself. We’ve probably heard about DRY (don’t repeat yourself) code,  I am thankful that this book provides demonstrations on how to write in such a manner so that future changes can be made in one place.

Hide then Seek: Instance Variables

Sandi shares the benefits of hiding variables, even from the class that defines them, by wrapping them inside of methods. This way, we will have only one place in our code base that understands what the instance variable means.

Here is an example pulled from her book:

This first example shows the ratio method accessing the instance variables directly. And this,

demonstrates what happens when we use attr_reader to create wrapper methods to house @chainrig and @cog. We use the methods instead of the instance variables which has the effect of altering chainrig and cog from data thats referenced all over into a behavior that has been defined one time. Always hiding data from ourselves provides the benefit of adding protection to our code from being affected by unexpected changes in the future.

Hide then Seek: Data Structures

Here’s a quote from pg. 26 of Sandi’s book.

If being attached to an instance variable is bad, depending on a complicated data structure is worse. Direct references into complicated structures are confusing, because they obscure what the data really is, and they are a maintenance nightmare, because every reference will need to be changed when the structure changes.

To do anything useful with the above diameters method as it stands each sender of data has to have complete knowledge of what piece of data is at which index in the array. The diameters method essentially has two responsibilities. How to calculate diameters and where to find rims and tires in the array. Sandi mentions that the dependency, in the above example, is on the array’s structure.

The knowledge that rim is at array index [0] and tire is at index [1] should be known in just one place. She solves this issue by using Ruby’s Struct class. Just like we used a method to wrap our instance variables earlier, we can abstract out our array structure into a Struct.

Now instead of references to cell[0] and cell[1] we have message sends to wheel.rim and wheel.tire. This is an improvement from indexing into a structure to sending messages to an object.

If you’d like to learn a little more about Ruby’s struct class, I invite you to check out an older post of mine, which includes a link to a post on the same topic, but in greater depth by Steve Klabnik.

If you are looking to make your code more maintainable and/or just want a sincere and meaningful understanding of object-oriented program design, you owe it to yourself to pick up Sandi Metz’ book.

Oh, and one more thing…



Categories: Ruby

Tags: , ,

1 reply


  1. Embracing Change pt. 2: Enforcing Single Responsibility Everywhere | Project Ramon

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s