SBPP #2: Smalltalk Patterns in Ruby

Smalltalk Best Practice Patterns continues from the introduction with a brief explanation of patterns. Some notable quotes:

  • About leveraging commonality: “large-scale software re-use has not proven to be the answer”. A lot of the mid-90s OO PR centered around the idea that we’d all build our apps out of reusable off-the-shelf objects. As Beck notes, this didn’t really pan out. With rare exceptions, in-process software re-use still takes the form it always did: it happens at the “library” level of granularity, not at the object level. Patterns have been a much more successful way to re-use ideas.
  • “By carrying along their justification, patterns avoid the problem of most “style guides” that simply prescribe solutions without discussing why or when the solution is appropriate”.  Ironically, I often hear the criticism that patterns are “prescriptive, one-size-fits-all solutions”. When I hear this it makes me wonder if the person saying it has read a patterns book lately. Central to the form is a careful discussion of when the pattern makes sense, and when it doesn’t.

Once I got into the meat of the book I decided that, since I’m reading it for the Ruby Rogues book club, I should probably take a stab at translating the patterns to Ruby. You are welcome to follow my progress on GitHub: Also, feel free to fork and submit pull requests for alternate translations. There is definitely room for interpretation on some of these.

  • On Composed Method, this bit is key: “keep all operations in a method at the same level of abstraction”. I hate it when I find a system that has been broken up into small methods—except that the small methods still combine high-level calls with fiddly, low-level code. Code like this has all the disadvantages of small methods (harder to follow the logic) with none of the advantages (only having to introduce a change in one place).
  • There are a number of construction & coercion patterns early in the book. One thought that sprung out to me in reading these is that I don’t spend enough time thinking about writing alternatives to “.new” in Ruby code. More often, I just write a fancy “#initialize” which can handle various combinations of arguments. But there’s a good argument to be made in many classes for avoiding .new and instead defining more specific forms, e.g. Point.new_from_coords, Point.new_from_polar.
  • That last point is relevant to Rails code. A lot of the specialized factory methods I see for testing (“Factory.create(:admin_user)”) really ought to have analogs on the original model (User.new_admin).