Steven Harman

Maker and Breaker of Things

Reclaim Your Domain Model From Rails

TL,DR; When building an application using Rails, I prefer to keep all my model in app/models/. I reserve lib/ for those other things - those not-my-domain-things. I’d like to explain the what and why.

"Boundaries Amongst the Fields; Deep Greens"

Rails has a history of co-opting names, as happened when the ActiveRecord library used the active record pattern name. A similar co-opting has happened with the MVC pattern wherein many believe Rails is an example of the MVC design pattern. In truth, it’s probably closer to MVC Model 2… but I digress.

Model View What’s-that-now?

MVC stands for Model, View, Controller. In Rails-land we know what the Controllers are. And while we don’t have Views in the way that MVC meant, we do have view-templates, and we call those our views. The Model is meant to be all the things it takes to model our problem domain. As applied to Rails, the Model seems the most misunderstood/misused of the MVC triumvirate.

The No Man’s Land of Web Development

I think about the current state of web development experiences as a continuum. On one end we have traditional Rails-era web apps - full page loads, with bits of dynamism haphazardly mixed in. On the other are rich client-side JavaScript apps with their own structure and life cycles, standing alone and/or talking to an HTTP API.

"No Man's Land Flanders Field France 1919."

Rails-era web apps have some great tooling and deliver a pretty nice development experience. The shift toward rich client-side web experiences has lead to some great tooling that makes for a 1st-class web development experience.

A no man’s land

Between these two approaches lies a no man’s land. The tooling and techniques are focused largely on either end of the continuum despite the large population of apps living in the middle.

Git Clean: Delete Already-Merged Branches

TL;DR

To delete local branches which have alread been merged into master:

$ git branch --merged master | grep -v "\* master" | xargs -n 1 git branch -d

You can omit the master branch argument to remove local branches which have already been merged into the current HEAD:

$ git branch --merged | grep -v "\*" | xargs -n 1 git branch -d

Breaking it down

We start by getting a list of local branches which have already been merged into the current branch (i.e. HEAD)

$ git branch --merged

  add_new_user_gravatar_links
  assign_unique_key_to_uploads
* master
  remember_the_last_activity_per_user
  update_kaminari_to_thread_safe_version

We then pipe that to grep to match on the "\*" character, inverting that match via -v to get all merged branches sans the current one.

$ git branch --merged | grep -v "\*"

  add_new_user_gravatar_links
  assign_unique_key_to_uploads
  remember_the_last_activity_per_user
  update_kaminari_to_thread_safe_version

Finally we pipe that list in to xargs so we can strip apart the input and pass it on to a new command. We use -n 1 to ensure at most one argument is taken from the input to be passed to the invocation of the new command. The resulting commands that xargs will invoke are effectively

$ git branch -d add_new_user_gravatar_links
$ git branch -d assign_unique_key_to_uploads
$ git branch -d remember_the_last_activity_per_user
$ git branch -d update_kaminari_to_thread_safe_version

Pulling it all back together, we have

$ git branch --merged | grep -v "\*" | xargs -n 1 git branch -d

Deleted branch add_new_user_gravatar_links
Deleted branch assign_unique_key_to_uploads
Deleted branch remember_the_last_activity_per_user
Deleted branch update_kaminari_to_thread_safe_version

And there you have it. Go forth and clean up!

Bag of Methods Module and Grep-driven Development

Always looking for more concise ways to express ideas, I’d like to present two terms for your consideration.

BOMM |bäm| (abbreviation)
Bag of Methods Module
An anti-pattern for “sharing behavior” or “separating concerns” of an object. In practice such modules often contain code that is related in name or function, but lacking a cohesive purpose. See also: GDD.
GDD (initialism)
Grep-driven Development
A software development process that relies on searching full source code to find usages of methods and deduce intended behavior of a piece of code. Often caused by lack of coherent and cohesive design. See also: BOMM.

Thanks to fellow Highgroover, Andy Lindeman, for helping me to finally define these terms. Or at least, refine them.

Sensible Testing Is About Sensible Design

If you’ve not yet seen Justin Leitgeb’s GoGaRuCo talk, Sensible Testing, go check out the slides. I hope the actual talk is posted soon; I’m sure it’s more rich and full of context.

Overall I agree with most of Justin’s points. However, I get the feeling that he, like many folks, approaches testing as a method for verifying the correctness of code. As I understand the thesis, CUPID is to testing what SOLID is to design.

