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
@cog. We use the methods instead of the instance variables which has the effect of altering
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
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
tire is at index
 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 we have message sends to
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…