SOLID Principles


S: Single responsibility principle:- A class should take care of only one responsibility.


O: Open closed principle:- Extension should be preferred over modification.


L: Liskov substitution principle:- A parent class object should be able to refer child objects seamlessly during runtime polymorphism.


I: Interface segregation principle:- Client should not be forced to use a interface if it does not need it.


D: Dependency inversion principle:- High level modules should not depend on low level modules but should depend on abstraction.

Static Constructor

Static constructors are introduced with C# to initialize the static data of a class. CLR calls the static constructor before the first instance is created.

The static constructor has the following features:

  • No access specifier is required to define it.
  • You cannot pass parameters in static constructor.
  • A class can have only one static constructor.
  • It can access only static members of the class.
  • It is invoked only once, when the program execution begins.

Default Access Modifiers in C#

Name Default accessibility
Class internal
Interface public
Delegate internal
Struct internal
enum public

 

Members of Default member accessibility
enum public
class private
interface public
struct private

 

 

Implicit VS Explicit Interface Implementations

As classes in C# can implement multiple interfaces and these interfaces may include methods that have the same signatures as existing class members or members of other interfaces.

Explicit interface implementations can be used

  • To disambiguate class and interface methods that would otherwise conflict.
  • To hide the details of an interface that the class developer considers private. This would avoid that method/property/member to be visible in the object of class that implements the interface as the level of privacy afforded by PRIVATE keyword is not that great.

A classic example where why explicit implementation would be required specifically for point 2:

img1

 

Inheritence, Association, Aggregation and Composition

Summary

To avoid confusion henceforth for these three terms, I have put forward a table below which will help us compare them from three angles: owner, lifetime, and child object.

Association Aggregation Composition
Owner No owner Single owner Single owner
Life time Have their own lifetime Have their own lifetime Owner’s life time
Child object Child objects all are independent Child objects belong to a single parent Child objects belong to a single parent

Extracting real world relationships from a requirement

The whole point of OOP is that your code replicates real world objects, thus making your code readable and maintainable. When we say real world, the real world has relationships. Let’s consider the simple requirement listed below:

  1. Manager is an employee of XYZ limited corporation.
  2. Manager uses a swipe card to enter XYZ premises.
  3. Manager has workers who work under him.
  4. Manager has the responsibility of ensuring that the project is successful.
  5. Manager’s salary will be judged based on project success.

If you flesh out the above five point requirement, we can easily visualize four relationships:-

  • Inheritance
  • Aggregation
  • Association
  • Composition

Let’s understand them one by one.

Requirement 1: The IS A relationship

If you look at the first requirement (Manager is an employee of XYZ limited corporation), it’s a parent child relationship or inheritance relationship. The sentence above specifies that Manager is a type of employee, in other words we will have two classes: parent class Employee, and a child class Manager which will inherit from the Employee class.

Requirement 2: The Using relationship: Association

Requirement 2 is an interesting requirement (Manager uses a swipe card to enter XYZ premises). In this requirement, the manager object and the swipe card object use each other but they have their own object life time. In other words, they can exist without each other. The most important point in this relationship is that there is no single owner.

Requirement 3: The Using relationship with Parent: Aggregation

The third requirement from our list (Manager has workers who work under him) denotes the same type of relationship like association but with a difference that one of them is an owner. So as per the requirement, the Manager object will own Worker objects.

The child Worker objects can not belong to any other object. For instance, a Worker object cannot belong to a SwipeCard object.

But… the Worker object can have its own life time which is completely disconnected from the Manager object. Looking from a different perspective, it means that if the Manager object is deleted, the Worker object does not die.

This relationship is termed as an “Aggregation” relationship.

Requirements 4 and 5: The Death relationship: Composition

The last two requirements are actually logically one. If you read closely, the requirements are as follows:

  1. Manager has the responsibility of ensuring that the project is successful.
  2. Manager’s salary will be judged based on project success.

Below is the conclusion from analyzing the above requirements:

  1. Manager and the project objects are dependent on each other.
  2. The lifetimes of both the objects are the same. In other words, the project will not be successful if the manager is not good, and the manager will not get good increments if the project has issues.

Below is how the class formation will look like. You can also see that when I go to create the project object, it needs the manager object.

