Thursday, November 21, 2013

Bridge Design Pattern & Logging System

   While going through some basic stuff about design pattern, I come across the Bridge design pattern & decided to implement it for Logging system. 
  My take is to separate concern about What Is Being Logged & where is being Logged.
An application can log errors as well as user actions too. Same time logging can go to various places like Database, EventLog or a File. 
   Here is Code for Classes that implement Logging system as Bridge Design pattern.
Code here is from a console application 'POALoggingAgent' with a class file 'LoggingAgent.cs' & implicitly created entry point i.e. Program.cs.

[LoggingAgent.cs]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Data;
using System.Data.SqlClient;

namespace POALoggingAgent
{
    //Process of Logging Should be Decoubled from Loggable Message
    abstract class LogImplementor
    {
        public abstract bool Log(string Message);
    }

    //Let us to change Logging Implementation at any latter moment when new requirement arise
    class LogAbstraction
    {
        protected LogImplementor Implementor;
        protected string Message;

        public LogAbstraction(string Msg)
        {
            Message = Msg;
        }

        // Implementor
        public LogImplementor LogImplementor
        {
            set
            {
                Implementor = value;
            }
        }

        public virtual  bool Log()
        {
            return Implementor.Log(Message);
        }
    }

    //what is to be logged an error,a user event,application event etc
    class ErrorLogAbstraction : LogAbstraction
    {
        Exception LogggbleException;
        public ErrorLogAbstraction(Exception exp):base(string.Empty)
        {
            LogggbleException = exp;
        }

        public override bool Log()
        {
            /*manipulate exception object propeties to build */
            Message = FormatMessage();
            return Implementor.Log(Message);
        }

        public string FormatMessage()
        {
            //Do Some work on LogggbleException to create formated message and set it to Message inherited Variable
            return "***" + LogggbleException .Message+ "***";
        }
    }

    //initial logging was on console
    class ConsoleLogImplementor : LogImplementor
    {
        public override bool Log(string Message)
        {
            try
            {
                /*BEGIN - Code To Log Message To Console*/
                /*END   - Code To Log Message To Console*/

                //Place Holder
                Console.WriteLine("Class:ConsoleLogImplementor,Method:Log,Message:" + Message);
                return true;
            }
            catch
            {
                return false;
            }
        }
    }

    //logging to database is new requirement generated
    class DbLogImplementor : LogImplementor
    {
        public override bool Log(string Message)
        {
            try
            {
                /*BEGIN - Code To Log Message To DB*/
                /*END   - Code To Log Message To Db*/

                //Place Holder
                Console.WriteLine("Class:DbLogImplementor,Method:Log,Message:" + Message);
                return true;
            }
            catch
            {
                return false;
            }
        }
    }
}

Calling above code from our console Application

[Program.cs]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace POALoggingAgent
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                int i = 0;
                int j = 1;
                Console.WriteLine("Trying to Divide 1 by 0,Output = " + Convert.ToString(j / i));
            }
            catch (Exception exp)
            {
                LogAbstraction LogAb = new ErrorLogAbstraction(exp);

                //  choose console Logging Implementation
                LogAb.LogImplementor = new ConsoleLogImplementor();
                LogAb.Log();

                // choose Database Logging Implementation
                LogAb.LogImplementor = new DbLogImplementor();
                LogAb.Log();
            }
            // Wait for user
            Console.ReadKey();
        }
    }
} 
   To be Frank, I am not sure if Bridge Design Pattern is suitable case for Logging system as there are Singleton & Command, Chain of Responsibility & Subscriber- Publisher; that are often used with logging system.

   Anyone who willing to help me to improve above design of so called Logging system is more than welcomed!

No comments:

Post a Comment