SOLID & IoC Principles
-
Upload
pavlo-hodysh -
Category
Software
-
view
73 -
download
2
Transcript of SOLID & IoC Principles
eleks.com eleks.com
SOLID & IOC PRINCIPLESThe 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 PRINCIPLEA 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 PRINCIPLEObjects 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 PRINCIPLEclass 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 PRINCIPLELet 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 PRINCIPLEMany client-specific interfaces are better than one general-purpose interface
Robert C. Martin
INTERFACE SEGREGATION PRINCIPLEStates 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 PRINCIPLEclass 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 PRINCIPLEOne should depend upon abstractions, not on concretions
Robert C. Martin
DEPENDENCY INVERSION PRINCIPLEA. 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 PRINCIPLEpublic 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 PRINCIPLEpublic 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 PRINCIPLEDescribes 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 IoCDependency
Inversion
Inversion of Control
Delegates Events Service Locator
Dependency Injection
Constructor Injection
Property Injection
Method Injection
DEPENDENCY INJECTION PATTERNA software design pattern that implements inversion of control for resolving dependencies through:
• Constructor Injection• Method Injection• Property Injection
DEPENDENCY INJECTION PATTERNProblem Solution
SERVICE LOCATOR PATTERNA design pattern used in software development to encapsulate the processes involved in obtaining a service with a strong abstraction layer.
SERVICE LOCATOR PATTERNProblem Solution
IOC CONTAINERSWhat 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 TESTABILITYIf 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 CONCEPTSReusableHigher-level components can be reused if lower-lever components change with time to meet the requirements.
ExtensibleSoftware is easily extended with new components and features because design is based on abstractions.
ReplaceableLower-level components can be replaced to meet new requirements without modifying existing code.
Loosely CoupledAllows components to perform on their own with as little knowledge as possible about other components.
CohesiveBuild you software easily with different components as building blocks.
TestableIt is easy to understand what and how to test in each component because components are loosely-coupled.
Additional Linkshttp://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-7a4e69bfhttp://programmers.stackexchange.com/questions/202571/solid-principles-and-code-structure
eleks.com
Inspired by Technology.Driven by Value.