Thursday, March 29, 2012

Better software development estimates


Is it possible to estimate software tasks better?  In certain circumstances, my experience tells me yes!  It's not just a wish (/me waves to commenter on last post).

First, to establish what kind of estimates I'm talking about.  It's not possible to estimate anything past two months, in my experience.  When I was working at Microsoft and heard lots of estimates from other teams, I realized that "This software product will take us two years" really meant "We have no idea and we will never finish a product that recognizably matches our plan".  A one year estimate turn into a somewhat recognizable outcome in two or three years.  Even a six month estimate, while it might turn into a year-long project fairly reliably, ends up finishing quite different tasks than the planned tasks which originally led to the six month estimate.

Other things that make a difference in estimation accuracy:
 * What language is being used?  Snags can be a bigger time dilator with a compiled or lower-level language like C, whereas hitting a snag in Python might not throw out the estimate that much.
 * Is something new being integrated? Any time a task involves compiling and linking a new library, or adding a new Ruby gem, I know the estimate is weaker.
 * How routine is it? Adding a new page to a Ruby on Rails project can be pretty damn predictable.
 * How many people are involved?  Estimating a one-person task is way more accurate than estimating a team project.  Even a one-person task that has an issue that requires another person's answer is less accurate than the task that can be done by one person independently.
 * How many other estimated tasks are dependencies?  If you have a chain of tasks to estimate, a change in one task can throw out the others.

And then there's bias.  Have you ever noticed that some developers always estimate high and some always estimate low?  It's intriguing, because even though they're consistently wrong, they are consistently wrong in the same direction.  That means they are actually giving management good information, if management knows their biases.  I once managed one optimist and one pessimist in the same team for over two years.  The optimist always estimated about 1/3 of his actual time required. The pessimist always estimated about three times the actual time required.  I would assign what looked like three months of work to the pessimist, and what looked like a week and a half of work to the optimist, and they would finish around the same time.

