Showing posts with label Single responsibility principle. Show all posts
Showing posts with label Single responsibility principle. Show all posts

Wednesday, 27 August 2014

Single Responsibility Principle

According to the single responsibility principle:
A class,a method ,an assembly should have one and only one reason to change.

Explanation:


  • If we have more than one reasons ,say you have n reasons to change for a class, we have to split the functionality in into n number classes.
  • Each class will handle only one responsibility and on future if we need to make one change we are going to make it in the class which handle it. 
  • When we need to make a change in a class having more responsibilities the change might affect the other functionality of the classes.
  • The Single Responsibility Principle represents a good way of identifying classes during the design phase of an application and it reminds you to think of all the ways a class can evolve.
  • A good separation of responsibilities is done only when the full picture of how the application should work is well understand.

Example

Suppose I have a project for customer management , using which users can
a. Do CRUD(Create Retrieve Update Delete) operations on customer data
b. Send mails for CU to customer and D to Administrator
c. and also, we have a requirement to log exceptions if there is a failure.
So, the first step we do is create three layers in the CustomerManagementProject:
a. UI
b. BAL
c. DAL
Now, UI takes care of all UI related functionality and DAL takes care of all data related functionality.
The middle tier has the business rules to
a. Create/Update/Delete Customers
b. Sending email and email format
c. Log Exceptions.
The BAL class looks like:
The sample sequence diagram is:
Now,
if there is a change in the business rules to send email or log exceptions we are going to touch the manage customerBAL class.
So, this class is violating SRP.

How To Resolve:


1. Although BAL has to do all the three functions of managing customers, sending mails and logging errors.
Let us have three separate projects:
a. ManageCustomerBAL
b.Exceptions
c.Email

So, now my solution looks something like:
Even though we have moved exception and email to two different projects, but still then we need to create an object of the exception class and log exceptions.
For example my BAL refers to Exception like

Add reference
Create an instance of the class
Call the method
So, now the sequence diagram looks like:
Similarly to log email exceptions we have another class in LogException namespace.
But suppose, the requirement changes and I need to add the exception to event viewer as well what do I do?

You cannot come again and instance of another class in ManageCustomerBAL.
If you create it you are again violating SRP.

So, what should I do??

Now , we need to add an interface for logging. The exception class and the BAL refer to the exception logging methods using interface.
So,What we need to do is replace the FileException Class with a generic interface and extend the FileException class from this interface.
Step 1: Create a project to contain the Interface.
Step 2: And add method to the interface.


Step 4 : Extend this Interface in all the exception classes

Step 5: Remove the reference to Exception from BAL and add reference to IInterface.
Step 6: Add reference for the interface in BAL





Now that we have added an interface , there is going to be no change in the BAL if we are going to add a new class to the LogException Namespace.
The problem is how do I create an object for the interface?
So, I should use a factory class.
Step 7: Add a ExceptionFactory project 
Step 8 : Add reference to Exception and IInterface to the ExceptionFactory project.
The interface is what which will help to identify the classes properly.
and how do you identify the class?
Step 9:You have a key-value pair in the web.config file something like

Step 10: In the ExceptionFactory add a  method which reads this web.config and creates objects of required classes.

Step 11: Refer factory class in BAL
So, whenever you have a change in requirement you need to change only at two places:
a. The ExceptionFactory
b.The LogException class.

SOLID Design Principles

SOLID : Design Principles

Software design principles represent a set of guidelines that helps us to avoid having a bad design. The design principles are associated to Robert Martin who gathered them in "Agile Software Development: Principles, Patterns, and Practices". 
According to Robert Martin there are 3 important characteristics of a bad design that should be avoided:
  • Rigidity - It is hard to change because every change affects too many other parts of the system.
  • Fragility - When you make a change, unexpected parts of the system break.
  • Immobility - It is hard to reuse in another application because it cannot be disentangled from the current application.

Following 2 characters should be taken care during designing any software:
  • High Cohesion - How focused are the responsibilities of the modules you are designing.
  • Low Coupling - The degree to which modules rely on other modules.
Principles Of Object Oriented Class Design (the "SOLID" principles)
S => SRP Single responsibility principle - the notion that an object should have only a single responsibility.

O => OCP Open/closed principle the notion that “software entities … should be open for extension, but closed for modification”. 

L => LSP Liskov substitution principle the notion that “objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program”. 

I=>  ISP Interface segregation principle the notion that “many client specific interfaces are better than one general purpose interface.” 

D => DIP Dependency inversion principle the notion that one should “Depend upon Abstractions. Do not depend upon concretions.” Dependency injection is one method of following this principle.

I think that these form the foundation of Object Oriented design that allows concise, modular, and ultimately maintainable code. This means code that you (or others) can understand and modify easily and without causing unintended consequences for the function of the application in which the code resides.

Although the above design principles are good and helpful, but they should be used intelligently otherwise this may lead to problems.

The other principle , that is of a great importance is YAGNI (You ain't gonna need it).

According to YAGNI:
  • The time spent is taken from adding, testing or improving necessary functionality.
  • The new features must be debugged, documented, and supported.
  • Any new feature imposes constraints on what can be done in the future, so an unnecessary feature now opens the possibility of conflicting with a necessary feature later.[clarification needed]
  • Until the feature is actually needed, it is difficult to fully define what it should do and to test it. If the new feature is not properly defined and tested, it may not work correctly, even if it eventually is needed.
  • It leads to code bloat; the software becomes larger and more complicated.
  • Unless there are specifications and some kind of revision control, the feature may not be known to programmers who could make use of it.
  • Adding the new feature may suggest other new features. If these new features are implemented as well, this may result in a snowball effect towards feature creep.



But then futuristic thinking is also a must while designing a software.
So, you should always take design decisions intelligently.