13 August 2008

ReSharper Combos -- Refactoring To Components

ReSharper has a number of features which are powerful by themselves, but reveal even more coolness when combined with other features. It's like Kung-Fu, when master can outperform enemies by wisely combining basic movements and strikes.

Let's take for example a task of converting existing system, where all types are instantiated explicitly, to some component container system. Without ReSharper, this task is SCARY! Just imagine, going through hundreds or even thousands of files, checking where particular component is used, where instance is created and how passed to clients and manually updating all that code. Days or weeks to complete? No, we aren't going to do this...

With ReSharper the task is still not simple one, but it can be achieved in a reasonable amount of time. Here is simple example:

  public class TheManager
  {
    public void Manage(string text) {  }
  }
 
  public class TheProcessor
  {
    private readonly TheManager myManager;
 
    public TheProcessor(TheManager manager)
    {
      myManager = manager;
    }
 
    public void Process(IEnumerable<string> texts)
    {
      foreach (var text in texts)
        myManager.Manage(text);
    }
  }
 
  internal class Program
  {
    public static void Main(string[] args)
    {
      var processor = new TheProcessor(new TheManager());
      processor.Process(args);
    }
  }


Now let's make it utilize some fictional ComponentContainer:

1. Create temporary static class ComponentFactory to put factory methods in
2. Execute Replace constructor with factory method refactoring against component constructor, specify ComponentFactory as containing type.
3. Use Extract Interface refactoring from the component implementation.
4. Utilize Use base type where possible refactoring, select extracted interface. This should update all usages from specific class to interface.
5. Find Usages of component and verify you don't have any references to the class except instantiation inside ComponentFactory. Having other references mean interface was not complete, or there are dependencies on component implementation. Refactor as needed.

Now you should have something like this:

  public static class ComponentFactory
  {
    public static ITheManager CreateTheManager()
    {
      return new TheManager();
    }
  }
 
  public interface ITheManager
  {
    void Manage(string text);
  }
 
  public class TheManager : ITheManager
  {
    public void Manage(string text) { }
  }
 
  public class TheProcessor 
  {
    private readonly ITheManager myManager;
 
    public TheProcessor(ITheManager manager)
    {
      myManager = manager;
    }
 
    public void Process(IEnumerable<string> texts)
    {
      foreach (var text in texts)
        myManager.Manage(text);
    }
  }
 
  internal class Program
  {
    public static void Main(string[] args)
    {
      var processor = new TheProcessor(ComponentFactory.CreateTheManager());
      processor.Process(args);
    }
  }


Note, how TheProcessor now uses ITheManager interface instead of specific implementation.

What you do next depends on what framework for components you are going to use. If you plan to use one of the Dependency Injection frameworks out there, you will continue with other components (TheProcessor in our example) and let framework inject ITheManager dependency into constructor. If you are going to use component querying system, you will update component constructor to use factory method instead of parameters, and use Safe Delete on parameters to remove them and update usages.

After you finish with refactoring all component access to ComponentFactory static class, you can change the implementation of factory methods to query your component framework of choice.

Finally, you are ready for the last strike to finish it off: use Inline Method refactoring to get rid of temporary factory methods and finish conversion of your code.