This relationship is termed as the composition relationship. In this relationship, both objects are heavily dependent on each other. In other words, if one goes for garbage collection the other also has to be garbage collected, or putting from a different perspective, the lifetime of the objects are the same. That’s why I have put in the heading “Death” relationship.

Putting things together

Below is a visual representation of how the relationships have emerged from the requirements.

Reference: http://www.codeproject.com/Articles/330447/Understanding-Association-Aggregation-and-Composit

Search a text in SQL Server database…

Many times, developers encounter this problem while performing impact analysis. E.g. Consider a scenario where a new parameter has been to an existing stored procedure. Now the challenge to the the developer is to analyze its impact of this change in entire application and its database. Hence, as this post restrains itself to performing search in SQL database for a particular text, below given is the query that pulls all the objects with the search text in it or containing in its definition. Although there are certain tools like Red Gate search tool which are available for free.

DECLARE

@Search varchar(255)

SET

@Search=‘project’

SELECT

DISTINCT

o.name ASObject_Name,o.type_desc

FROMsys.sql_modules        m 

INNERJOINsys.objects  o ON m.object_id=o.object_id

WHERE m.definitionLike‘%’+@Search+‘%’

ORDERBY 2,1

The Dependency Injection (DI)…

In designing an object-oriented application, a major tenet of design is “loose coupling”. It means that objects should only have as many dependencies as is needed to do their job and the dependencies should be few. Furthermore, an object’s dependencies should be on interfaces and not on “concrete” objects, when possible. (A concrete object is any object created with the keyword new.) Loose coupling promotes greater reusability, easier maintainability, and allows you to easily provide “mock” objects in place of expensive services.

The “Dependency Injection” (DI) is also known as “Inversion of Control” (IoC), can be used as a technique for encouraging this loose coupling.

There are two primary approaches to implementing DI:

  1. Constructor injection
  2. Setter injection

Obviously, at some point, something must be responsible for creating the concrete objects that will be injected into another object. The injector can be a parent object, which I’ll call the “DI controller”, or can be externalized and handled by a “DI container” framework. What follows is a brief overview of the various approaches for using dependency injection techniques.

Constructor injection

It’s the technique of passing objects dependencies to its constructor.

E.g. “Person” class exposes a method for retrieving every home address of person. Consequently, the “Person” class needs a data-access object for communicating with the database. Assume, an AddressDAO exists which implements the interface IDAO.

One way that a “Person” object can get this dependency is by executing the following within the: IDAO obj1 = new AddressDAO();. The disadvantage of this are:

  1. The benefit of having the interface in the first place has been negated since the concrete instance was created locally.
  2. AddressDAO cannot easily be replaced by a mock object for testing purposes.

Hence, to avoid this following must be done.

Constructor Injection

Note that the constructor accepts an interface and not concrete object. Also, note that an exception is thrown if the orderDao parameter is null. This emphasizes the importance of receiving a valid dependency. Constructor Injection is, in my opinion, the preferred mechanism for giving an object its dependencies. It is clear to the developer while invoking the object which dependencies need to be given to the “Person” object for proper execution.

Setter Injection

But consider the following example… Suppose you have a class with ten methods that have no dependencies, but you’re adding a new method that does have a dependency on IDAO. You could change the constructor to use Constructor Injection, but this may force you to changes to all constructor calls all over the place. Alternatively, you could just add a new constructor that takes the dependency, but then how does a developer easily know when to use one constructor over the other. Finally, if the dependency is very expensive to create, why should it be created and passed to the constructor when it may only be used rarely? “Setter Injection” is another DI technique that can be used in situations such as this.

Setter Injection does not force dependencies to be passed to the constructor. Instead, the dependencies are set onto public properties exposed by the object in need. As implied previously, the primary motivators for doing this include:

  1. Supporting dependency injection without having to modify the constructor of a legacy class.
  2. Allowing expensive resources or services to be created as late as possible and only when needed.

Here is the example of how the above code would look like.

Setter Injection

Setter Injection should be used sparingly in place of Constructor Injection, because:

  1. It does not make it clear to the developer which dependencies are needed when, at least until a “has not been initialized” exception is thrown.
  2. It makes it a bit more difficult to track down where the exception came from and why it got thrown.

With this said, Setter Injection can save on modifying a lot of legacy code when introducing new methods, and can provide a performance boost if the dependency is expensive or not easily accessible.

Follow

Get every new post delivered to your Inbox.