One of the things I really do love about Agile (and Pivotal Tracker reifies this) is how it understands the above points.
 * Task length? Agile encourages developers to break work down into smaller tasks (no three-week tasks in any agile process I've ever seen)
 * How many people are involved?  Agile encourages issues to be resolved before the estimate is even made, and it is designed for single-person tasks.
 *  How many unfinished dependencies are there?  Agile encourages planning with a shorter horizon, so the chain of dependencies is usually reduced.
 * Consistent bias?  Agile tracks velocity, not accuracy, so a consistent bias is simply a constant part of a consistent velocity.

With all that, one of the main things that intrigues me, and this is what I'm unpacking from my previous post, is whether better feedback would help developer estimates get even better than Agile already makes them.  Agile does not measure time spent so it doesn't give developers feedback that would allow them to either fix a consistent overall bias, or to start to recognize tasks that need to be estimated a little higher.

Sunday, March 25, 2012

Scrum thinks people are stupid

One thing I both love and hate about the hardcore agile process, particularly the Scrum process, is that it tends to work around participants' biases, weaknesses, and lack of trust, rather than try to fix them. Scrum may not even leave room for improvements in trust or reliability. Some examples:

Developers' estimation biases are worked around, not fixed
Because developers have biases in estimating tasks (biases that are consistent over time and on average), scrum "velocity" measures estimates against results.  It doesn't attempt to fix estimates, e.g. by showing a developer the difference between their estimates and time spent.  In fact, velocity doesn't measure time spent at all, and lumps all developers in a team, over-estimators and under-estimators together, in one velocity measurement.

This is probably for the best -- it's one simple measure that's remarkably consistent.  Still, I wonder if it wouldn't be more useful in the long run to learn to estimate better.  I've never seen a really good estimation feedback loop in the software development context, but wouldn't it be neat to try?

Product owners' changes are either completely allowed or disallowed
Traditionally engineering teams have to train product owners not to change the product plans all the time.  This involves frequent team arguments about product plan changes.  Instead, scrum tries to carve out one small space where product changes are forbidden, and allow all other changes without argument.  In the current interval, the product owner cannot make any changes or the current plans are all tossed out and the estimation process is restarted, a consequence severe enough to effectively forbid any small changes.

This rule does keep product owners off the developers' backs.  If the product owner is thinking of a change to this week's plans, the consequences of an "abnormal sprint termination" probably stop them.  If the product owner is thinking of a change to next week's plans, the upcoming sprint planning meeting is where they'll discuss it.  Either way, the product owner does not walk up to a developer and say "Hey!  I've got a great idea!"

If keeping the product owner off the developer's back sounds like a really good idea to you, well you probably haven't worked with trusted, experienced product owners.  And if the team has processes that reify the distrust, then there's less chance to build trust.

Demos help people who can't analyse abstract plans
Weekly demos are a course correction mechanism. In order for anything to be marked done, it must be demoed.  And when a feature is demoed, the product owner can see the practical consequences better than they could when the feature was designed.  Now the product owner is able to immediately add things to the backlog, which might get done in the next iteration, and this is good.  Iterative design for the win.

The practical consequence of this appears to be less specification and planning work, which is good (avoid overplanning), but taken to the point where the product owners do not feel any particular pressure to understand and analyze the design.  Instead of sitting in front of the wireframes and thinking it through -- "What happens if I press this if it were implemented?  If this were a real system and the item had been deleted, what would the user need to see? " It's a difficult what-if skill and takes practice.   It doesn't make design any less iterative!  Instead, it moves the iterations into the design phase rather than the costly implementation phase.

Frequent demos, and the scrum rules which allow for any changes in the backlog, seem to remove some of the need to develop abstract design skills.  That makes me a little sad.  Still, frequent demos and iterations are a tool I'd use in any software development process.

Optimizing considered harmful
In hardcore scrum, developers are practically forbidden from doing any changes now that would make future work easier.  It's discouraged, and the way the system tracks tasks makes it unrewarding to do.

Let's say that today my task is to create a feature for users to delete items. There's also a story in the backlog or icebox for undeleting items (e.g. finding them in a trash folder and returning them).  Well, the way success is structured in scrum, I estimate the time to delete items at the beginning of the period where I do that work, and it makes everybody happier if I figure out how to delete items without much work, and we make more features fit in this period.  It doesn't help me now to estimate high in order to prepare for the 'undelete' feature.  It doesn't help me in the future either -- when we get to the scrum meeting where we estimate the  'undelete' feature, it might not even be me doing the feature.  (In theory, developers are supposed to be interchangeable in agile/scrum).  Even if it is me,  it's no big deal to have to do the undelete by rewriting the way delete worked -- I just build that into my estimates for this period.

There's no overall project schedule view that would have showed the value for doing these two features together and doing delete right the first time.  There are other ways where optimizing is actively discouraged:

  • Literally, optimizing speed or resource use is discouraged.  Functional stories only say that the feature has to work.  Other stories in the future might or might not say that the feature has to work in 2 seconds.  Security might also be an afterthought!
  • Optimizing by expertise is discouraged.  Everybody in the team is supposed to be interchangeable.  If all of this week's features are GUI features, then everybody does GUI work. If all of the next week's features are security features, then everybody does security work. 
  • Optimizing the sequence of work by engineering constraints is discouraged.  If it would be faster to do feature A after the more general feature B is completed, too bad.  If there's a pileup of work with dependencies, and it's slipping to the end of the backlog where the dependencies will start to slow down each task, too bad.  Only the priority sorting of the product owner is valid.
I've seen passionate arguments for "You Aren't Gonna Need It" (YAGNI), and they're right.  Engineers often optimize prematurely.  Engineers often predict what they think the user will need and can be wrong.   But none of the passionate arguments for YAGNI think that it can be used without a sense of balance, right?  So when scrum methodology encourages developers to always put off optional work, scrum puts its thumb on the balance.  It short-circuits the discussions of complex tradeoffs and simply says do it later. 

Summary
What's common among all these traits is an attitude in scrum not only that people are fallible, but they're routinely wrong, and that they can't be trusted to work together on complex issues for the greater good. That means that it works best in environments where that attitude is more true -- e.g. a contract development team, comprised of decent engineers but not particularly specialized, who don't know much about the end use and maybe don't care too much, working with product owners who aren't experienced in software design, are way too busy to write specs and discuss complex tradeoffs, and are always tempted to change things they shouldn't.  

Agile should be done differently when the engineers are specialized, care about what they're doing and what it will be used for, work closely with the product owners in the same business unit, and the product owners are smart and can be trusted to learn good software development practices.  Just how it should be done differently is an open question to me. There are agile process variants that take different attitudes (e.g. those that encourage planning a whole release) and for the kind of team I am currently working in and enjoy working in, I'm interested in those variants.

Thursday, March 01, 2012

One more thing about using Sorcery in a Rails project

One more thing about using Sorcery in a Rails project. I did mention that to make unit tests work, I had to stub out "current_user" in every single controller:
  Given /^I'm a doctor$/ do
    @user = User.create!(:email => "testuser@example.com", :password => "password")
    DoctorsController.any_instance.stub(:current_user).and_return(@user)
    VisitsController.any_instance.stub(:current_user).and_return(@user)
    PatientsController.any_instance.stub(:current_user).and_return(@user)
  end

Even in Cucumber scenarios that do not use one of these steps that stub out current_user, I found that I had to explicitly unstub the method. I did not investigate why this is the case; I'm guessing that Cucumber would have to reload the whole environment between running each scenario, which would take too long. Perhaps there's a better way for Sorcery to provide "current user" functionality without patching each controller, or perhaps there's a better way for me to test mocking logged in users. In any case, this works, explicitly adding a step to make sure that the mocked-up logged-in user is no longer stubbed in:
  Given /^I am not logged in$/ do
    begin
      VisitsController.any_instance.unstub(:current_user)
    rescue RSpec::Mocks::MockExpectationError
    end
    begin
      DoctorsController.any_instance.unstub(:current_user)
    rescue RSpec::Mocks::MockExpectationError
    end
    // etc...
  end

Blog Archive

Creative Commons License
This work is licensed under a Creative Commons Attribution 3.0 Unported License.