Isd Assignment
Isd Assignment
2
Introduction
The SOLID principles are a set of five design principles that were introduced by Robert C.
Martin (also known as "Uncle Bob") to help developers create more maintainable, flexible,
and scalable software. These principles provide guidelines for writing clean, modular, and
extensible code that is easier to understand, test, and maintain. By following the SOLID
principles, developers can create software that is more robust, less error-prone, and easier
to change over time. In this way, the SOLID principles have become an important aspect of
modern software development, and are widely used in a variety of programming languages
which means that it should only have one responsibility. This helps to keep the
2. Open/Closed Principle (OCP): Software entities should be open for extension but
closed for modification. This principle states that classes or modules should be
designed in a way that allows them to be extended without modifying their source
program. This principle states that any subclass should be able to be used in place
of its superclass without causing any unexpected behavior or breaking the code.
3
be as small and specific as possible, to prevent clients from being forced to depend
depend on details. Details should depend on abstractions. This principle states that
which helps to decouple modules and make them more flexible and reusable.
Together, these five principles form the acronym SOLID, and they provide guidelines for
The SOLID principles are important because they provide a set of guidelines for
designing software that is easy to maintain, understand, and extend. By following these
principles, developers can create code that is more modular, less tightly coupled, and
easier to change.
Here are some specific reasons why the SOLID principles are important:
it easier to isolate and fix bugs, and it also makes it easier to add new features or
2. Testability: SOLID principles can make code easier to test because they encourage
code that is more modular and loosely coupled. This allows for easier unit testing of
individual components, which can help catch bugs earlier in the development
process.
4
3. Flexibility: The SOLID principles encourage code that is flexible and extensible, which
means it can adapt to changing requirements and business needs. This can reduce
the cost and effort required to make changes to the codebase over time.
4. Code Quality: Following SOLID principles can result in code that is cleaner, more
readable, and easier to understand. This can improve the overall quality of the
codebase, making it easier to maintain and reduce the risk of introducing bugs or
errors.
projects.
Overall, the SOLID principles provide guidelines for designing software that is maintainable,
extensible, and easy to understand. By following these principles, developers can create
code that is more modular, less tightly coupled, and easier to change over time
5
SRP(Single-responsibility Principle):
A class should have one and only one reason to change, meaning that a
class should have only one job. That is, if we want to change a class in
case of SRP, we should change it for one specific reason.
Now, let us take a look at the following code:
public StoreCache(){
this.cache=new ConcurrentDictionary<int,String>();
}
public void addOrUpdate(int id,String message){
this.cache.AddOrUpdate(id,message,(i,s)=>message);
}
public String GetOrAdd(int id,Func<int,String> messageFactory){
return this.cache.GetOrAdd(id,messageFactory);
}
}
OCP(Open-Closed Principle):
Objects or entities should be open for extension but closed for
modification. In OCP, if we want to change the behaviour of a method of a
class then we should not modify the existing code as it can still be in use
by the client code, rather we should extend the class and do the
necessary modification in the new extended class. This extension can be
done by using Inheritance or by using Composition.
Now, if we want to use Database instead of File in the previous example
code then we can change the code in the following way if we want to
follow the open-closed principle:
Extension Using Inheritance
public class FileMessageStore{
private readonly StoreCache cache;
private readonly StoreLogger log;
private readonly storeFile fileStore;
public FileStore(DirectoryInfo workingDirectory){
// code
this.fileStore=getStore();
}
public getStore(){
return new FileSore();
}
public getStore(){
return new FileSore();
}
If we want to create DB store, we can write logics like reading from the
database in the ReadAllText method and we can write logics like writing
to the database in the WriteAllText method. But we will not be able to
implement the GetFileInfo method in the DB store. This method is totally
irrelevant while creating a DB store. So, the "messageShow" will not
work as it requires the method for file information. actually, all these
three methods are essential for making the "messageShow" work. Now,
if we discard the GetFileInfo method, the DB store may work fine but the
FileStore will get a compilation error due to the absence of this method.
On the contrary, if we keep this method, we have to keep this method
empty or we have to return null providing some codes for checking that
whether the method is returning null or not. So, clearly there arises a
problem and we are unable to manage this situation meaningfully. Now
that, this is the claim of the Liskov Substitution Principle that there
should be no problem while the objects of a superclass is replaced with
the objects of its subclasses. In our case, the messageStore is working if
we send FileStore through the IStore, but it will not work, if we send the
DB store through the Istore. So, our instance is violating the Liskov Sub-
stitution Principle. In this condition, we have to solve for the I of SOLID.
The Dependency Principle states that high-level modules should not depend on low-
level modules. Instead, both should depend on abstraction. This means that the
design of a system should be such that modules should depend on abstract interfaces,
rather than concrete implementation. This promotes flexibility, reusability and
maintainability of the code.
In the above example, High Level Modules ‘MessageStore’ depends on Low Level
Modules ‘FileStore’. So, this violates Dependency Inversion Principle.
To refactor this code, we will create an interface named ‘IStore’ and inject it to the
‘MessageStore’.
Refactored Code
Now, both ‘MessageStore’ and ‘FileStore’ depends on interface ‘IStore’ but there is
no direct dependency between them.
Interface Segregation Principle
The Interface Segregation Principle states that clients should not be forced to depend
on interfaces they do not use. Instead, a class should be designed with multiple
interfaces that are specific to the client’s need. In other words, a class should not
have a single, monolithic interface that contains methods that may not be relevant to
all clients.
Now if we want to extend our ‘MessageStore’ for both ‘FileStore’ and ‘DBStore’,
we have to create a ‘DBStore’ class which will implement ‘IStore’ interface.
But here ‘DBStore’ is forced to implement ‘getFileInfo( )’ method which is not used
for Database functionalities.
So, the above code violates Interface Segregation Principle.
Refactored Code
We will divide the ‘IStore’ interface into two interfaces named ‘IStore’ and
‘IFileInfo’.