Pivotal Labs

Main menu

Skip to primary content
Skip to secondary content
  • About
  • Case Studies
  • Team
    • Executives
    • Locations
      • San Francisco (HQ)
      • Boston
      • Boulder
      • Denver
      • London
      • Los Angeles
      • New York
  • Community
    • Blogs
    • Tech Talks
    • Events
  • Careers
    • Lifestyle
    • Principles & Practices
    • Benefits
    • FAQ
    • Apply
  • Contact
    • Press Room
    • Press Releases
    • In The News
    • Press Kit
  • All
  • Labs
  • Standup
  • Tracker
Will Read

"Point" Me in the Right Direction

Will Read
Friday, January 29, 2010

“Bugs and Chores don’t get points, unless you want to give them points, then they get points, but don’t point your bugs or chores.” Whaaaa?

In Tracker, you can (and should) always point your features. But you have to turn on this setting buried deep in the menus and next to a disclaimer if you want to point your bugs and chores.

If you’re looking for that check box, you’re probably a developer, or someone who is responsible for justifying the work of the developers. The business side has no interest in it what-so-ever. “Why?” That’s the right question.

The two of you (business and development) are trying to answer two different questions. Business wants to know how long it’ll be before they can release a product. As such, they have a set of features that must get in to a release. Doing anything aside from features, like chores and bugs, is paying down debt, and thus should be subtractive from velocity.

As a developer, you are less interested in when the business guys have decided to put a stamp on it and “go live”, you’ll still be developing just as much the next day anyway. You want to know if you’re getting better, faster, stronger as a team (we have the technology btw, just ask for Pivotal Labs!). Typically you might do an iteration or two with a lot of features, build up a solid velocity, push it to staging, and wait for the bugs to roll in. Now your next iteration is almost all bugs and your team is killing it, but Tracker says “0 points” and it kills you. “The guys (and gals) are doing all this work, and this will wreck their velocity”, you think to yourself.

Yes. But! Only their points completed for that iteration will be zero. Their velocity will accurately reflect their ability to deliver features over time. To better illustrate my point consider the following team:

  • They get started on a new feature set, first iteration: 10 points, 1 bug, 4 chores
  • Second iteration, the groundwork is laid out now: 15 points, 4 bugs, and 1 chore
  • By the third iteration, they’re in the groove: 20 points, 1 bug, 1 chore
  • They push to staging, get a bug list back and get to mashing in the fourth iteration: 2 points, 18 bugs, 0 chores
  • Release!

If you fiddle with the number of iterations Tracker uses to compute the velocity, you see numbers like this at the end of the final iteration:

  • 1 iteration: velocity = 2
  • 2 iterations: velocity = 11
  • 3 iterations: velocity = 12
  • 4 iterations: velocity = 11

In this case, 11, from the average of the past 4 iterations, is the interesting number to most. It includes the bug part and the ramp up part. If your releases tend to be 3 iterations, you might consider making velocity an average of 3 iterations. If your releases are 15 iterations long, you might want to consider breaking them down into smaller releases.

By matching the number of iterations used to compute velocity to the length of your typical release, you should arrive at a very stable velocity for your team. This not only helps the business side predict when you can release, it also gives you something to point at when the financial guy wonders if the whole engineering team took the week off when you had a 0 velocity. And if he really grills you, you can always pop open Tracker and show the list of bugs and chores that were found by the other outstanding employees and how they’ve since been corrected, making the product better than it has ever been before.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Joseph Palermo

Careful when doing a :include with a :has_one :through association

Joseph Palermo
Monday, January 12, 2009

We had an odd bug last week where we ended up with different results after we had eager loaded an association vs loaded directly.

There are apparently two issues with :has_one :through, one of which also applies to :has_many :through.

So given:

class Person
  has_many :friendships
  has_one :best_friend, :through => :friendships, :conditions => "friendships.best = 1"
end

If you do a Person.find(:all, :include => :best_friend), the best_friend that gets preloaded is not necessarily one that has a “friendship.best = 1″

This is due to a bug in the association preloading code that doesn’t pass down the finder options, so any :conditions or :order are completely ignored. This problem is easy to fix, just a one line change, but it then exposes another problem.

This problem applies to both :has_many :through and :has_one :through associations. The problem is that the :through association is loaded separately from the :has_one or :has_many association. So it first loads :friendships, and then when it tries to load :best_friend, it doesn’t have the table it needs for the :conditions and explodes.

Our current work around is basically putting the conditions on the :through association, although sometimes you need to create a new association just for that which is certainly not idea, especially if you plan on accessing the :through model after it has been loaded.

The way to fix it in Rails is unfortunately a rewrite of how the :through associations are eager loaded.

You can see the lighthouse ticket here

There is also a couple of messages on the Rails Core group

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
David Stevenson

