SlideShare a Scribd company logo
eleks.comeleks.com
SOLID & IOC PRINCIPLES
The basic principles of OOP design
What is SOLID?
The first five principles of OOP design.
A set of rules on how to build an awesome application that
is flexible and easy to use, understand and maintain.
SINGLE RESPONSIBILITY PRINCIPLE
A class should have only one reason to change
Robert C. Martin
SINGLE RESPONSIBILITY PRINCIPLE
// Data access class is only responsible for data base
related operations
class DataAccess
{
public static void InsertData()
{
Console.WriteLine("Data inserted into database
successfully");
}
}
// Data access class is only responsible for data base
related operations
class DataAccess
{
public static void InsertData()
{
Logger.WriteLog("Data inserted into database
successfully");
}
}
// Logger class is only responsible for logging
related operations
class Logger
{
public static void WriteLog(string messsage)
{
Console.WriteLine("Logged Time:" +
DateTime.Now + messsage);
}
}
OPEN/CLOSED PRINCIPLE
Objects or entities should be open for
extension, but closed for modification
Bertrand Meyer
OPEN/CLOSED PRINCIPLE
// Here DataProvider is open for extension (extends to
Sql, Oracle, Oledb Providers and so on..) and closed
for manipulation
abstract class DataProvider
{
public abstract int OpenConnection();
public abstract int CloseConnection();
public abstract int ExecuteCommand();
}
class SqlDataProvider : DataProvider
{
public override int OpenConnection()
{
Console.WriteLine("nSql Connection opened");
return 1;
}
public override int CloseConnection()
{
Console.WriteLine("Sql Connection closed");
return 1;
}
public override int ExecuteCommand()
{
Console.WriteLine("Sql Command Executed");
return 1;
}
}
OPEN/CLOSED PRINCIPLE
class OracleDataProvider : DataProvider
{
public override int OpenConnection()
{
Console.WriteLine("Oracle Connection opened");
return 1;
}
public override int CloseConnection()
{
Console.WriteLine("Oracle Connection closed");
return 1;
}
public override int ExecuteCommand()
{
Console.WriteLine("Oracle Command Executed");
return 1;
}
}
class OpenClosePrincipleDemo
{
public static void OSPDemo()
{
Console.WriteLine("Open Close Principle");
DataProvider DataProviderObject =
new SqlDataProvider();
DataProviderObject.OpenConnection();
DataProviderObject.ExecuteCommand();
DataProviderObject.CloseConnection();
DataProviderObject = new OracleDataProvider();
DataProviderObject.OpenConnection();
DataProviderObject.ExecuteCommand();
DataProviderObject.CloseConnection();
}
}
LISKOV SUBSTITUTION PRINCIPLE
Let f(x) be a property of objects X of type T.
Then f(y) should be true for objects Y of type S
where S is a subtype of T
Barbara Liskov
LISKOV SUBSTITUTION PRINCIPLE
// While implementing derived classes, one needs to
ensure that, derived classes just extend the
functionality of base classes without replacing the
functionality of base classes.
class Rectangle
{
protected int mWidth = 0;
protected int mHeight = 0;
public virtual void SetWidth(int width)
{
mWidth = width;
}
public virtual void SetHeight(int height)
{
mHeight = height;
}
public virtual int GetArea()
{
return mWidth * mHeight;
}
}
// While implementing derived class if one replaces
the functionality of base class then,
// it might results into undesired side effects when
such derived classes are used in existing program
modules.
class Square : Rectangle
{
// This class modifies the base class
functionality instead of extending the base class
functionality. Now below methods implementation will
impact base class functionality.
public override void SetWidth(int width)
{
mWidth = width;
mHeight = width;
}
public override void SetHeight(int height)
{
mWidth = height;
mHeight = height;
}
}
INTERFACE SEGREGATION PRINCIPLE
Many client-specific interfaces are better than
one general-purpose interface
Robert C. Martin
INTERFACE SEGREGATION PRINCIPLE
States that no client should be forced to depend
on methods it does not use. Thus having
multiple grained interfaces is better that one
INTERFACE SEGREGATION PRINCIPLE
// Only common generic methods exists for all
derived classes.
interface IDataProvider
{
int OpenConnection();
int CloseConnection();
}
// Implement methods specific to the respective
derived classes
interface ISqlDataProvider : IDataProvider
{
int ExecuteSqlCommand();
}
// Implement methods specific to the respective
derived classes
interface IOracleDataProvider : IDataProvider
{
int ExecuteOracleCommand();
}
// Should not force SqlDataProvider client to
implement ExecuteOracleCommand, as it wont required
that method to be implemented.
class SqlDataClient : ISqlDataProvider
{
public int OpenConnection()
{
Console.WriteLine("Sql Connection opened");
return 1;
}
public int CloseConnection()
{
Console.WriteLine("Sql Connection closed");
return 1;
}
public int ExecuteSqlCommand()
{
Console.WriteLine("Sql Server specific
Command Executed successfully");
return 1;
}
}
INTERFACE SEGREGATION PRINCIPLE
class OracleDataClient : IOracleDataProvider
{
public int OpenConnection()
{
Console.WriteLine("Oracle Connection
opened");
return 1;
}
public int CloseConnection()
{
Console.WriteLine("Oracle Connection
closed");
return 1;
}
public int ExecuteOracleCommand()
{
Console.WriteLine("Oracle specific Command
Executed successfully");
return 1;
}
}
class InterfaceSegregationPrincipleDemo
{
public static void ISPDemo()
{
Console.WriteLine("Interface Inversion
Principle Demo ");
ISqlDataProvider SqlDataProviderObject =
new SqlDataClient();
SqlDataProviderObject.OpenConnection();
SqlDataProviderObject.ExecuteSqlCommand();
SqlDataProviderObject.CloseConnection();
IOracleDataProvider OracleDataProviderObject
= new OracleDataClient();
OracleDataProviderObject.OpenConnection();
OracleDataProviderObject.ExecuteOracleCommand();
OracleDataProviderObject.CloseConnection();
}
}
DEPENDENCY INVERSION PRINCIPLE
One should depend upon abstractions, not on
concretions
Robert C. Martin
DEPENDENCY INVERSION PRINCIPLE
A. High-level modules should not depend on
low-level modules. Both should depend on
abstractions.
B. Abstractions should not depend on details.
Details should depend on abstractions.
DEPENDENCY INVERSION PRINCIPLE
public interface ITransferSource
{
long AccountNumber { get; set; }
decimal Balance { get; set; }
void RemoveFunds(decimal value);
}
public interface ITransferDestination
{
long AccountNumber { get; set; }
decimal Balance { get; set; }
void AddFunds(decimal value);
}
public class BOABankAccount :
ITransferSource,
ITransferDestination
{
public long AccountNumber { get; set; }
public decimal Balance { get; set; }
public void AddFunds(decimal value)
{
Balance += value;
}
public void RemoveFunds(decimal value)
{
Balance -= value;
}
}
DEPENDENCY INVERSION PRINCIPLE
public class TransferAmounts
{
public decimal Amount { get; set; }
public void Transfer(
ITransferSource TransferSource,
ITransferDestination TransferDestination)
{
TransferSource.RemoveFunds(Amount);
TransferDestination.AddFunds(Amount);
}
}
public class BOABankAccount :
ITransferSource,
ITransferDestination
{
public long AccountNumber { get; set; }
public decimal Balance { get; set; }
public void AddFunds(decimal value)
{
Balance += value;
}
public void RemoveFunds(decimal value)
{
Balance -= value;
}
}
INVERSION OF CONTROL PRINCIPLE
Describes a design in which custom-written
portions of a computer program receive the flow
of control from a generic, reusable library
What For?
• To decouple the execution of a task from
implementation.
• To focus a module on the task it is designed for.
• To free modules from assumptions about how
other systems do what they do and instead rely
on contracts.
• To prevent side effects when replacing a module.
Types of IoC
Dependency
Inversion
Inversion of
Control
Delegates Events
Service
Locator
Dependency
Injection
Constructor
Injection
Property
Injection
Method
Injection
DEPENDENCY INJECTION PATTERN
A software design pattern that implements
inversion of control for resolving dependencies
through:
• Constructor Injection
• Method Injection
• Property Injection
DEPENDENCY INJECTION PATTERN
Problem Solution
SERVICE LOCATOR PATTERN
A design pattern used in software development
to encapsulate the processes involved in
obtaining a service with a strong abstraction
layer.
SERVICE LOCATOR PATTERN
Problem Solution
IOC CONTAINERS
What for?
• Is responsible for creating
objects
• Is responsible for dependency
injection
• Manages lifetime of those
objects
• Removes dependencies from
your code
Concrete Implementations
• Microsoft Unity
• Castle Windsor
• Ninject
• Spring.NET
• Light Inject
• Simple Injector
SOFTWARE TESTABILITY
If your code isn't testable, then you have a
design problem
Common Sense
WHAT MAKES YOUR CODE TESTABLE ?
SRP
Since type is doing
only one job, you can
clearly understand
what should be
tested.
LSP
Since types used
can be replaced with
subtypes, mocks and
stubs can be used
instead of real types.
ISP
Since there are more
granular client-
specific interfaces,
you know exactly
what to mock.
LET’S REVIEW SOME CONCEPTS
Reusable
Higher-level components can
be reused if lower-lever
components change with time
to meet the requirements.
Extensible
Software is easily extended
with new components and
features because design is
based on abstractions.
Replaceable
Lower-level components can be
replaced to meet new
requirements without modifying
existing code.
Loosely Coupled
Allows components to perform
on their own with as little
knowledge as possible about
other components.
Cohesive
Build you software easily with
different components as
building blocks.
Testable
It is easy to understand what
and how to test in each
component because
components are loosely-
coupled.
Additional Links
http://www.csharpstar.com/solid-design-principles-c/
http://www.codeproject.com/Articles/703634/SOLID-architecture-principles-
using-simple-Csharp#Understanding%E2%80%9CS%E2%80%9D-
SRP(Singleresponsibilityprinciple).
https://code.msdn.microsoft.com/windowsapps/OOPS-Principles-SOLID-
7a4e69bf
http://programmers.stackexchange.com/questions/202571/solid-principles-and-
code-structure
eleks.com
Inspired by Technology.
Driven by Value.

More Related Content

SOLID & IoC Principles

  • 1. eleks.comeleks.com SOLID & IOC PRINCIPLES The basic principles of OOP design
  • 2. What is SOLID? The first five principles of OOP design. A set of rules on how to build an awesome application that is flexible and easy to use, understand and maintain.
  • 3. SINGLE RESPONSIBILITY PRINCIPLE A class should have only one reason to change Robert C. Martin
  • 4. SINGLE RESPONSIBILITY PRINCIPLE // Data access class is only responsible for data base related operations class DataAccess { public static void InsertData() { Console.WriteLine("Data inserted into database successfully"); } } // Data access class is only responsible for data base related operations class DataAccess { public static void InsertData() { Logger.WriteLog("Data inserted into database successfully"); } } // Logger class is only responsible for logging related operations class Logger { public static void WriteLog(string messsage) { Console.WriteLine("Logged Time:" + DateTime.Now + messsage); } }
  • 5. OPEN/CLOSED PRINCIPLE Objects or entities should be open for extension, but closed for modification Bertrand Meyer
  • 6. OPEN/CLOSED PRINCIPLE // Here DataProvider is open for extension (extends to Sql, Oracle, Oledb Providers and so on..) and closed for manipulation abstract class DataProvider { public abstract int OpenConnection(); public abstract int CloseConnection(); public abstract int ExecuteCommand(); } class SqlDataProvider : DataProvider { public override int OpenConnection() { Console.WriteLine("nSql Connection opened"); return 1; } public override int CloseConnection() { Console.WriteLine("Sql Connection closed"); return 1; } public override int ExecuteCommand() { Console.WriteLine("Sql Command Executed"); return 1; } }
  • 7. OPEN/CLOSED PRINCIPLE class OracleDataProvider : DataProvider { public override int OpenConnection() { Console.WriteLine("Oracle Connection opened"); return 1; } public override int CloseConnection() { Console.WriteLine("Oracle Connection closed"); return 1; } public override int ExecuteCommand() { Console.WriteLine("Oracle Command Executed"); return 1; } } class OpenClosePrincipleDemo { public static void OSPDemo() { Console.WriteLine("Open Close Principle"); DataProvider DataProviderObject = new SqlDataProvider(); DataProviderObject.OpenConnection(); DataProviderObject.ExecuteCommand(); DataProviderObject.CloseConnection(); DataProviderObject = new OracleDataProvider(); DataProviderObject.OpenConnection(); DataProviderObject.ExecuteCommand(); DataProviderObject.CloseConnection(); } }
  • 8. LISKOV SUBSTITUTION PRINCIPLE Let f(x) be a property of objects X of type T. Then f(y) should be true for objects Y of type S where S is a subtype of T Barbara Liskov
  • 9. LISKOV SUBSTITUTION PRINCIPLE // While implementing derived classes, one needs to ensure that, derived classes just extend the functionality of base classes without replacing the functionality of base classes. class Rectangle { protected int mWidth = 0; protected int mHeight = 0; public virtual void SetWidth(int width) { mWidth = width; } public virtual void SetHeight(int height) { mHeight = height; } public virtual int GetArea() { return mWidth * mHeight; } } // While implementing derived class if one replaces the functionality of base class then, // it might results into undesired side effects when such derived classes are used in existing program modules. class Square : Rectangle { // This class modifies the base class functionality instead of extending the base class functionality. Now below methods implementation will impact base class functionality. public override void SetWidth(int width) { mWidth = width; mHeight = width; } public override void SetHeight(int height) { mWidth = height; mHeight = height; } }
  • 10. INTERFACE SEGREGATION PRINCIPLE Many client-specific interfaces are better than one general-purpose interface Robert C. Martin
  • 11. INTERFACE SEGREGATION PRINCIPLE States that no client should be forced to depend on methods it does not use. Thus having multiple grained interfaces is better that one
  • 12. INTERFACE SEGREGATION PRINCIPLE // Only common generic methods exists for all derived classes. interface IDataProvider { int OpenConnection(); int CloseConnection(); } // Implement methods specific to the respective derived classes interface ISqlDataProvider : IDataProvider { int ExecuteSqlCommand(); } // Implement methods specific to the respective derived classes interface IOracleDataProvider : IDataProvider { int ExecuteOracleCommand(); } // Should not force SqlDataProvider client to implement ExecuteOracleCommand, as it wont required that method to be implemented. class SqlDataClient : ISqlDataProvider { public int OpenConnection() { Console.WriteLine("Sql Connection opened"); return 1; } public int CloseConnection() { Console.WriteLine("Sql Connection closed"); return 1; } public int ExecuteSqlCommand() { Console.WriteLine("Sql Server specific Command Executed successfully"); return 1; } }
  • 13. INTERFACE SEGREGATION PRINCIPLE class OracleDataClient : IOracleDataProvider { public int OpenConnection() { Console.WriteLine("Oracle Connection opened"); return 1; } public int CloseConnection() { Console.WriteLine("Oracle Connection closed"); return 1; } public int ExecuteOracleCommand() { Console.WriteLine("Oracle specific Command Executed successfully"); return 1; } } class InterfaceSegregationPrincipleDemo { public static void ISPDemo() { Console.WriteLine("Interface Inversion Principle Demo "); ISqlDataProvider SqlDataProviderObject = new SqlDataClient(); SqlDataProviderObject.OpenConnection(); SqlDataProviderObject.ExecuteSqlCommand(); SqlDataProviderObject.CloseConnection(); IOracleDataProvider OracleDataProviderObject = new OracleDataClient(); OracleDataProviderObject.OpenConnection(); OracleDataProviderObject.ExecuteOracleCommand(); OracleDataProviderObject.CloseConnection(); } }
  • 14. DEPENDENCY INVERSION PRINCIPLE One should depend upon abstractions, not on concretions Robert C. Martin
  • 15. DEPENDENCY INVERSION PRINCIPLE A. High-level modules should not depend on low-level modules. Both should depend on abstractions. B. Abstractions should not depend on details. Details should depend on abstractions.
  • 16. DEPENDENCY INVERSION PRINCIPLE public interface ITransferSource { long AccountNumber { get; set; } decimal Balance { get; set; } void RemoveFunds(decimal value); } public interface ITransferDestination { long AccountNumber { get; set; } decimal Balance { get; set; } void AddFunds(decimal value); } public class BOABankAccount : ITransferSource, ITransferDestination { public long AccountNumber { get; set; } public decimal Balance { get; set; } public void AddFunds(decimal value) { Balance += value; } public void RemoveFunds(decimal value) { Balance -= value; } }
  • 17. DEPENDENCY INVERSION PRINCIPLE public class TransferAmounts { public decimal Amount { get; set; } public void Transfer( ITransferSource TransferSource, ITransferDestination TransferDestination) { TransferSource.RemoveFunds(Amount); TransferDestination.AddFunds(Amount); } } public class BOABankAccount : ITransferSource, ITransferDestination { public long AccountNumber { get; set; } public decimal Balance { get; set; } public void AddFunds(decimal value) { Balance += value; } public void RemoveFunds(decimal value) { Balance -= value; } }
  • 18. INVERSION OF CONTROL PRINCIPLE Describes a design in which custom-written portions of a computer program receive the flow of control from a generic, reusable library
  • 19. What For? • To decouple the execution of a task from implementation. • To focus a module on the task it is designed for. • To free modules from assumptions about how other systems do what they do and instead rely on contracts. • To prevent side effects when replacing a module.
  • 20. Types of IoC Dependency Inversion Inversion of Control Delegates Events Service Locator Dependency Injection Constructor Injection Property Injection Method Injection
  • 21. DEPENDENCY INJECTION PATTERN A software design pattern that implements inversion of control for resolving dependencies through: • Constructor Injection • Method Injection • Property Injection
  • 23. SERVICE LOCATOR PATTERN A design pattern used in software development to encapsulate the processes involved in obtaining a service with a strong abstraction layer.
  • 25. IOC CONTAINERS What for? • Is responsible for creating objects • Is responsible for dependency injection • Manages lifetime of those objects • Removes dependencies from your code Concrete Implementations • Microsoft Unity • Castle Windsor • Ninject • Spring.NET • Light Inject • Simple Injector
  • 26. SOFTWARE TESTABILITY If your code isn't testable, then you have a design problem Common Sense
  • 27. WHAT MAKES YOUR CODE TESTABLE ? SRP Since type is doing only one job, you can clearly understand what should be tested. LSP Since types used can be replaced with subtypes, mocks and stubs can be used instead of real types. ISP Since there are more granular client- specific interfaces, you know exactly what to mock.
  • 28. LET’S REVIEW SOME CONCEPTS Reusable Higher-level components can be reused if lower-lever components change with time to meet the requirements. Extensible Software is easily extended with new components and features because design is based on abstractions. Replaceable Lower-level components can be replaced to meet new requirements without modifying existing code. Loosely Coupled Allows components to perform on their own with as little knowledge as possible about other components. Cohesive Build you software easily with different components as building blocks. Testable It is easy to understand what and how to test in each component because components are loosely- coupled.