• The Failure of Infinite Capacity - A Product Management Trap

    One of the main principals of agile software development according to the Agile Manifesto is that teams will work to continuously deliver valuable software. Further, they will do this by working on and delivering the features and capabilities that provide the greatest value first. Obviously, any understanding of the value a particular feature delivers is a hypothesis based on the teams current understanding of the Customer’s1 needs. By learning as they release new software into production they can evolve their understanding of the Customer’s needs. This fact allows teams to continue to make software more valuable without necessarily trailing off in their ability to do so.

    However, a common desire from stakeholders and product managers is to get more done faster. This would be fine and dandy except that it is often not accompanied by a corresponding increase in feedback and customer based product development. This means if the team keeps adding new things to work on without new learning and does so in order of value then the last item the add will be the least valuable.

    The result of this is that the longer the list of things a team works on before going back to customers for feedback the lower the average value of each feature. Even if we assume the the minimum value of a feature is greater than zero(which I think is unlikely) the average value of a feature will approach the minimum possible. Additionally, since increases in capacity are inevitably associated with hiring more staff, costs increase. Even if we naively assume that productivity will increase linearly this just means that costs increase at the same rate2. Therefore, the more capacity the organization has the greater chance they are doing work that is less valuable than the cost of doing it.

    Cost of Feature Development vs Value

    Rather than maximize capacity for feature development organizations should strive to balance capacity for development with capacity for feedback and product development. Further, they should recognize that the answer for how to grow the product is not always more software development.

    1. In this context Customer stands in for what ever number of people or organizations that your software solves problems or provides value for. 

    2. Often as has been understood in software development for years costs actually rise faster than productivity because each additional staff member increases overhead and thus provides less value than the previous staff member. This only serves to make the situation worse. 

  • Using Resharper to Refactor Static Methods or Properties Into Instance Methods

    This is an example of how you can combine a bunch of smaller automated refactorings to achieve an effect for which there is no automated refactoring in a safe and non-manual way. Note: All short cut keys given are with Resharper configured with the Visual Studio hotkey choice

    If you see the following sort of code:

    public static class A
    {
    	public static string Method1(string p)
    	{
    		return p;
    	}
    
    	public static string Property1
    	{
    		get
    		{
    			return "abc";
    		}
    	}
    }

    First, remove the static keyword off the class leaving you with the following.

    public class A
    {
    	public static string Method1(string p)
    	{
    		return p;
    	}
    
    	public static string Property1
    	{
    		get
    		{
    			return "abc";
    		}
    	}
    }

    Rebuild, there should be no other changes required at this point for a successful build. Next, to make the method non-static we are going to add a local variable to that method that is an instance of class A as follows:

    public class A
    {
    	public static string Method1(string p)
    	{
    		var self = new A();
    		return p;
    	}
    
    	public static string Property1
    	{
    		get
    		{
    			return "abc";
    		}
    	}
    }

    Next, we will promote self to a parameter using Resharper. To do this highlight the word self. Now, either right click on the highlighted word and go to Refactor -> Introduce Parameter or use the keyboard shortcut CTRL R, P. You should be in the introduce parameter popup. Accept all the defaults and hit next until completed.

    This should result in code that looks like the following:

    public class A
    {
    	public static string Method1(string p, A self)
    	{
    		return p;
    	}
    
    	public static string Property1
    	{
    		get
    		{
    			return "abc";
    		}
    	}
    }

    And everywhere that method is called will now look like A.Method1(“a string”, new A());

    Now right click on Method1 and choose Refactor -> Make Method Non-Static. You should get a popup. Make sure the parameter of type A is highlighted in the popup and hit next.

    This will result in code that looks like the following:

    public class A
    {
    	public string Method1(string p)
    	{
    		return p;
    	}
    
    	public static string Property1
    	{
    		get
    		{
    			return "abc";
    		}
    	}
    }

    And all callers should look like the following:

    new A().Method1("some text");

    Now, for the property we have to add 2 steps: First, highlight the name of the property, right click, and choose Refactor -> Convert Property to Method. You should get a popup. Accept all the defaults and hit next until done. Now you should have code that looks like the following:

    public class A
    {
    	public string Method1(string p)
    	{
    		return p;
    	}
    
    	public static string GetProperty1()
    	{
    		return "abc";
    	}
    }

    Now we have a method so we can do all the steps above, add a local variable of type A, introduce it as a parameter, and convert method to non-static. Finally we can use Resharper to convert the method back to a property. Right click on the property name and go to Refactor -> Convert Method to Property. Accept all the defaults in the popup and hit next until done.

    Finally you should now have code like the following:

    public class A
    {
    	public string Method1(string p)
    	{
    		return p;
    	}
    
    	public string Property1
    	{
    		get
    		{
    			return "abc";
    		}
    	}
    }

    I know this seems like a lot of steps but once you do it a few times it won’t feel so bad and it is a heck of a lot quicker than hand fixing 20 callers. Also, since it is fully automated it is a technique that allows you to feel confident you are not changing the behavior of the code even though you don’t have tests for it yet.

subscribe via RSS