Thursday, February 28, 2008
Return on INVESTment

At our last pre-planning meeting, we made a point of putting all the user stories into INVEST format, and I was pleased that there was a general consensus that this worked well.

I think this took quite a while, partially because we were all getting used to evaluating the statement of the stories critically, but I think this was worth it. We had product, IA, and engineering folks suggesting wordings for stories, and at least some of our stories came in in a canonical format:

"As <who>, I want <feature>, so that <value>."

Having the full INVEST filter did help us with a few things:

  • Independent: We did not have a lot of stories that were dependent, but we did end up with a very few that were cross-team. Since this was just a handful of the stories, we figured it would be ok to leave the story as is (since we couldn't quickly come up with a way to rewrite it) and track the dependencies through our scrum-of-scrums.
  • Negotiable: I think we generally nailed this one. We did not look at any IA wireframes or Design mockups during pre-planning, and were able to identify the high-level goals here. This has already become useful in planning, where my team has suggested a new / faster approach to at least one story which was not as originally conceived, but our Product Owner agreed that we still hit the abstract requirement.
  • Valuable: There were a few stories that were original cast as abstract technical requirements (e.g. make the middleware support foo), but we refactored them in a way that expressed value to the end user (which, incidentally, will make it more obvious how to test).
  • Estimable: We've already agreed not to do a small handful of stories because we realized there were too many unknowns; for one of these, there was a middleware task that depended on IA we hadn't seen and on data we didn't have in the DB yet. We actually spent a lot of time trying to talk about how to tackle this before we realized we couldn't estimate it. Since it was not critical for implementation this sprint, we agreed with the product owner to turn this into a story where we would do a feasibility study and rough design by the end of the sprint instead, which was something we could commit to. (The value here is to the product owner, who will then be able to write an Estimable story about the feature!)
  • Small: We did a good job here of refactoring large stories into multiple pieces and then figuring out how to get Value out of each piece. We only had a handful of medium to large stories.
  • Testable: We're asking each team during planning to make sure they hash out "how to demo" for the feature with the Product Owner, so we should know if we've gotten there by the end of sprint planning.

With the up-front work on the stories we did, our team has found it easier to negotiate a specific solution and in some cases to actually plan without the product owner, which is actually convenient (he's doing multiple duty so he's having to bounce back and forth between multiple sprint planning sessions!).

Sunday, February 24, 2008
INVESTing in user stories

In my previous post I made reference to the INVEST acronym for evaluating user stories:

  • (I)ndependent
  • (N)egotiable
  • (V)aluable
  • (E)stimable
  • (S)mall
  • (T)estable

I'd like to spend a little bit of time talking about each of these characteristics, and motivating why each is important through some anecdotes about what happens when each characteristic is not attained.

Independent: The idea here is that stories are free of dependencies from one another. (A good test would be to ask if you could implement them in any order, rather than just in the priority order generated by the Product Owner). We want this for multiple reasons: first, on a multi-team project, it allows stories to be load-balanced across teams more easily, since in theory any one story could get moved around, rather than having to move an entire batch of them. Secondly, and on a related note, it means that when sprint teams sign up for work, they can draw the commit line anywhere. Thirdly, it helps avoid cross-team dependencies (although a scrum-of-scrums and specific attention to dependent situations can handle it, it is still much easier to handle all your dependencies intra-team).

For a specific example, consider if you have teams that are layered horizontally by functional layer (e.g. a database team, and a webapp team). If you have two stories which are the "halves" of building some functionality, and assign one to each team, you take on the following risks:

  • teams must coordinate closely around this feature (extra communication/tracking overhead)
  • if one team finishes but the other doesn't, you may have extra "clean up" work at the end of the sprint to make the software still work, and you may have had a team do work that ultimately had no product impact that sprint (e.g. middleware can handle some new data and display it, but data didn't actually apppear in the DB, so no actual behavioral difference)

We'll see that some of the other INVEST characteristics actually help track this down as well.

Negotiable. To me, this means that the requirements given are as abstract as possible, so that the actual details of what is going to get built are determined by the team and Product Owner during sprint planning and modified as needed over the course of the sprint. For example, "user can change timezone with one click" vs. "user timezone is shown in a 100x25 dropdown box in the header". (Of course, if the latter language actually represented a contractual obligation, then that might be as abstract as you can make it, but you get the idea...).

This is primarily important for two reasons: to allow the team to exercise maximal creativity and to allow the team to adjust for the unpredictable events that will happen mid-sprint. In the former case, the dropdown box might be tacked on to the story as a starting point or suggestion, but the team may come up with an approach that is easier to implement or which actually satisfies the Product Owner more. In the latter case, it leaves some room to negotiate if the team has under-estimated and is behind mid-sprint, and still be able to "finish" the user story.

