The Hashrocket Blog
The Hashrocket blog is collectively written by the Rocketeers via their own blogs. Content is then aggregated here if it relates to Hashrocket.
-
Ensure With Explicit Return
Quick! What does the following method do when
thing.method_that_might_raise!raisesSomeAppException? And why is this a code smell?1 def some_method 2 thing.method_that_might_raise! 3 ensure 4 return thing 5 end
Before giving the answers to these two questions, let’s go over what
ensuredoes.The
ensureclause in Ruby is run regardless of whether a block has thrown an exception or not. A simple example is opening a file1:1 def file_open_with_auto_close(name, mode = 'w', &block) 2 f = File.open(name, mode) 3 puts "calling your block" 4 yield f 5 ensure 6 if f 7 f.close 8 puts "file safely closed" 9 end 10 end 11 12 file_open_with_auto_close('test') do |file| 13 file << 'data' 14 raise 'exception raised' 15 end 16 # 17 #calling your block 18 #file safely closed 19 #RuntimeError: exception raised 20 # from (irb):14 21 # from (irb):4:in `file_open_with_auto_close' 22 # from (irb):12
Even if there is an exception while processing the file, like the one we
raiseon line 14,ensureallows us to close the file.After the
ensureclause has run, Ruby either continues the exception handling (in this caseirbrescues it and gives us a stack trace) or continues executing the block.Except if you have an explicit
returnstatement in yourensureclause.Let’s take a look at the difference in
irb, first without an explicitreturnstatement:1 def ensure_without_return 2 yield 3 ensure 4 puts 'ensure' 5 true 6 end 7 8 ensure_without_return { puts 'block'; false } 9 # 10 #block 11 #ensure 12 #=> false 13 # 14 ensure_without_return { raise 'exception raised'; puts 'block'; false } 15 # 16 #ensure 17 #RuntimeError: exception raised 18 # from (irb):21 19 # from (irb):16:in `ensure_without_return' 20 # from (irb):21
Note that although the
ensureclause is run after the block from line 8, it has not changed the return value of the method.And now with an explicit
returnstatement:1 def ensure_with_return 2 yield 3 ensure 4 puts 'ensure' 5 return true 6 end 7 8 ensure_with_return { puts 'block'; false } 9 # 10 #block 11 #ensure 12 #=> true 13 # 14 ensure_with_return { raise 'exception raised'; puts 'block'; false } 15 # 16 #ensure 17 #=> true
The first thing to note is that the return of the method is now determined by the
returnstatement in theensureclause on line 5.The second thing to note is that the explicit
returnstatement acts as an implicitrescueclause, allowing the code to resume as if no exception had been raised.Summarizing:
- an
ensureclause runs whether an exception is raised or not - an
ensureclause without an explicitreturnstatement does not alter the return value - using the explicit
returnchanges the control flow as if arescue Exceptionclause was in place before theensureclause
Back to our original questions. You should now know what the method does when
thing.method_that_might_raise!raisesSomeAppException.But why is this a code smell? Consider the following code:
1 def some_method 2 thing.method_that_might_raise! 3 rescue Exception 4 # we have rescued all possible exceptions 5 ensure 6 return thing 7 end
Line 3 is a code smell. Rescuing all exceptions is not desirable. From our exploration of
ensurewe can see that this code is the equivalent of the original code.Can we refactor it? Yes. Yes we can.
When we can recover from
SomeAppException, we can justrescue:1 def some_method 2 begin 3 thing.method_that_might_raise! 4 rescue SomeAppException => e 5 # do something clever here 6 end 7 thing 8 end
And when we cannot recover from
SomeAppException, we just let the exception propagate up the call stack:1 def some_method 2 thing.method_that_might_raise! 3 thing 4 end
1
File.openalready does this. - an
-
You Say Tomato
I say Pomodoro!
After a significant amount of time and effort and the gracious help of several contributors, I’m proud to officially announce tomatoi.st.
For those in a hurry
tomatoi.st is a simple timer application that helps you implement the Pomodoro Technique. You should totally use it.
The Story
While pairing with Corey Grusden a few months ago, we decided to experiment with the Pomodoro Technique. We immediately found that it helped improve our productivity and fight off project fatigue. Plus it gave Corey some officially sanctioned time in which to deal with his digital logorrhea (SMS much?). Needless to say, we were hooked!
The immediate hurdle was that the software available for doing the timing was lackluster (fwiw, decent software has since been developed). In light of this, we spent the first few days working with a simple
sleep 1500 && growlnotifytype solutioni which was inelegant at best. More importantly, it was missing an utterly essential piece of functionality: the ability to start a timer at my desk, go to the john, and check up on the time left in a break whilst on the throne!And so, in pursuit of this lofty goal, a tomato was born.
What it does
tomatoi.st does very little, but we like to think it does it very well. ahem.
- Visit http://tomatoi.st
- Click the “Pomodoro” button
- Start a focused unit of work
- When you hear the “ding!”, click “Short Break”
- Take a break, go to the john, whatever
- Rinse and repeat
It is suggested that you do 4 sets of Pomodoros. The first three are followed by a short break, the last by a long one. tomatoi.st makes the assumption that you’ll be doing them in that order and handily suggests the next timer you should do by highlighting it’s button in green when the previous timer expires. Your current timer is highlighted in yellow while it’s underway and then red once it’s expired. Your timer history is tracked just below the big ticker.
Timers out of sync with reality (say, after a long lunch)? Click the “Reset” button to start fresh.
Want to come back to this set of timers tomorrow? Customize the name of the timer and then “rename” it so it’s easy to remember.
What it doesn’t do
It is not intended to be a full implementation of the Pomodoro Technique. Notably absent are things like task planning and daily review.
What’s next
Coming up promptly is integration with Fluid’s javascript API to provide neat things like Growl integration.
Want to help shape the face of what tomatoi.st will become? There are a number of ways you can help do so:
- scratch your own itch and fork it on github
- file a github issue
- peruse and/or add to our tracker project
- or make a request below in the comments
-
Given Due Consideration
Or: Just Say No to Cukes
As alluded to by veez, the undercurrent from some of us at Hashrocket has been decidedly anti-cucumber. Here’s my brief littany:
- A well developed cucumber suite is invariably slow to run
- For me, at least, it makes development feel slower (this is almost certainly perceptual, but that doesn’t mean it’s not actual as well)
- The indirection makes debugging laborious
- Matching plain english to executable code via regular expressions just feels wrong
All of these things (and more) have been excused for quite some time because Cucumber is thought of as a necessary tax. If you want to do full stack integration testing in Ruby… this is how it’s done.
Here’s the good news: it’s not the only way! Veez has gone over the basics in the post I linked above, so I won’t belabor the setup, though I will give you the latest version. Here are the relevant bits of my
spec/spec_helper.rb:require 'webrat' require 'spec/support/integration' Webrat.configure do |config| config.mode = :rails end Spec::Runner.configure do |config| config.include(Webrat::Matchers, :type => [:integration]) end class ActionController::Integration::Session; include Spec::Matchers; end
Interleaving the above into your existing
spec_helper.rbis all you need to get going.Let’s use this user story from a project I’m working on now as the backdrop to our discussion:
In order to dissolve a business relationship
As a user
I want to be able to remove a colleagueScenario:
Given a user with colleagues
When I click a colleagues “Remove colleague” button
Then I should be on the colleagues list
And I should not see the colleague
And the colleague should not see me in their colleague listHere’s how you might implement that using RSpec and Webrat:
describe "User removes colleague" do before do login_as @user visit colleauges_path click_button 'Remove colleague' end it "redirects you to the colleagues list" do current_url.should == colleagues_url end it "removes them from my colleagues list" do response.body.should_not have_tag('#colleagues .colleague') end it "removes me from their colleague list" do logout login_as(@colleague) visit colleauges_path response.body.should_not have_tag('#colleagues .colleague') end end
That’s all well and good, but you may be saying to yourself (or your co-worker, or your poor, terrified cat): “But, that doesn’t capture the plain english user story! Darn it all to Bethesda!”. And you’re absolutely right… but how’s this strike you:
Feature "User removes colleague" do Given do login_as @user visit colleagues_path click_button 'Remove colleague' end Scenario "removal" do When "I press remove" do Then "I should be on my collegues list" do current_url.should == colleagues_url end And "I should not see the user in my colleagues list" do response.body.should_not have_tag('#colleagues .colleague') end And "My colleague should not see me in their colleague list" do logout login_as @colleague visit colleagues_path response.body.should_not have_tag('#colleagues .colleague') end end end end
@l4rk and I came up with this clever bit of aliasing to get you where you want to go. Just add this at the bottom of your
spec_helper.rb:module Spec::DSL::Main alias :Feature :describe end module Spec::Example::ExampleGroupMethods alias :Scenario :describe alias :When :describe alias :Given :before #TODO: make Given take :before or :after and :each or :all alias :Then :example alias :And :example end
The failing of this technique, for the time being, is the round-trip output:
User removes colleague removal I press remove
- I should be on my collegues list
- I should not see the user in my colleagues list
- My colleague should not see me in their colleague list
But we’re already scheming up a way to improve that situation, so stay tuned as the story develops.
-
Twiki
While pairing with @wesgibbs on a project at hashrocket, we got in the habbit of ‘testing’ our migrations by doing the following:
rake db:migrate db:migrate:redo db:test:prepare
At some point; frazzled and dealing with a migration that kept breaking while running the above, I uttered: “db-db-db”, which was subsequently flipped around to “bidi-bidi-bidi”. Now, as a proud (well, kinda) son of the 80’s, my mind went immediately to Pamela Hensley… and soon thereafter, to Twiki of Buck Rodgers and his perennial tag line.
And so the following shell script was born (Mac only, sorry windozers):
twiki () { say -v Zarvox 'beedee-beedee-beedee' rake db:migrate && rake db:migrate:redo && rake db:test:prepare }
The speed and voice aren’t quite right, but the sheer cheese factor cracks me up on the regular, so I figured I’d spread the wealth ;)
Also of note: the Twiki throwback dance mix
-
Pair Programming & git & github & Gravatar & You & You
Or, how Hashrocket displays pair programming gravatars on github.
The Peculiar Problem of Pairs
At Hashrocket, we pair program all the time. We also use git exclusively for source control. This presents a problem:
gitonly supports one “commiter,” but we’d like to give credit to both developers. Here’s how we hacked it.Author vs. Committer
First, a bit of background:
gitdoes support the notion of an “author” as distinct from a “committer.” This feature handles the situation where some external third-party developer has submitted a patch to a source maintainer. The maintainer, as the authoritative and github-credentialed “committer,” can commit the changeset for the external developer, who is set as the “author.” Both the author and the committer are recorded in the commit data.We did think about setting one pair developer as the author, and the other as the committer. But, then we thought of something we think is even sexier.
Set the Pairs in the Author Fields
Unfortunately,
gitonly supports one “author” as well. But, the author fields do provide us a workable place to hack in our pair attribution solution: we concatenate and store both pair developers usernames in the those author fields. In theBASHshell, that goes a little something like this:bash$ export GIT_AUTHOR_NAME='Jon Larkowski and Tim Pope' bash$ export GIT_AUTHOR_EMAIL=dev+l4rk+tpope@example.com
The convention we use for
GIT_AUTHOR_EMAILis the form:dev+pair1+pair2@example.comwhere “dev” is short for “developer.”devis just an email alias that goes to every developer at Hashrocket. The pairs are added in alphabetical order by github username. We hack our usernames into the email address using the “plus-notation” feature of email addresses.Configure the Committer
Committer for a Developer’s Laptop
As for the committer field, it’s just the developer whose machine you’re pairing on. This allows us to tell which user this commit came from, while still indicating the pair authors. Also, it allows us to simply use that developer’s github credentials for pushing up changes. So the
git log --pretty=fullafter a commit looks something like:commit 3eb7b3a155f11e56cf406f2b09dc2fd98e92b532 Author: Jon Larkowski and Tim Pope <dev+l4rk+tpope@example.com> Commit: Jon Larkowski <jon@example.com> Ebony and ivory, live together in perfect harmony.Committer for a Shared Pairing Workstation
We do have one twist on the committer. More and more, we’re using communal desktop machines at Hashrocket. We have a couple Macs Pro and a couple Macs Mini (I assure you, those are the proper irregulars plural, look it up). On these shared machines, we name the committer after the machine’s name. This allows us to know which machine a commit came from, but it’s not attached to any particular developer’s name.
bash$ git config --get-regexp user\.* user.email dev+some_workstation@example.com user.name Some Workstation
Also, note that the shared development workstation will need to have its own public key registered on github, under your organization's main github account, not your own personal one.
github & Gravatar Photos
github displays a Gravatar photo next to a username when displaying commit information. This helps add to the “social” feel of github.
Single Developer Gravatar Photo
For you as a lone developer, github just looks up that gravatar based on the email address you gave github when you signed up.
Developer Pair Gravatar Photo
Now for a pair, we need a unique email address that github can use to look up a photo on gravator. This is where our pair developer email address convention comes into play. We just add that
dev+pair1+pair2@example.comas a new email address under our main corporate gravatar account, which is maybe signed up underinfo@example.comfor instance.Gravator lets you have as many email addresses as you one under one main umbrella account. It’s a bit spammy, in that every developer will receive a gravatar confirmation email whenever a new pair permutation signs up. But, that sounds like a “First World problem,” if I ever heard one.
Say, “Cheese!”
We typically just snap our pair photos using Photo Booth.app, since we’re likely pairing at that very moment on a Mac with a built-in iSight camera. Oh, and since we’re picky, we make sure that
pair1is on the left andpair2is on the right of the photo.Hitch
Setting
gitenvironment variables by hand every time you switch pairs could get tedious. Ro and Les wrote a little gem called “Hitch” that makes this easy.Install it with:
sudo gem install therubymug-hitchTo set it up, follow the prompts and answer the questions:
hitchrcWhen you start pairing with someone, just call:
hitch your_pairs_github_usernameTo code solo:
unhitchTo pick from the list of your previous pairs:
hitch -iJust running hitch, with no arguments, will tell you who you are pairing with. Pro tip: Add it to your
Bonus, can hitch/unhitch from withinbashprofile to see it when you start a shell.vim, i.e.:!hitch github_username
Hardcore BASH Scripting Action
Here's a BASH script that accomplishes the same thing as hitch.
To set up a pair:
bash$ pair fry bender
Bender Bending Rodriguez and Philip J. FryTo enter a pair that's not a declared variable at the top of the script:
bash$ pair fry hypnotoad="All Hail the Hypnotoad"
Philip J. Fry and All Hail the HypnotoadTo persist a pairing, even between shell invocations:
bash$ pair -w zoidberg bender
Bender Bending Rodriguez and Dr. John ZoidbergUse pair with no arguments to see who's paired. Use pair -w with no arguments to clear a persistent pairing.
-
BizConf Venue Teaser
BizConf Venue Teaser from Hashrocket on Vimeo
-
Pairing With Hitch
Pair programming does present some unique problems, one that we encountered at Hashrocket was commit attribution: a commit message would be identified with one member of the pair only. This is not exactly tragic, but from the perspective of a passioniate developer, having commit credit (and accountability) is a critical and visible part of the ethos.
Tim Pope had the brilliant idea of using a group email address with tags (such as group+you@example.com) to identify the commits a pair made to git. A little bash script fu lead to a nifty command line utility that let us track pairs with our git commits. With that script as a starting point, Ro Samour wrote a pure ruby implementation:
hitchhitchwill modify your git configuration to reflect who you are pairing with. Here is ahitchcommit message usinggit log --pretty=full:commit e518dd0637e7d1d77d3bd79a645e5d0bc93eae2d Author: Les Hill and Rogelio Samour <bleep+bleep+bleep@hashrocket.com> Commit: Les Hill and Rogelio Samour <bleep+bleep+bleep@hashrocket.com> Adding show note iconThis is a commit message from
hitchon github:
hitchis open source and is available from github.Getting started
You will need to install the
hitchgem from github1:% sudo gem install therubymug-hitchYou will need a group email account with a service such as GMail that allows email tags2 (as an example,
newsis a tag in this email address yourname+news@example.com which is considered to be the same email address as yourname@example.com):You really want a Gravatar for your group email account so that the commits show the custom gravatar along with your commit messages. For every pair, register a new gravatar and associate it with a tagged email address of the form:
dev+github_user_1+github_user_2@example.comThe github usernames should appear in the local part of the address in alphabetical order after the group address local part, each github username seperated by a
+.Initialize
hitchby runninghitchrcand giving it your name, github username, and group email address when prompted:% hitchrcUsing
hitchTo pair with another developer whose github username is
pair:% hitch pairhitchwill prompt you if it does not recognize github username of your pair and save it for later use.To unpair and code solo:
% unhitchTo see who you are currently paired with:
% hitch1 Add
github.comto your gem sources withgem sources -a http://gems.github.com/2 Read about email tags on Wikipedia
-
On my first tattoo