While I’m not opposed to laying down some names and concepts to improve the state of testing, I don’t belive testing should be the goal. It’s not about testing. I believe testing is a tool to be used in guiding your design.

The Accepts_nested_attributes_for Un-Solution

"merry go round"

Why does Rails’ accepts_nested_attributes_for approach always feel so darned wrong?

My suspicion is that it feels wrong because it likely is wrong - or at least it is likely the wrong tool for the job.

An example

An accounting of a recent ride I took into the accepts_nested_attributes_for merry go round.

In order to create a Message, I have to first create the Conversation it’s a part of.

This sounds like an explicit workflow, so I’ll model it that way.

… hours later …

FFFUUU, this is too complicated! There must be an easier, more Rails-y way.

I know, Conversations can accepts_nested_attributes_for :messages. Brilliant!

… hours later …

FFFUUU, this is too complicated! There must be a simpler way.

I know, rather than shoehorning this into an overly-coupled mess I’ll model it as an explicit workflow!

FML.

Remember, easy is not the same thing as simple.

image via: lolitanie.com

From Testing to Test-First to Test-Driven

When I started writing tests, around 2005, I was stoked just to have the tests.

When I started writing tests first, around 2006, I was excited because I was Doing The TDD.

A couple of years later I found that writing tests was getting really painful. Painful because they were so damn hard to set up, and painful because I had to wait too damn long (on the order of 10-15 minutes) for the test suite to run. I reacted to the pain by changing how I write my tests; I discovered mock objects. My tests got faster, but they were still painful.

A realization

In 2008 I was talking with Corey Haines about test pain, object-oriented design, and “listening” to the former to influence the latter. Scott Bellware also contributed much insight, forcing me to really think about what I hoped to gain from writing tests.

Those conversations help to crystallize it for me: the root cause of the pain was not the tests, but the design of the code under test. I had been doing test-first development, not test-driven design.

In the years since I’ve honed my technique for driving design by listening to tests and I continue to seek out the ideas and experiences of other fast test fanatics.

The Ruby and Rails communities have accelerated this path for many. I would say it’s not uncommon for new folks to get started where I was in 2005 or 2006. What’s more exciting is the growing numbers who are starting to feel some pain in how they test. The next step is to become more aware of that pain; lower your pain threshold and then make it stop hurting!

It’s a journey

It was by no means an overnight endeavour. It literally took years of work for me to figure this out, and I’m both happy and proud to say that I’m still learning. I hope by putting my experience out there, yours can be better, faster, MOAR!

Another Git Repository Visualization, Just for Fun.

I’ve created visualizations for Git repositories before – the one tracked a product from its first commit through launch. And while I still think there is some information and insight to be gleaned from such visualizations, the real reason I like to make them is… I think they’re neat.

To celebrate launching the latest incarnation of VersionOne, I made another visualization! This one tracks all changes made in our Git repository that occurred between our last major release (in late February) right through the very last commit that made it into the Spring 2011 release.

Wow… that really sounded like a sales pitch, didn’t it? I hate sales pitches!

Enough of that. Enjoy!

Git Pull With Automatic Rebase

To rebase, or not to rebase - for me its not really a question. I generally prefer a clean, linear commit history. Why? Because merge bubbles make history confusing, noisy, break git bisect.

y-u-no-rebase Don’t believe me? Check out the pretty log to the right. See all those merge bubbles in there? Eww!

The Why?

The workflow that caused those merges was as follows:

  1. git pull (to bring local up to date)
  2. hackity-hack
  3. git commit
  4. git pull
  5. git push

By default git pull will fetch any new commits from the remote, and then merge any local changes in, resulting in the merge bubbles.

An Io Language Vim Plugin

Who here doesn’t enjoy a little color in their life? I know I do, especially when used to highlight the syntax of a language - as anyone who’s been around me while downing a few pints can attest!

Learning, Io, and Vim

In an attempt to feed our insatiable desire to learn, a few of us at VersionOne are doing a book club on Seven Languages in Seven Weeks. We’re currently working on chapter 2: Io. My current favorite editor is Vim. I wanted syntax highlighting for Io, in Vim.

I found a decent Vim script to get Io syntax highlighting, and then wrote a quick ftdetect script to set Io-related files to use the Io syntax. The resulting vim-io plugin is currently embedded in my dotfiles on the GitHubs, but if there’s interest I can pull them out into a standalone plugin.

Grab it, enjoy it, fork and improve it!