The danger of not being able to negotiate the functionality is really twofold: first, not completing the full set of work in a sprint eventually crushes team morale; not being able to complete an assignment is a big downer, especially when you have worked hard and because, due to the inherent complexity of software development, things just took longer than you thought. Eventually you get to the point where your team will just shrug, and say, oh well, I guess we won't finish that stuff. I have seen this happen first-hand, and it is demotivating.

Secondly, there is danger to the product roadmap. By not having requirements couched abstractly, you run the risk of slipping features or having unfinished, "carryover" work, which adds up and pushes the product roadmap back. By giving the team the freedom to brainstorm a way to satisfy the requirement in less time, you are not letting them off the hook -- you are using the deadline of the end of the sprint as pressure to encourage the team to develop the functionality as efficiently as possible. The resulting functionality may not be as complex or deep as originally hoped for or conceived, but if the spirit of the story is met, then you have some aspect of it ready to go out as shippable product.

Valuable. Each user story should provide value somehow. The original articles I read about this amended this to "provide value to the end user / customer." While I think noting the value explicitly can help product owners check off that the story will help their Key Performance Indicators (KPI), I think the more important thing this brings is that the team is aware of why this story is important. This can help constrain the solution space for Negotiation in an important way. Finally, this is just a cross-check for Indepencence; if this story is completed, and no other, does it generate value, or do we also need another story to be finished in order to get the value?

On a side note, the phrase "to the end user" is an interesting one. We keep a "tech backlog" of infrastructure/refactoring ideas around, and prior to each sprint, we evaluate which ones are critical to current development, and ask for those to be prioritized in with the current product backlog. Generally, we have been very judicious about this, maybe in a nod to providing direct benefit to an end user -- we usually wait until an infrastructure adjustment is needed or desirable for implementing new functionality before taking it on. This suggests that other infrastructure work get carried out during lab days, to scratch those developers' itches. I'm still up in the air over how strict we should be about "to the end user", but I do lean towards requiring that most of the time.

Estimable. If you can't put an estimate on it, either the requirements are too vague (see Testable), or the technical solution is unknown (e.g. "I don't even know if this is feasible!"). In the latter case, a suggested tactic would be to alter the user story into a feasibility study / research effort for this sprint, which could be easily timeboxed; the original story could then be revisited in a later sprint, when there will be less cloudiness around it, and it can be properly estimated.

Where this can bite you is in signing up for work you don't know you can finish. This sets up for an expectation mismatch with your Product Owner, and also prevents you from making efficient use of your time; you run the risk of attempting to estimate it, and either grossly underestimating it, putting all the lower-priority sprint backlog at risk, of grossly overestimating it and not signing up for enough work, or of padding the estimate to try to account for the risk and then spending more time on it than the feature is really worth.

Small. We want things that will take no more than a full sprint to do, and hopefully less. While the full scope of a feature vision may require more than one sprint, you want to refactor it somehow so that you get something out of even the very first sprint (see Valuable); then you can be sure that you reap some result from your effort in shippable product, as opposed to doing some partial work, and then having the remaining work deprioritized for several months before you can extract value.

Finally, a purely pragmatic reason for keeping the stories small is to reduce the risk of gross under-estimation. I've personally been way off on a single big story (as everyone is from time to time), and when it's been a big one, I've simultaneously trashed my personal life for a month of overtime and sleep deprivation, while requiring a bunch of load-balancing and rejuggling across multiple sprint teams due to the fact that the rest of the sprint backlog I signed up for was now at risk. So don't do that -- take smaller bites, just like Mom used to say.

Testable. This primarily serves three purposes: ensuring that Product Owner expectations are in-tune with what the team thinks it is delivering (see also Negotiable), giving the team a way to know when it can stop working on the story, and giving the testers a starting point for writing their test cases. Beware of non-quantifiable adjectives like "good" or "acceptable" in your user story descriptions. For a while, when we were doing sprint planning on spreadsheets, we had a "How to Demo" column--this worked great while we did it, but we never had enough discipline to follow through here and continue doing it. This is one of the things I'm hoping to bring back during my Scrum revival next sprint.

There's nothing worse than showing up to a sprint review and having your Product Owner say, "but that's not at all what I asked for, or that's not what I meant." Big morale crusher for everyone involved (team and stakeholders).