Some people have asked why I’ve got a Hashrocket tattoo on my calf. The reasons are pretty biographical; ‘ware ye the history contained herein. Credit for the photo goes to Travis Schmeisser.
Each Wednesday Hashrocket has a midweek get-together called Hashrocket Hot Hackers Hump Day Happy Hour (or 6H). It was a chilly January evening and there were almost a dozen rocketeers milling about at the local martini bar when Sal casually asked if I wanted to go get a Hashrocket tattoo with him.
Of course, inebriated as I was, there wasn’t much chance I was going to turn down the idea of getting a Hashrocket tattoo.
Yet, there was a time when I considered tattoos silly things that a person gets to show how edgy he or she is, or to indicate an extreme level of I-will-kick-your-ass. Now I’ve got one. So why choose to get a Hashrocket tattoo?
I’ve become quite enamored of Hashrocket since I arrived in Atlantic Beach at the end of March in 2008. I was still a recovering burn-out when I came down here, and somehow Hashrocket refilled my spiritual-coding cup. That sounds extreme, but it’s just the way things are.
I spent five years at a county-level government IT shop as a web programmer. I serviced sixteen department websites and also wrote an intranet from the ground up that served 1700 employees while I was there. My boss was lost on anything past FrontPage and for help I had only a string of limited-engagement, part-time assistants of varying levels of skill.
I burned out. Totally and completely. I threw away all of my computer gear and went back to auditing hotels overnight and contemplatively staring at the moon. After about a year, I had the realization that software is what I do, and no matter how burned I felt or how much I wished otherwise, it seemed that was the value I would provide to society.
I began the slow road back to development by working as a part-time webmaster at a non-profit. Then Tiger turned me on to Ruby on Rails, and things started to happen inside of me. A strange sensation that, after experiencing a few times I was able to place: happiness. I was happy writing ruby code. I was happy using the rails framework. Just typing out each line of code somehow made me feel good.
That’s how I came to be a Rails consultant in Madison, Wisconsin. My first paid site was completed in November, 2007, and I’ve never looked back.
When Tiger invited me to come down and see how Hashrocket does things in March of 2008, I was excited to see the magic sauce that had both he and Lark raving about the company. I didn’t expect to be offered a job, but I was, and it’s been the best thing that’s happened to me.
In many of the same ways that ruby and rails took away the pain of coding for me, Hashrocket has taken away the pain of work and replaced it with happiness. Pair programming has made me a more effective and efficient programmer. Communicating all the time has taken away all the bad conversations, because nothing has time to fester. Test-driven development gives me a level of confidence in my code that makes me unafraid to change even systems I haven’t looked at in ages. I feel encouraged to excel as an individual rockstar within the community, even on the Hashrocket clock. As Les Hill (in the photo, on the right) is wont to remind us in his blog posts, working at Hashrocket is like attending an ongoing seminar.
All of these reasons, from my discovery of Ruby on Rails through joining Hashrocket and even becoming a presenter at local user groups, this is why I have a Hashrocket tattoo on my calf. If I never have another experience that I want to commemorate with a tattoo, I’m glad I’ve had this one.
-
Most Bugs Fall to the Second Pair of Eyes
While recently discussing if a power law applies to bugs at the ongoing seminar I sentimentally call work, I noted a corollary to Linus’s Law.
Linus’s Law states:
Given enough eyeballs, all bugs are shallow
The corollary is:
Most bugs fall to the second pair of eyes
That is, just having one other developer look at a bug will likely resolve it. Of course, developer’s who are pair programming already know this and are ahead of the game.
On a related note, pretty much every developer has been in the following situation. You are called over by a collegue to look over a bug, often accompanied by the statement, ‘This should work.’ You give a cursory examination and you resolve the problem with a quick change, often one that is obvious (after you pointed it out!)
If you come away from that experience thinking ‘Fresh pair of eyes’ or some such, good for you, you passed the test.
If you come away from that experience thinking ‘I am so awesome!’ or some such, not so good for you, you are probably not even competent.
-
Velocity Is Not Destiny
One of the most persistent and pernicious stumbling blocks I see when a team is starting out with Agile1 is equating story points and velocity directly with hours.
Often this stumbling block is not apparent immediately; it often crops up after a few iterations have passed. As an example, a stakeholder who was new and unsure about agile, was eager to have a release a month into development as an affirmation of the decision to go with an agile approach. After we had prioritized the feature set for the release, he turned to me and said, “Let’s see, we have 78 points in the release, so we can deliver the release four weeks from today.”
My answer, “Not exactly”, surprised him.
If the velocity of the team is an evidence-based number using the teams own story point estimations, how could such a statement be incorrect? There are two related reasons such a statement needs to be qualified to be useful, the Planning Fallacy and Velocity is not Destiny2.
The Planning Fallacy
As described in the Overcoming Bias blog, when students were asked in an experiment to forecast when they would complete an assignment:
“Even when asked to make a highly conservative forecast, a prediction that they felt virtually certain that they would fulfill, students’ confidence in their time estimates far exceeded their accomplishments.”
More generally, this phenomenon is known as the “planning fallacy”. The planning fallacy is that people think they can plan, ha ha.Since giving up on planning is not an option, we can make our estimates better through various techniques, one of which is to plan based on similarity to other known efforts, instead of estimations of time.
a cross-cultural study, found that Japanese students expected to finish their essays 10 days before deadline. They actually finished 1 day before deadline. Asked when they had previously completed similar tasks, they responded, “1 day before deadline.”
Agile mitigates the planning fallacy by eschewing estimates in hours or days and using story points3. Story points are abstract esitmations based on similarity; a 4 point story should be of the same relative size or complexity as any other 4 point story. Time is not a factor with story points.
Velocity is not Destiny
Given that story points yield better estimates, and velocity is an evidence based aggregate number smoothing out variations in individual stories, why qualify saying we can deliver four weeks from today? Velocity is a continuous measurement of the past performance of your team and is not a constant. The velocity of your team is a dynamic variable giving you direct and constant insight into how they are progressing. A future iteration has no velocity, as it has not been (and cannot yet be) measured. We can make predictions about future iterations based on velocity, but we cannot make any iron-clad guarantees.
An analogy might help explain how to think of velocity. You are taking a long automobile trip you have never taken before, where you will leave at 9 a.m. and travel 250 miles to arrive at your destination. Your car will accurately report your average velocity on the trip. 125 miles into the trip, your car reports an average velocity of 62.5 miles per hour, and you are currently on the highway going 70 miles per hour. How long do you have left, and how much money would you bet that you are accurate within one minute? Intuitively, most people understand that although the very clear math says you are 2 hours away from your destination, there are too many pitfalls such as traffic, accidents, road work, weather conditions, signals, etc to make a prediction that is accurate to the minute. (With your final average velocity, the very clear math will yield an exact and accurate result.)
Making the Release
There are many pitfalls in any software project, the one which was making me cautious about our release was a common one for novice stakeholders, Release Induced Focus. RIF is the tendancy for novice stakeholders to only really pay attention when they have an immediate release pending, leading to a spike in the number of stories rejected and bugs filed, and a corresponding drop in velocity. Given an experienced stakeholder who is rigorous about acceptance, the bug tax on velocity is taken out of velocity over time; with RIF the entire bug tax on velocity is paid in one or two velocity sapping iterations.
After explaining this, and using velocity as a predictor, we adjusted our plan for the release. We reprioritized the backlog to front load all the required features, moved unneeded features out of the release, and had the stakeholders exercise more rigor when doing their acceptance. The release was made in four weeks, with the team and stakeholders delivering tangible value without the long hours and anxiety provoked by more static approaches to software project management.
Velocity is a Dynamic Measure
Velocity is a continous measurement of your team’s past performance over time; all of the previously known and unknown risk variables have been surfaced, made known, become constants, and reduced to one accurate numeric measure. What velocity does not tell you is what the future holds. To quote every mutual fund prospectus ever written:
Past Performance is no Guarantee of Future Results
Understanding that velocity is accurate and dynamic is key to using it for iteration planning. Most other software project management methodologies pretend that the project is static in all aspects, that all variables are known and quantified. Agile acknowledges that a software project is a dynamic system, and provides simple evidence based tools to manage the dynamism inherent in building new software.
1 I use the term to encompass the variations of Agile methodologies that use story points and velocity.
2 I first heard this poetic phrase from Amy Kline, an awesome scrum master and friend.
3 Peter Jackson has written a great summary of why we use story points in The Case for Story Points .
