Constraints Driven Development

”. . . every time you write code, you’re experimenting. . . . Usually, I’ll make a specific kind of constraint for myself . . . and see how it shapes my code. And if I like it, I might roll that into the main project or I might just throw it out . . .”

Dan Kubb said that during the 047 Ruby Rogues podcast.

This is, without a doubt, the most inspiring thing I have listened in the last 12 months. I have been following the same technique for a while, and I am confident to say it is a great tool to help us hone our craft.

So, I invite you to experiment new things in your code. It does not matter if it is an elaborated design pattern or a simple variable naming rule. Pick a constraint, anyone, and force yourself using it for the next couple of hours. If you feel it is improving your code, e.g. easier testing, more readability or expressiveness, loosely coupling, etc., keep it. But if it is not, drop it, otherwise you may be wasting time. Next are some examples you can try.

During the same podcast, Dan mentioned he had been using strict command query separation (CQS) for every method he wrote. And if it was a command, he was returning self to enable chaining.

Dan also commented how he solved the problem of Heckle taking too long to mutate his code. He split test files per method, so he could mutate specific tiny parts of the system and cut down execution time.

Speaking of CQS, Sandi Metz gave a talk (slides) at RailsConf 2013 on how to unit test command and queries. She proposed some testing rules and defined a schema called: The Unit Testing Minimalist.

Sandi also proposed four rules for developers in the 087 Ruby Rogues podcast. The guys from thoughtbot also shared their experience applying these rules, and how elegantly they had satisfied one of the constraints.

Jeff Bay proposed nine “rules of thumb” to better software design in the essay entitled Object Calisthenics in the ThoughtWorks Anthology.

These are enough examples to start. You can shall define your own constraints too. One of my actual constraints is to completely take apart routing definitions from controllers specs. This helps me define better URL design and treat controllers more like normal classes instead of some magic black box which receives requests. And I think controllers should not know anything about routing and HTTP verbs anyway, so it is making sense for now.

I ended turning this:

# spec/controllers/posts_controller_spec.rb
# Tighly coupling between routing and controller actions
describe "GET show" do
  # ...
end

into this:

# spec/routing/posts_routing_spec.rb
# Routing knows about HTTP verbs
describe "Access a post" do
 it { expect(get("/posts/1")).to route_to("posts#show", id: "1") }
end

# spec/controllers/posts_controller_spec.rb
# show is an ordinary method in the controller
describe "#show" do
  # ...
end