Finally, this gives the Scrum master a hook to save the team from perfectionism or unbounded creativity. For example, if you've gotten the feature to the point where it satisfies the acceptance tests and has been built up to your standards of quality, just stop working on it, and start working on the next user story. This is your old friend, the Pareto principle, at work -- would you rather spend a day mining the long tail of a functionally complete feature, or would you rather spend it getting the up-front meat of a new feature? The other place this helps is when you finish a feature, and you and the Product Owner are looking at it, and you now see something totally awesome that is now possible -- stop, ship the feature you have, and queue the good idea up as a user story for the next sprint so it can be properly prioritized with everything else. Again, this is about efficient use of the time in the sprint.

I'm anticipating having this be a little painful as we work through this together with the product team the first time; we've all signed off on this in principle, but we've never actually attempted to make each story adhere to INVEST. I suspect, like all similar things, it will be a bit robotic for the first few stories, but we'll quickly get the hang of it and be able to move on during pre-planning. I'll let you know how it goes.

Saturday, February 23, 2008
Back to Basics

I've been re-reading "Agile Software Development with Scrum" to see if it has any insight for some of our current product struggles. Fortunately, I think it does, and I've been getting fired up for a great Scrum revival. [Revival tent picture courtesy of PinkMoose on Flickr, used under a Creative Commons Attribution license.] I'm going to be reprising my role as Scrum Master for my team next sprint as well, so hopefully I'll be able to transmit some of these values.

Looking forward to getting back to some Scrum fundamentals, including:

  • sprint goal: let's set an overarching sprint goal we can be working towards
  • INVEST user stories: in particular, the "N" -- negotiable -- means we have maximum flexibility to react with agility during the sprint
  • commitment: the team signs up for a set of work, and commits to completing it by the end of the sprint. No carryover. If burndown shows we are behind, we need to collaborate with the Product Owner to revise functionality / approach so that we have an achievable set of work. Also, we need to have the team take responsibility for completing the work -- no more reporting blockers and then giving up without trying something else.
  • product increment: end of the sprint, we have a potentially shippable product. No half-baked / half-finished pages on the site.

I'm pretty excited for the upcoming sprint. We've got a lot of talented folks, we just need to really get them motivated and self-organized, and then awesome stuff will erupt.

Wednesday, February 13, 2008
REST-based service design, v2

I want to revisit the basic "favorite food" service from last post, in light of some further discussion I've had with colleagues.

  • GET: returns a list of the user's favorite foods, in some representation. Returns 404 NOT FOUND if the user has never specified favorites.
  • PUT: sets the list of the user's favorite foods to be the value sent, creating it if necessary.
  • DELETE: removes the user's favorite list. This is different than doing a PUT with an empty list.
  • POST: returns 405 METHOD NOT ALLOWED.
  • GET: returns 200 OK if the food is a favorite of the user. Returns 404 NOT FOUND if the food is not a favorite of the user.
  • PUT: makes the food one of the user's favorites
  • DELETE: makes the food *not* a favorite
  • POST: returns 405 METHOD NOT ALLOWED

So, PUT can create a resource if it doesn't exist, and DELETE of a URI means the next GET of it (in the absence of any other operations) will be a 404 NOT FOUND.

One note is that as a client of this API, I want and can make use of the most atomic operation available. For example, to make "spaghetti" a favorite food, I could either:

  1. GET http://host/path/{userid}/favorites
  2. PUT http://host/path/{userid}/favorites (new list with spaghetti added in)

or I could just:

  1. PUT http://host/path/{userid}/favorites/spaghetti

Note that in the first case, I might have an atomicity issue in the presence of concurrent access, so I might need to build in some sort of optimistic locking protocol, where the representation of the favorites list has a version number on it that is checked by the PUT operation. However, if I just use the second method, I don't have this issue, because the server handles all my concurrency/transactional stuff for me.

Tuesday, February 12, 2008
REST-based service design

Just wanted to walk through a quick REST-style API design exercise. Let's suppose I want a service that lets folks maintain a list of favorite foods. Just as a quick strawman design, let's walk through some URIs and supported operations:

GET on this URI returns a list of the current user's favorites. List might be empty. PUT on this URI overwrites an existing list of favorites. DELETE on this URI sets the list of favorites to the empty list.
GET on this URI returns something (really, we just want a 200 status code) if the food is a favorite, or returns 404 if it is not. DELETE on this URI un-favorites the food for the user. PUT on this URI makes the food a favorite.

So, questions for the audience:

  1. Does this look reasonable?
  2. Does the use of PUT look right, or would you use POST here?
  3. How about the use of DELETE to set the full list to the empty list? Does it make sense to DELETE a URI and then be able to GET it and have something be there?