Though I’m still in the early chapters of POODR, I can already tell this is going to be a monumental asset not only to my understanding and appreciation of Ruby, but also to my sensibilities and skills as a programmer. Most laudably, it’s just written so damn well. Maybe too well, as one reviewer has tellingly marveled:
“I was rather surprised how, even though the book starts with simple examples, it quickly develops and builds on them to provide good explanations.”
In other words, POODR is comprehensible, digestible, and accessible. As such, it’s actually an effective learning tool. Shocking!
Anyhow, the crux of this post is — in addition to praise for Metz’ work — the Ruby
Struct class. I came across this neat little ‘class helper’, if you will, for the first time in Chapter 2 of POODR.
What is a Struct?
According to the official Ruby documentation, a Struct is “a convenient way to bundle a number of attributes together, using accessor methods, without having to write an explicit class.” After playing around with it a bit in pry, it feels like a quick and cheap way to create
Class-like instances on the fly that can possess both behaviors and qualities (much like regular
Classes). Here’s a sample
Struct that I’ll build out called
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
Cool, right? Remember, the symbols you pass to your new
Struct upon initialization — in this case
:gender — act like regular
attr_accessors. So I could make some alterations after the matter, like so:
1 2 3 4
…but that might be a little confusing.
I can now also make a bunch of new
Persons, instantiating each one with his or her name/age/gender, and he or she will also respond to the
When would you use a Struct?
This is a great question. It wasn’t immediately clear to my why or when one would use a
Struct, especially when the more ubiquitous
Class is always an option. According to what I’ve read so far in POODR, it seems that using a
Struct is one way to separate structure from meaning; it plays nicely with
Classes, and also helps to make your methods more transparent.
If all of that sounded a bit vague and not yet super helpful, then it might help to look at another example wherein a
Struct is used within a
Class in order to break down method responsibilities and also make those methods more transparent:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
Class above takes a parameter called ‘data’ — in this case, that data is coming in the form of a 2-dimensional array. It is immediately dealt with upon initialization, calling on a method named
structify(data) that turns each
[name, gender] pair from the given array into
Struct objects that can be further dealt with via the
:participants attr_accessor, and which respond to both
In taking this approach, we were able to give the TransparentRoster class mostly the illusion of single-class responsibility (i.e technically, the Roster class shouldn’t be responsible for, say, initializing new
Persons; it should deal solely with duties that might sensibly pertain to a Roster like listing names, ordering them, etc). Furthermore, we were able to keep all of its methods small and single-purpose as well. Finally, the handling of raw data was kept limited to one place — the
structify(data) method — so that if the given data were to change from a 2-dimensional array to a different structure, such as a hash, the code to extract the necessary data would only need to be altered in one place. All other method dependencies could remain relatively unharmed.
I’m curious to see in what other contexts and real-life code bases I might come across
Structs. So far, they seem like a great tool for managing single-class responsibility when you’re not yet sure how many classes you ought to build or of what magnitude these classes should be for an evolving project. There’s a lot left of POODR to read so maybe subsequent chapters will shed further light on this.
- POODR is awesome.
Structis a convenient way to bundle together attributes without having to build out or commit to building a whole
Structs can be included within
- If done so, a
Structcan help illuminate the given
Class’s ‘single purpose’ by handling the extraneous stuff; this also keeps the
Class’s methods short and sweet.