Thursday, May 28, 2020

SOLID Design Principles

SOLID is an acronym for 5 important design principles when doing OOP (Object Oriented Programming).
The intention of these principles is to make software designs more understandable, easier to maintain and easier to extend.

S —Single responsibility principle

In programming, the Single Responsibility Principle states that every module or class should have responsibility over a single part of the functionality provided by the software.

You may have heard the quote: “Do one thing and do it well”.
This refers to the single responsibility principle.


Let’s do an example of how to write a piece of code that violates this principle.

class Account
{
void CreateAccount(Database db, obj accDetails)
{
try
{
db.Add(accDetails);
}
catch (Exception ex)
{
db.LogError("An error occured: ", ex.ToString());
File.WriteAllText("\LocalErrors.txt", ex.ToString());
}
}
}

We notice how the  method has too much responsibility, given that it can both create a new account, log an error in the database, and log an error in a local file.
This violates the single responsibility principle.

Let’s try to correct it.

class Account
{
private ErrorLogger errorLogger = new ErrorLogger();
void CreateAccount(Database db, obj accDetails)
{
try
{
db.Add(accDetails);
}
catch (Exception ex)
{
errorLogger.log(ex.ToString())
}
}
}
class ErrorLogger
{
void log(string error)
{
db.LogError("An error occured: ", error);
File.WriteAllText("\LocalErrors.txt", error);
}
}
By abstracting the functionality that handles the error logging, we no longer violate the single responsibility principle.
Now we have two classes that each has one responsibility; to create a post and to log an error, respectively.

O — Open/closed principle

In programming, the open/closed principle states that software entities (classes, modules, functions, etc.) should be open for extensions, but closed for modification.

Let’s take an example of bank accounts like regular savings, salary saving, corporate etc. for different customers. As for each customer type, there are different rules and different interest rates. The code below violates OCP principle if the bank introduces a new Account type. Said code modifies this method for adding a new account type.

public class Account
{
 public decimal Interest { get; set; }
 public decimal Balance { get; set; }
 // members and function declaration
 public decimal CalcInterest(string accType)
 {

 if (accType == "Regular") // savings
 {
 Interest = (Balance * 4) / 100;
 if (Balance < 1000) Interest -= (Balance * 2) / 100;
 if (Balance < 50000) Interest += (Balance * 4) / 100;
 }
 else if (accType == "Salary") // salary savings
 {
 Interest = (Balance * 5) / 100;
 }
 else if (accType == "Corporate") // Corporate
 {
 Interest = (Balance * 3) / 100;
 }
 return Interest;
 }
}

We can apply OCP by using interface, abstract class, abstract methods and virtual methods when you want to extend functionality. Here I have used interface for example only but you can go as per your requirement.

 interface IAccount
{
 // members and function declaration, properties
 decimal Balance { get; set; }
 decimal CalcInterest();
}
 
//regular savings account 
public class RegularSavingAccount : IAccount
{
 public decimal Balance { get; set; } = 0;
 public decimal CalcInterest()
 {
 decimal Interest = (Balance * 4) / 100;
 if (Balance < 1000) Interest -= (Balance * 2) / 100;
 if (Balance < 50000) Interest += (Balance * 4) / 100;
 
 return Interest;
 }
}
 
//Salary savings account 
public class SalarySavingAccount : IAccount
{
 public decimal Balance { get; set; } = 0;
 public decimal CalcInterest()
 {
 decimal Interest = (Balance * 5) / 100;
 return Interest;
 }
}
 
//Corporate Account
public class CorporateAccount : IAccount
{
 public decimal Balance { get; set; } = 0;
 public decimal CalcInterest()
 {
 decimal Interest = (Balance * 3) / 100;
 return Interest;
 }
}

In the above code three new classes are created; regular saving account, SalarySavingAccount, and CorporateAccount, by extending them from IAccount.

