Saturday, October 15, 2011

Extension Class: LogHelperExt

I wrote a helper class for logging text messages long time ago. Recently I tried to write a document and demo project about using this helper class.  During the writing process, I found that the helper class can be further enhanced.

The helper class provides some static methods for writing a message string. One of  basic method takes several parameters, with ILog instance as its first parameter.  I realized that actually this instance is not needed to be passed in since this is a singleton instance. Why should I pass it every time? I started to simple this method.  The strategy I took is to add another helper class, called as LogHelperExt. I tried to avoid to change LogHelper because this class has been used in many places.

The new helper class contains much simple APIs. The first one is Initialize:

public class LogHelperExt {
  private int m_Spaces;
  private int m_indents;

  public static ILog Logger { get; private set; }
  public static LogHelperExt Instance { get; private set; }

  private LogHelperExt() : this(0)
  {
  }

  private LogHelperExt(int indents)
  {
    m_Spaces = 0;
    m_indents = indents;
  }

  public static LogHelperExt Initialize()
  {
    return Initialize(null, 0);
  }

  public static LogHelperExt Initialize(ILog log)
  {
    return Initialize(log, 0);
  }

  public static Initialize(ILog log, int indents)
  {
    if ( Instance == null )
    {
      Instance = new LogHelperExt(indents);
      Logger = log;
    }
  }
  ...
}

The Initialize method is to pass ILog instance in. This method is normally used once. An additional indent value is passed for a new feature of indenting spaces for logged messages.

The commonly used API for writing messages is as followings:

public LogHelperExt WriteMessage(string flags, LogType logType, GetMessageDelegate getMessage)
{
  if (getMessage != null )
  {
    LogHelper.WriteMessage(Logger, flags, logType,
        delegate()
        {
          return string.format("{0}{1}",
            m_Spaces > 0 new string(' ', m_Spaces) : "",
            getMessage):
        }
  }
  return this;
}

This interface is much cleaner than before. Notice that the API method is an instance method with data type of the class itself. I intended to design this class in this way, fluent interface pattern, so that I can chain the calls just in one line.

The indention and un-indention feature are added to this class:

public LogHelperExt Indent() {
  m_Spaces += m_indents;
  return this;
}

public LogHelperExt Unindent {
  m_Spaces -= m_indents;
  if ( m_Spaces < 0 )
  {
    m_Spaces = 0;
  }
  return this;
}

With above changes, I will use LogHelperExt for logging messages. Here is the example I wrote in my demo project:

class DemoClass {
  public void TestMethod()
  {
    LogHelperExt.Instance.WriteMessage("d", LogType.Debug, "Enter TestMethod").Indent();
    ...
    LogHelperExt.WriteMessage("d", LogType.Debug, "Test message");
    ...
    LogHelperExt.Instance.UnIndent().WriteMessage("d", LogType.Debug, "Leaving TestMethod");
  }
}

0 comments: