SRP simple

    #if Old
        // THE class is doing things WHICH HE IS NOT SUPPOSED TO DO. 
        // its over loaded with lot of responsibility.
        // customer class should do customer data validations. 
        // but if you see the catch block closely it also doing LOGGING activity.  
    class Customer
    {
        public void Add()
        {
            try
            {
                //database code goes here
            }
            catch (Exception ex)
            {
                System.IO.File.WriteAllText(@"c:\error.text", 
                DateTime.Now.ToString() + ex.StackTrace + ex.Message);
            }
        }
    }
    #endif

    #if Improve
    class FileLogger
        {
        public void Handle(string error)
        {
            System.IO.File.WriteAllText(@"c:\error.text", error);
        }
    }
    class Customer
    {
        private FileLogger obj = new FileLogger();
        public virtual void Add()
        {
            try
            {
                //database code goes here
            }
            catch (Exception ex)
            {
                obj.Handle(DateTime.Now.ToString() + ex.StackTrace + ex.Message);
            }
        }
    }
    #endif


#   OCP sample
     #if Old
    class customer
    {
        private int _CustType;
        public int CustType
        {
            get { return _CustType; }
            set { _CustType = value; }
        }
        public double getDiscount(double TotalSales)
        {
            /* if we add a new customer type we need to go 
             * and add one more "IF" condition in the "getDiscount" function, 
             * we need change the customer class. */
            if (_CustType == 1) return TotalSales - 100;
            else return TotalSales - 50;
        }
    }
    #endif

    #if Improve
    // putting in simple words the "Customer" class is now closed for any new modificatin 
    // but it's open for extensions when new customer types are added to the project.
    class Customer
    {
        public virtual double getDiscount(double TotalSales) { return TotalSales; }
    }

    class SilverCustomer : Customer
    {
        public override double getDiscount(double TotalSales)
        {
            return base.getDiscount(TotalSales) - 50;
        }
    }
    class goldCusomter : Customer
    {
        public override double getDiscount(double TotalSales)
        {
            return base.getDiscount(TotalSales) - 100;
        }
    }
        #endif


#   LSP sample
    #if Old
    class Customer
    {
        public virtual double getDiscount(double TotalSales) { return TotalSales; }
        public virtual void Add() { }
    }

    /// <summary>
    /// per the inheritance hierarchy the "Customer" object can point to any one of its child objects 
    /// and we do not expect any unusual behavior.
    /// but when "Add" method of the "Enquiry" object is invoked 
    /// it leads to error "Exception was unhandled" during runingtime.
    /// because our "Equiry" object does save enquires to database as they are not actual customer.
    /// </summary>
    class Enquiry:Customer
    {
        public override double getDiscount(double TotalSales)
        {
            return base.getDiscount(TotalSales)-5;
        }
        public override void Add()
        {
            throw new Exception("Not allowed");
        }
    }
    #endif

    #if Improve
    /// <summary>
    /// per the inheritance hierarchy the "Customer" object can point to any one of its child objects 
    /// and we do not expect any unusual behavior.
    /// but when "Add" method of the "Enquiry" object is invoked 
    /// it leads to error "Exception was unhandled" during runingtime.
    /// because our "Equiry" object does save enquires to database as they are not actual customer.
    /// 
    /// In other words the "Enquiry" has discount calculation, it looks like a "Customer" but it is not a customer. 
    /// so the parent cannot replace the child object seamlessly. 
    /// "Customer" is not the actual parent for the "Enquiry" class. "Enquiry" is a different entity altogether.
    /// 
    /// So LISKOV principle says the parent should easily replace the child object.
    /// So to implement LISKOV we need to create two interfaces one is for discount and other for database. 
    /// </summary>

    interface IDiscount
    {
        double getDiscount(double TotalSales);
    }
    interface IDatabase
    {
        void Add();
    }
    class Enquiry : IDiscount
    {
        public double getDiscount(double TotalSales)
        {
            return TotalSales - 5;
        }
    }
    class Cusomer : IDiscount, IDatabase
    {
        private FileLogger obj = new FileLogger();
        public virtual void Add()
        {
            try { }
            catch (Exception ex)
            {
                obj.Handle(DateTime.Now.ToString() + ex.StackTrace + ex.Message);
            }
        }
        public virtual double getDiscount(double TotalSales) { return TotalSales; }
    }
    /// <summary>
    /// assisitant class
    /// </summary>
    class FileLogger
    {
        public void Handle(string error)
        {
            System.IO.File.WriteAllText(@"c:\error.text", error);
        }
    }
    #endif


#   ISP sample

    #if Old
    /// <summary>
    /// the new requirement which as come up, 
    /// we have two kinds of client's: who want's just use "Add" method. another who wants to use "Add" + "Read".
    /// 
    /// it's not good idea to add Read method in IDatabase interface, it will affect current client.
    /// </summary>
    interface IDatabase
    {
        void Add(); // old client are happy with these.
        void Read(); // add for new clients.
    }
    #endif

    #if Improve
    interface IDatabase
    {
        void Add(); // old client are happy with these.
    }
    /// <summary>
    /// a better approach would be to keep exisitng clients in their own sweet world 
    /// and the serve the new clients's separately.
    /// </summary>
    interface IDatabaseV1 : IDatabase
    {
        void Read();
    }
    class CusomterWithRead : IDatabase, IDatabaseV1
    {
        public void Add() {
            Cusomter obj = new Cusomter();
            obj.Add();
        }
        public void Read() { // logic for read
        }
    }
    #endif
    //IDatabase i = new Customer(); // 1000 happy old clients not touched
    //i.Add();

    //IDatabaseV1 iv1 = new CustomerWithread(); // new clients
    //Iv1.Read();


#   DIP sample
    #if Old
    /// <summary>
    /// the logger class is satisfy SRP. 
    /// If we want change logger , for example, database logger, EventViewer logger, 
    /// we have to change customer code, it's not good idea.
    /// </summary>
    class Customer
    {
        private FileLogger obj = new FileLogger();
        public virtual void Add()
        {
            try {
                // database code logic.
            }
            catch(Exception ex) { obj.Handle(ex.ToString()); }
        }
    }
    class FileLogger
    {
        public void Handle(string error)
        {
            System.IO.File.WriteAllText(@"c:\error.text", error);
        }
    }
    #endif

    #if Improve
    interface ILogger
    {
        void Handle(string error);
    }
    class FileLogger: ILogger
    {
        public void Handle(string error)
        {
            System.IO.File.WriteAllText(@"c:\error.text", error);
        }
    }
    class DatabaseLogger : ILogger
    {
        public void Handle(string error)
        {
            // log wirte to database table.
        }
    }
    class EventViewerLogger : ILogger
    {
        public void Handle(string error)
        {
           // log errors to event viewer.
        }
    }
    class Customer : IDiscount, IDatabase
    {
        private ILogger logObj;
        public Customer(ILogger log)
        {
            logObj = log;
        }
    }
    #endif

results matching ""

    No results matching ""