Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / All-Topics

Refactor: Sequential Coupling => Template Method

5.00/5 (2 votes)
15 Apr 2010CPOL2 min read 1  
Refactor: Sequential Coupling => Template Method

Another colleague brought me a present today - the blog post. Thank you. You were right!

We will do some refactoring which will lead us from Anti-Pattern to Pattern. From Sequential Coupling to Template Method. And as I see it could be a very common way to refactor bad code that represents mentioned anti-pattern.

So, let's start with the following question. What do you see to be wrong with following code?

C#
public class Manager
{
  public void DoTheProject()
  {
    IWorker worker = GetMeWorker();

    worker.PreWork();
    worker.Work();
    worker.AfterWork();
  }

Manager is a very angry guy and he needs to get the project done. For that, he would like to get some worker, which implements IWorker interface, and delegate some work to him. But also, manager knows that worker could be new to project so it will require to go ahead and do some preparational work before and maybe something to do after work is done...

What is wrong? Answer is that Manager cares too much about how worker should organize his work. Why should manager know that worker needs to be prepared for work? What we have here is the Sequential Coupling anti-pattern.

(My definition)

Sequential Coupling Anti-Pattern - appears when consuming code is forced to call methods of used object in particular sequence to make it work correctly.

If we call Work and then PreWork, code could be broken. And we want to prevent this. For example, we can move all that stuff in one method - Work, but also sometimes, it is needed to perform pre or/and after work, but sometimes not. That is why we had the following design that allowed us do this. See that StandardWorker doesn't need to do something after he has finished. This was achieved with virtual and abstract methods.

C#
public interface IWorker
{
  void PreWork();
  void Work();
  void AfterWork();
}

public abstract class WorkerBase : IWorker
{
  public virtual void PreWork(){}

  public abstract void Work();

  public virtual void AfterWork(){}
}

public class StandardWorker : WorkerBase
{
  public override void PreWork()
  {
    Console.WriteLine("... I need to prepare to work ...");
  }
  public override void Work()
  {
    Console.WriteLine("... hard work is in process ...");
  }
}

So, what we need to do is to hide the order in which we call methods, be sure that order remains the same, and still have the possibility to override each method. What I just described is Template Method.

In our example, we could leave one method in interface, then implement it in base class with calling everything else we need in the correct order, each of those things we call could be overridden, we left them protected to not show to the world.

C#
public interface IWorker
{
  void Work();
}

public abstract class WorkerBase : IWorker
{
  //this is template method
  public void Work()
  {
    PreWorkActivity();
    WorkActivity();
    AfterWorkActivity();
  }

  protected virtual void PreWorkActivity() { }
  protected abstract void WorkActivity();
  protected virtual void AfterWorkActivity() { }
}

public class StandardWorker : WorkerBase
{
  protected override void PreWorkActivity()
  {
    Console.WriteLine("... I need to prepare to work ...");
  }
  protected override void WorkActivity()
  {
    Console.WriteLine("... hard work is in process ...");
  }
}

public class Manager
{
  public void DoTheProject()
  {
    IWorker worker = GetMeWorker();

    worker.Work();
  }

  private IWorker GetMeWorker()
  {
    return new StandardWorker();
  }
}

It really looks for me that it could be common to perform refactoring from Sequential Coupling to Template Method.

Hope you liked this post.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)