Pivots patch rails: named_scope with the :joins can cause table aliasing issues

David Stevenson
Monday, September 29, 2008

In order to accomplish some advanced search functionality, we’ve added a lot of named_scopes to our User model. This seems like a good idea, and well within the intended use for named_scopes. Unfortunately, we ran into issues with our :joins. We have a separate User and Profile model, but our advanced search scopes often needed both to make decisions. So we had some scopes that look like this:

class User
  named_scope :verified {
    :conditions => {:email_verified => true}
  }

  named_scope :answered_questions {
    :join => "INNER JOIN profiles ON profiles.user_id = users.id " +
                 "INNER JOIN answers ON answers.profile_id = profiles.id"
  }

  named_scope :with_name { lambda { |name|
    :join => "INNER JOIN profiles ON profiles.user_id = users.id",
    :conditions => ["profiles.name LIKE ?", "%#{name}%"]
  } }
end

Using these named_scopes, we wanted to dynamically construct a finder that would return the results the user was interested, such as: User.verified or User.answered_questions or even User.verified.answered_questions.with_name('Joseph'). The last scope caused issues, unfortunately, with table aliasing. The query ended up joining in the profiles table twice, in exactly the same way without renaming the table, so mysql rejects the query.

The easiest solution to this problem was to use only the hash form for :join clauses, such as :join => :profile. Rails correctly merges multiple consecutive join scopes that use hashes. If you need to use string joins (such as a LEFT JOIN rather than an INNER JOIN) or put a condition directly on your join, then merging goes out the window and the hashed form is immediately converted to a string and all consecutive joins are “merged” by appending them together.

We started by manually aliasing our scopes, but in some cases we were concerned about the amount of duplicate data this was causing in our queries.

We thought about creating a dependency framework for named_scopes, such that you could have a single :profile scope that other scopes were dependent on and it would only ever get added once. This seemed really difficult because of the way the with_scopes are constructed by named_scopes, there was no good place to keep track of these dependencies, and it would still cause problems if you had a manual with_scope, or :join in your find.

Finally we decided that rails fundamentally lacked the capability to deal with duplicate joins, and that we should solve this problem. It seemed a good solution was to allow :join options to take an array of strings as follows:

  named_scope :answered_questions {
    :join => ["INNER JOIN profiles ON profiles.user_id = users.id",
                 "INNER JOIN answers ON answers.profile_id = profiles.id"]
  }

Now calling User.answered_questions.with_name('Joseph') will create three values in a :join array, two of which are identical and will be uniq’d out. The downside to this approach is that each value in the :join array has to be string identical, or it will not be properly uniq’d.

So if you are mixing hash style :profile joins with string joins of the same table you need to be careful you match the rails generated syntax. We mostly use string style joins to avoid this issue.

Here’s the ticket the we filed and patched:
1077-chaining-scopes-with-duplicate-joins-causes-alias-problem

It has been commited and will roll out with rails 2.2. Since then we have filed two more issues related to :join and :include:

  • 1078-using-include-assoc-and-join-assoc-leads-to-alias-issue
  • 1104-references_eager_loaded_tables-should-search-tables-in-join-clauses

We hope to patch these two as well!

Joseph & David

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Topics

  • agile (780)
  • rails (113)
  • testing (88)
  • ruby (83)
  • ruby on rails (70)
  • jobs (62)
  • javascript (55)
  • techtalk (44)
  • rspec (38)
  • ironblogger (32)
  • productivity (30)
  • activerecord (29)
  • gogaruco (29)
  • git (28)
  • nyc (27)
  • rubymine (26)
  • bloggerdome (23)
  • mobile (22)
  • process (21)
  • pivotal tracker (20)
  • cucumber (20)
  • jasmine (19)
  • design (18)
  • ios (18)
  • webos (17)
  • objective-c (17)
  • android (16)
  • palm (16)
  • "soft" ware (16)
  • fun (15)
  • tracker ecosystem (15)
  • ci (15)
  • cedar (15)
  • rails3 (14)
  • performance (14)
  • bdd (14)
  • gem (13)
  • css (13)
  • tdd (13)
  • selenium (12)
  • goruco (12)
  • bundler (12)
  • meetup (11)
  • railsconf (11)
  • nyc-standup (11)
  • capybara (10)
  • mac (10)
  • mojo (10)
  • chef (10)
  • api (10)
Subscribe to bug Feed
  • About
  • Case Studies
  • Team
  • Community
  • Careers
  • Contact
  • Labs
  • Events

Contact Us

contact@pivotallabs.com
+1 415-77-PIVOT
TwitterLinkedInFacebook

Pivotal Tracker

Tracker is the award-winning agile project management tool that enables real-time collaboration around a shared, prioritized backlog.
Visit pivotaltracker.com >