Scrum Tip: Granularity of Tasks

One interesting observation I have seen regarding Scrum at Rackspace Apps deals with task breakdowns. Breaking down a story from the product backlog is an important step to create the sprint backlog. Breaking things down into smaller pieces is going to increase estimation accuracy, as well as help the team understand all the different parts of a story.

But tasks don’t mean anything. The story is the functional piece of software the product owner requires, not any individual task. Tasks only serves as a compass for a team to track progress during a sprint. It is important to remember this and not become obsessed with task breakdowns.

With that said, how should teams go about breaking down a story into tasks? How granular should they go? Well, all teams are different, but I think I have found the general rule that works well

You are too granular when the team starts talking about the invalidity of tasks during a sprint.

Just this week, I had a team discussing how most of their task breakdown was not valid near the end of the sprint. It ended up that the story had about 3 tasks, not 6. When this starts happening to teams regularly, they need to take a step back and get less granular. Invalid tasks are a waste that should should be eliminated.

The general Scrum recommendation is 4-16 hours per task, and I definitely see anything under 4 as usually a waste. I have some teams where their breakdown is 2-3 days. It seems high, but in the end, if they are getting their stories done at a regular pace, it is fine with me.

But then again, do you even need to estimate tasks to begin with?

Defining outcomes not steps

One of the hardest tasks I have as a manager is empowering developers to make their own decisions. I like to think I do it pretty well, but I know way too much about a lot of applications. Sometimes I find myself defining how something should be done instead of just what should be done. For developers turned managers, I imagine you might feel the same way. What it really boils down to is understanding when to step in and when not to.

Stay out of application design meetings. Most managers that have been in an organization for a while have a good idea how something should be done. This doesn’t always mean they need to express it to their developers though. Staying out of these meetings allows leaders to step forward and drive the conversation. With a more senior person in the room, they may stay silent. Most good teams will leave a design meeting with an awesome plan and a list of questions for me anyways.

Steer developers away from pitfalls. In the above, I mentioned staying out of design meetings. It doesn’t mean you should be ignorant to the design of an application or feature. Get someone on the team to give you a summary, and recognize any concerns you have. You shouldn’t let developers do something that you know has a high chance of failing because you have experienced it. Plus, you are a domain expert, your guidance may shine light on something they didn’t think about. The important thing about giving feedback is it is after they have an idea of how to do something. Then, you are not defining the how but the what if.

Influence through teaching. Good code has certain traits. Easily testable. Decoupled. Inversion of control. Etc etc. Instead of defining how they apply to a given scenario, teach developers why they are important. It is one thing to explain inversion of control and dependency injection containers, it is another to define a class diagram for a given feature. Let them figure the latter out on their own.

Let them go out on a limb, every now and again. Management has a lot to do with trust. Once you trust a team, it is alright to let them go out on a limb every now and again and do something you aren’t 100% comfortable with. As I get further from day-to-day development, this happens more often. It is a good thing actually. I don’t know the specifics of certain technologies my teams are using anymore, but I have teams embracing them. Letting them do it is a huge step away from the how and into the what.

Managers that define the how prevent leaders from stepping up. For a team to feel ownership of an application, they must be empowered to make decisions about that application. This really starts by helping define the outcome and not the steps to get there.

Using Extension Methods to clean up Mocks (MoQ)

Mock’s can quickly become an ugly beast. They require lots of complex setup and verification. I have had good luck with using extension methods to simplify the complexity.

Assume we have the following code to implement our data layer on top of some ReST API.

public interface IWebClient
{
    string DownloadString(string url);
    string UploadValues(string method, string address, NameValueCollection data);
}
public class WebClientWrapper : IWebClient
{
    private WebClient client;
 
    public WebClientWrapper()
    {
        client = new WebClient();
    }
 
    public string DownloadString(string url)
    {
        return client.DownloadString(url);
    }
 
    public string UploadValues(string method, string address, NameValueCollection data)
    {
        return Encoding.UTF8.GetString(client.UploadValues(address, method, data));
    }
}

In the business/domain layer, we have a class that uses IWebClient to get some information from the API.

public class BusinessObject
{
    IWebClient client;
 
    public BusinessObject(IWebClient _client)
    {
        client = _client;
    }
    public XmlDocument FindCustomer(string search)
    {
        var result = client.DownloadString(
            string.Format("http://someApi/customers?search={0}",
                HttpUtility.UrlEncode(search))
            );
 
        return BuildXml(result);
    }
    public XmlDocument FindCustomer(char startsWith)
    {
        var result = client.DownloadString(
            string.Format("http://someApi/customers?startsWith={0}",
                HttpUtility.UrlEncode(startsWith.ToString()))
            );
 
        return BuildXml(result);
    }
    private XmlDocument BuildXml(string result)
    {
        var doc = new XmlDocument();
        doc.LoadXml(result);
        return doc;
    }
}

How do we go about testing this? My first attempt would look something like the following, relying heavily on MoQ.

[TestFixture]
public class BusinessObjectTests
{
    string resultXml = "<xml><customer></customer></xml>";
    Mock<IWebClient> client;
    BusinessObject bo;
 
    [SetUp]
    public void Setup()
    {
        client = new Mock<IWebClient>(MockBehavior.Strict);
        bo = new BusinessObject(client.Object);
    }
 
    [Test]
    public void Find_customer_using_search()
    {
        client.Setup(s => s.DownloadString("http://someApi/customers?search=searchVal"))
            .Returns(resultXml)
            .AtMostOnce();
 
        bo.FindCustomer("searchVal");
 
        client.VerifyAll();
    }
 
    [Test]
    public void Find_customer_using_filter()
    {
        client.Setup(s => s.DownloadString("http://someApi/customers?startsWith=a"))
            .Returns(resultXml)
            .AtMostOnce();
 
        bo.FindCustomer('a');
 
        client.VerifyAll();
    }
}

But I don’t like this. It is very verbose, and doesn’t resuse functionality very well. Morever, in real world examples, there would probably be many more functions with very similar setup and verification steps. How can we refactor this to make it better?

public static class ClientMockExtensions
{
    public static void VerifyGetContainedParmeter(this Mock<IWebClient> client, string name, string value)
    {
        client.Verify(c => c.DownloadString(
          It.Is<string>(s => s.IndexOf(name + "=" + value) > s.IndexOf("?"))));
    }
}
[TestFixture]
public class BusinessObjectTests
{
    string resultXml = "<xml><customer></customer></xml>";
    Mock<IWebClient> client;
    BusinessObject bo;
 
    [SetUp]
    public void Setup()
    {
        client = new Mock<IWebClient>(MockBehavior.Strict);
        bo = new BusinessObject(client.Object);
 
        client.Setup(s => s.DownloadString(
            It.Is<string>(str => str.StartsWith("http://someApi/customers"))))
            .Returns(resultXml)
            .AtMostOnce();
    }
 
    [Test]
    public void Find_customer_using_search()
    {
        bo.FindCustomer("searchVal");
 
        client.VerifyGetContainedParmeter("search", "searchVal");
        client.VerifyAll();
    }
 
    [Test]
    public void Find_customer_using_filter()
    {
        bo.FindCustomer('a');
 
        client.VerifyGetContainedParmeter("startsWith", "a");
        client.VerifyAll();
    }

In the example, I use extension methods to reuse verification steps, which also makes the tests much cleaner. Too many times developers stay away from complex verification steps in favor of complex setups. I think it is cleaner to do a more generic setup, and then use verify to get down to the specifics of what was done.