This solves the problem of modification of class and by extending interface, we can extend functionality.

Above code is implementing both OCP and SRP principle, as each class has single is doing a single task and we are not modifying class and only doing an extension.

Liskov Substitution Principle (LSP)

Definition by Robert C. Martin: Functions that use pointers or references to base classes must be able to use objects of derived classes without knowin

Difference Between dispose() and finalize() in C#

Definition of dispose()

The dispose() method releases the unmanaged resources that are held by an object of the class. The unmanaged resources are files, data connections, etc. The method dispose() is declared in the interface IDisposeable and it is implemented by the class by implementing the interface IDisposable. This method is not called automatically. The programmer has to implement it manually when you are creating a custom class that will be used by others.

The method has the following syntax:

  1. public void dispose( ){
  2. // Dispose code here
  3. }

In the above syntax, you can observe that the method is declared as public. It is because this method is defined in the interface IDisposable and it has to be implemented by the class that implements this interface. So, to provide accessibility to the implementing class, the method is declared as public.

This method is invoked manually by the code of a program as it is implemented to invoke. The methods performance is fast, and it instantly frees the resources held by the object of a class.

Definition of finalize()

The finalize() method is defined in the object class. It is used for cleanup activities. This method is called by the garbage collector when the reference of an object is not used for a long time. Garbage collector frees the managed resources automatically but if you want to free the unmanaged resources like file handle, data connection, etc., the finalize method has to be implemented manually. The garbage collector invokes the method finalize() just before it destroys the object completely.

The syntax of the method finalize():

  1. protected void finalize( ){
  2. // finalization code here
  3. }

In the syntax above, the method finalize() is declared as protected. The reason behind this is, the method finalize() must not be accessible from outside the class, and it must only be accessible to the garbage collector.

The finalize() method affects the cost of the performance as it does not free the memory instantly. In C# the finalize method is called automatically with destructors.

Key Differences Between dispose() and finalize()

  1. The method dispose() is defined in an interface IDisposable. On the other hand, the method finalize() is defined in the class object.
  2. The method dispose() has to be manually invoked inside the code by a programmer, while the method finalize is automatically invoked by the garbage collector before it destroys the object.
  3. The method dispose could be invoked anytime, whereas the method finalize is invoked by the garbage collector when it finds that that object has not been referenced for a long time.
  4. The method dispose() is implemented in a class after implementing the interface IDisposable. The method finalize() has to be implemented only for unmanaged resources because the managed resources are automatically freed by the garbage collector.
  5. The access specifier of the method dispose() is public as it is defined in the interface IDisposable and it would be implemented by the class that implements this interface hence, it should be public. On the other hand, the method finalize() has protected access specifier so that it should not be accessible to any member outside the class.
  6. The method dispose() is fast and frees the object instantly hence, it does not affects the performance cost. The method finalize() is slower and does not free the resources held by the object instantly.

What is managed and unmanaged code

When working with .NET Framework, you will often encounter the term "managed code". This document will explain what this term means and additional information around it.

To put it very simply, managed code is just that: code whose execution is managed by a runtime. In this case, the runtime in question is called the Common Language Runtime or CLR, regardless of the implementation (Mono or .NET Framework or .NET Core). CLR is in charge of taking the managed code, compiling it into machine code and then executing it. On top of that, runtime provides several important services such as automatic memory management, security boundaries, type safety etc.

Contrast this to the way you would run a C/C++ program, also called "unmanaged code". In the unmanaged world, the programmer is in charge of pretty much everything. The actual program is, essentially, a binary that the operating system (OS) loads into memory and starts. Everything else, from memory management to security considerations are a burden of the programmer.

Managed code is written in one of the high-level languages that can be run on top of .NET, such as C#, Visual Basic, F# and others. When you compile code written in those languages with their respective compiler, you don’t get machine code. You get Intermediate Language code which the runtime then compiles and executes. C++ is the one exception to this rule, as it can also produce native, unmanaged binaries that run on Windows.


MANAGED CODEUNMANAGED CODE
It is executed by managed runtime environment or managed by the CLR.It is executed directly by the operating system.
It provides security to the application written in .NET Framework.It does not provide any security to the application.
Memory buffer overflow does not occur.Memory buffer overflow may occur.
It provide runtime services like Garbage Collection, exception handling, etc.It does not provide runtime services like Garbage Collection, exception handling, etc.
The source code is complied in the intermideate language know as IL or MSIL or CIL.The source code direclty compile into native langugae.
It does not provide low-level access to the prgrammer.It provide low-level access to the prgrammer.

HttpHandlers and HttpModule

Introduction

Many times we want to implement pre-processing logic before a request hits the IIS resources. For instance you would like to apply security mechanism, URL rewriting, filter something in the request, etc. ASP.NET has provided two types of interception HttpModule and HttpHandler. This article walks through it.

The Problem

Many times we need to inject some kind of logic before the page is requested. Some of the commonly used pre-processing logics are stat counters, URL rewriting, authentication / authorization and many more. We can do this in the code behind but then that can lead to lot of complication and tangled code. The code behind will not solve the purpose because in some implementations like authorization, we want the logic to execute before it reaches the resource. ASP.NET provides two ways of injecting logic in the request pipeline HttpHandlers and HttpModules.

1.jpg

HttpHandler - The Extension Based Preprocessor

HttpHandler help us to inject pre-processing logic based on the extension of the file name requested. So when a page is requested, HttpHandler executes on the base of extension file names and on the base of verbs. For instance, you can visualize from the figure below how we have different handlers mapped to file extension. We can also map one handler to multiple file extensions. For instance, when any client requests for file with extension "GIF" and "JPEG", handler3 pre-processing logic executes.

2.jpg

HttpModule - The Event Based Preprocessor

HttpModule is an event based methodology to inject pre-processing logic before any resource is requested. When any client sends a request for a resource, the request pipeline emits a lot of events as shown in the figure below:

3.jpg
Below is a detailed explanation of the events. We have just pasted this from here.

  • BeginRequest: Request has been started. If you need to do something at the beginning of a request (for example, display advertisement banners at the top of each page), synchronize this event.
     
  • AuthenticateRequest: If you want to plug in your own custom authentication scheme (for example, look up a user against a database to validate the password), build a module that synchronizes this event and authenticates the user in a way that you want to.
     
  • AuthorizeRequest: This event is used internally to implement authorization mechanisms (for example, to store your access control lists (ACLs) in a database rather than in the file system). Although you can override this event, there are not many good reasons to do so.
     
  • PreRequestHandlerExecute: This event occurs before the HTTP handler is executed.
     
  • PostRequestHandlerExecute: This event occurs after the HTTP handler is executed. 
     
  • EndRequest: Request has been completed. You may want to build a debugging module that gathers information throughout the request and then writes the information to the page.

We can register these events with the HttpModules. So when the request pipe line executes depending on the event registered, the logic from the modules is processed.

4.jpg

The Overall Picture of Handler and Modules

Now that we have gone through the basics, let's understand what is the Microsoft definition for handler and modules to get the overall picture.

Reference: INFO: ASP.NET HTTP Modules and HTTP Handlers Overview

Modules are called before and after the handler executes. Modules enable developers to intercept, participate in, or modify each individual request. Handlers are used to process individual endpoint requests. Handlers enable the ASP.NET Framework to process individual HTTP URLs or groups of URL extensions within an application. Unlike modules, only one handler is used to process a requests.

5.jpg

Steps to Implement HttpHandlers

Step 1

HttpHandlers are nothing but classes which have pre-processing logic implemented. So the first thing is to create a class project and reference System.Web namespace and implement the IHttpHandler interface as shown in the below code snippet. IHttpHandler interface has two methods which needs to be implemented; one is the ProcessRequest and the other is the IsResuable. In the ProcessRequest method, we are just entering the URL into the file and displaying the same into the browser. We have manipulated the context response object to send the display to the browser.

using System;
using System.Web;
using System.IO;
namespace MyPipeLine
{
    public class clsMyHandler : IHttpHandler
    {
        public void ProcessRequest(System.Web.HttpContext context)
        {
            context.Response.Write("The page request is " + context.Request.RawUrl.ToString());
            StreamWriter sw = new StreamWriter(@"C:\requestLog.txt"true);
            sw.WriteLine("Page requested at " + DateTime.Now.ToString() +
            context.Request.RawUrl); sw.Close();
        }
        public bool IsReusable
        {
            get
            {
                return true;
            }
        }
    }
}


Step 2

In step 2, we just need to make an entry of HttpHandlers tag. In the tag, we need to specify which kind of extension requested will invoke our class.

<system.web>
    <httpHandlers>
        <add verb="*" path="*.Shiv,*.Koirala" type="MyPipeLine.clsMyHandler, MyPipeLine"/>
    </httpHandlers>
</
system.web>

Once done, request for page name with extension a shiva and you should see a display as shown below. So what has happened is when the IIS sees that request is for a a.shiva page extension, it just calls the clsMyHandler class pre-processing logic.

6.jpg
Steps to Implement HttpModule

Step 1

As discussed previously, HttpModule is an event pre-processor. So the first thing is to implement the IHttpModule and register the necessary events which this module should subscribe. For instance, we have registered in this sample for BeginRequest and EndRequest events. In those events, we have just written an entry onto the log file.

  public class clsMyModule : IHttpModule
    {
        public clsMyModule()
        { }
        public void Init(HttpApplication objApplication)
        {
            // Register event handler of the pipe line
            objApplication.BeginRequest += new EventHandler(this.context_BeginRequest);
            objApplication.EndRequest += new EventHandler(this.context_EndRequest);
        }
        public void Dispose()
        {
        }
        public void context_EndRequest(object sender, EventArgs e)
        {
            StreamWriter sw = new StreamWriter(@"C:\requestLog.txt"true);
            sw.WriteLine("End Request called at " + DateTime.Now.ToString()); sw.Close();
        }
        public void context_BeginRequest(object sender, EventArgs e)
        {
            StreamWriter sw = new StreamWriter(@"C:\requestLog.txt"true);
            sw.WriteLine("Begin request called at " + DateTime.Now.ToString()); sw.Close();
        }
    }

Step 2

We need to enter those module entries into the HttpModule tag as shown in the below code snippet:

      <httpModules>
            <add name="clsMyModule" type="MyPipeLine.clsMyModule, MyPipeLine"/>
        </httpModules>

The Final Output

If you run the code, you should see something like this in the RequestLog.txt. The above example is not so practical. But it will help us understand the fundamentals.

Begin request called at 11/12/2008 6:32:00 PM
End Request called at 11/12/2008 6:32:00 PM
Begin request called at 11/12/2008 6:32:03 PM
End Request called at 11/12/2008 6:32:03 PM
Begin request called at 11/12/2008 6:32:06 PM
End Request called at 11/12/2008 6:32:06 PM
Begin request called at 11/12/2008 8:36:04 PM
End Request called at 11/12/2008 8:36:04 PM
Begin request called at 11/12/2008 8:37:06 PM
End Request called at 11/12/2008 8:37:06 PM
Begin request called at 11/12/2008 8:37:09 PM
End Request called at 11/12/2008 8:37:09 PM
Begin request called at 11/12/2008 8:37:38 PM
Page requested at 11/12/2008 8:37:38 PM/WebSiteHandlerDemo/Articles.shiv
End Request called at 11/12/2008 8:37:38 PM

Try Catch Question




-------------------------------------------------------------------------------------------------------------------------