The document discusses the SOLID principles of object-oriented design, which are Single Responsibility Principle, Open Closed Principle, Liskov Substitution Principle, Interface Segregation Principle, and Dependency Inversion Principle. For each principle, it provides an example of how to apply the principle correctly and how violations of the principle can occur if it is not followed. It also lists some recommended reading materials on software design patterns and principles.
5. Single Responsibility
Principle
There should be one and only one
reason for a class to change.
6. SRP Violation
public class UserSettingService
{
  public void changeEmail(User user)
  {
    if(checkAccess(user))
    {
       //Grant option to change
    }
  }
  public boolean checkAccess(User user)
  {
    //Verify if the user is valid.
  }
}
7. SRP Restored
public class UserSettingService
{
  public void changeEmail(User user)
  {
    if(SecurityService.checkAccess(user))
    {
       //Grant option to change
    }
  }
}
public class SecurityService
{
  public static boolean checkAccess(User user)
  {
    //check the access.
  }
}
11. Class Responsibility
The classesâ responsibility is to filter
products (its job) based off the action of
filtering by colour (its behaviour).
The ProductFilter is responsible for
filtering products by colour.
12. Filter By Colour
public class ProductFilter
{
public IEnumerable<Product> ByColor(IList<Product> products, ProductColor productColor)
{
foreach (var product in products)
{
if (product.Color == productColor)
yield return product;
}
}
}
13. More Requirements!
User: We also need to filter by size.
Developer: Just size or colour and size?
User: Umm probably both.
Developer: Great!
14. Filter By Colour
The ProductFilter is responsible
for filtering products by colour,
size, colour and size.
15. public class ProductFilter
{
{
Filter By Colour
public IEnumerable<Product> ByColor(IList<Product> products, ProductColor productColor)
foreach (var product in products)
{
if (product.Color == productColor)
yield return product;
}
}
public IEnumerable<Product> ByColorAndSize(IList<Product> products,
ProductColor productColor,
ProductSize productSize)
{
foreach (var product in products)
{
if ((product.Color == productColor) &&
(product.Size == productSize))
yield return product;
}
}
public IEnumerable<Product> BySize(IList<Product> products,
ProductSize productSize)
{
foreach (var product in products)
{
if ((product.Size == productSize))
yield return product;
}
}
}
16. OCP Filter
public abstract class ProductFilterSpeciïŹcation
{
public IEnumerable<Product> Filter(IList<Product> products)
{
return ApplyFilter(products);
}
protected abstract IEnumerable<Product> ApplyFilter(IList<Product> products);
}
public class ProductFilter
{
public IEnumerable<Product> By(IList<Product> products, ProductFilterSpeciïŹcation
ïŹlterSpeciïŹcation)
{
return ïŹlterSpeciïŹcation.Filter(products);
}
}
17. OCP Filter
public class ColorFilterSpeciïŹcation : ProductFilterSpeciïŹcation
{
private readonly ProductColor productColor;
public ColorFilterSpeciïŹcation(ProductColor productColor)
{
this.productColor = productColor;
}
protected override IEnumerable<Product> ApplyFilter(IList<Product> products)
{
foreach (var product in products)
{
if (product.Color == productColor)
yield return product;
}
}
}
18.
19. Liskov Substitution
Principle
Functions that use references to base
classes must be able to use objects of
derived classes without knowing it.
20. LSP Violation
class Rectangle
{
! protected int m_width;
! protected int m_height;
! public void setWidth(int width){
! ! m_width = width;
! }
! public void setHeight(int height){
! ! m_height = height;
! }
! public int getWidth(){
! ! return m_width;
! }
! public int getHeight(){
! ! return m_height;
! }
! public int getArea(){
! ! return m_width * m_height;
! }!
}
22. LSP Violation
class LspTest
{
! private static Rectangle getNewRectangle()
! {
! ! // it can be an object returned by some factory ...
! ! return new Square();
! }
! public static void main (String args[])
! {
! ! Rectangle r = LspTest.getNewRectangle();
! ! r.setWidth(5);
! ! r.setHeight(10);
! ! // user knows that r it's a rectangle.
! ! // It assumes that he's able to set the width and height as for the base class
! ! System.out.println(r.getArea());
! ! // now he's surprised to see that the area is 100 instead of 50.
! }
}
23.
24. Interface Segregation
Principle
Clients should not be forced to depend
on interfaces that they do not use.
25. ISP Example
public abstract class Animal
{
public abstract void Feed();
}
public class Dog : Animal
{
public override void Feed()
{
// do something
}
}
public class Rattlesnake : Animal
{
public override void Feed()
{
// do something
}
}
26. ISP Violation
public abstract class Animal
{
public abstract void Feed();
public abstract void Groom();
}
public class Rattlesnake : Animal
{
public override void Feed()
{
// do something
}
public override void Groom()
{
// ignore
}
}
27. ISP Restored
public interface IPet
{
void Groom();
}
public abstract class Animal
{
public abstract void Feed();
}
public class Dog : Animal, IPet
{
public override void Feed()
{
// do something
}
public void Groom()
{
// do something
}
}
public class Rattlesnake : Animal
{
public override void Feed()
{
// do something
}
28. Handout
public class CustomMembershipProvider : MembershipProvider
{
public override string ApplicationName
{
get
{
throw new Exception("The method or operation is not implemented.");
}
set
{
throw new Exception("The method or operation is not implemented.");
}
}
public override bool ChangePassword(string username, string oldPassword, string
newPassword)
{
throw new Exception("The method or operation is not implemented.");
}
public override bool ChangePasswordQuestionAndAnswer(string username, string
29.
30. Dependency Inversion
Principle
High level modules should not depend
upon low level modules. Both should
depend upon abstractions.
Abstractions should not depend upon
details. Details should depend upon
abstractions.
31. DIP Violation
public class OrderProcessor
{
public decimal CalculateTotal(Order order)
{
decimal itemTotal = order.GetItemTotal();
decimal discountAmount = DiscountCalculator.CalculateDiscount(order);
decimal taxAmount = 0.0M;
if (order.Country == "US")
taxAmount = FindTaxAmount(order);
else if (order.Country == "UK")
taxAmount = FindVatAmount(order);
decimal total = itemTotal - discountAmount + taxAmount;
return total;
}
private decimal FindVatAmount(Order order)
{
// find the UK value added tax somehow
return 10.0M;
}
private decimal FindTaxAmount(Order order)
{
// find the US tax somehow
return 10.0M;
}
}
33. DIP Restored
public class DiscountCalculatorAdapter : IDiscountCalculator
{
public decimal CalculateDiscount(Order order)
{
return DiscountCalculator.CalculateDiscount(order);
}
}
public class USTaxStrategy : ITaxStrategy
{
public decimal FindTaxAmount(Order order)
{
}
}
public class UKTaxStrategy : ITaxStrategy
{
public decimal FindTaxAmount(Order order)
{
}
}
34. Reading
Clean Code: A Handbook of Agile Software
Craftsmanship Robert C. Martin
Design Patterns: Elements of Reusable Object-Oriented
Software Erich Gamma, Richard Helm, Ralph Johnson,
and John Vlissides
Agile Principles, Patterns and Practices in C#
Robert C. Martin
Lean Architecture: for Agile Software Development
James O. Coplien and Gertrud BjĂžrnvig
35. Photo Credits
SOLID Motivational Posters, by Derick Bailey, is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.
http://lostechies.com/derickbailey/ïŹles/2011/03/SOLID_6EC97F9C.jpg
http://lostechies.com/derickbailey/ïŹles/2011/03/SingleResponsibilityPrinciple2_71060858.jpg
http://lostechies.com/derickbailey/ïŹles/2011/03/OpenClosedPrinciple2_2C596E17.jpg
http://lostechies.com/derickbailey/ïŹles/2011/03/LiskovSubtitutionPrinciple_52BB5162.jpg
http://lostechies.com/derickbailey/ïŹles/2011/03/InterfaceSegregationPrinciple_60216468.jpg
http://lostechies.com/derickbailey/ïŹles/2011/03/DependencyInversionPrinciple_0278F9E2.jpg