Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Refactoring Applications      using SOLID Principles                       Steve Smith                           Telerik  ...
         www.devreach.com
Preventive Maintenance   • Refactoring        – Eliminate Duplication        – Simplify Design   • Automated Tests        ...
Refactoring Process   • Verify existing behavior   • Write Characterization Tests if none exist        – Find test points ...
Characterization Tests   Process   1. Write a test you know will fail   2. Use the output of the failing test to      dete...
SOLID  Principles               http://flickr.com/photos/kevinkemmerer/2772526725
Principles of OO Design   0. Don’t Repeat Yourself (DRY)   1. Single Responsibility   2. Open/Closed   3. Liskov Substitut...
Don’t Repeat   Repeat Yourself   • Duplication in logic calls for abstraction   • Duplication in process calls for     aut...
Common Refactorings   •   Replace Magic Number/String   •   Parameterize Method   •   Pull Up Field   •   Pull Up Method  ...
Role Checks    if(user.IsInRole(“Admins”)    {      // allow access to resource    }    // favor privileges over role chec...
Single Responsibility Principle   The Single Responsibility Principle states that every object     should have a single re...
Example Responsibilities   •   Persistence   •   Validation   •   Notification   •   Error Handling   •   Logging   •   Cl...
Dependency and Coupling   • Excessive coupling makes changing     legacy software difficult   • Breaking apart responsibil...
Common Refactorings   • Extract Class   • Move Methodwww.devreach.com
Heuristics and Code Smells   • Visual Studio Metricswww.devreach.com
Code Smell: Regions   More on Regions: http://ardalis.com/regional-differenceswww.devreach.com
Open / Closed Principle   The Open / Closed Principle states that software entities     (classes, modules, functions, etc....
Open / Closed Principle   Open to Extension     New behavior can be added in the future   Closed to Modification     Chang...
Common Refactorings   • Extract Interface / Apply Strategy Pattern   • Parameterize Method   • Form Template Methodwww.dev...
OCP Failwww.devreach.com
OCP Fail    public bool IsSpecialCustomer(Customer c)    {      if(c.Country == “US” && c.Balance < 50)   return   false; ...
OCP OK    private IEnumerable<ICustomerRule> _rules;    public bool IsSpecialCustomer(Customer c)    {      foreach(var ru...
Liskov Substitution Principle   The Liskov Substitution Principle states that    Subtypes must be substitutable for their ...
Common Refactorings   • Collapse Hierarchy   • Pull Up / Push Down Field   • Pull Up / Push Down Methodwww.devreach.com
Liskov Substitution Fail    foreach(var employee in employees)    {      if(employee is Manager)      {        Helpers.Pri...
Liskov Substitution OK    foreach(var employee in employees)    {      employee.Print();      // or      Helpers.PrintEmpl...
Interface Segregation Principle   The Interface Segregation Principle states that     Clients should not be forced to depe...
Common Refactorings   • Extract Interfacewww.devreach.com
ISP Fail (sometimes)    public IRepository<T>    {      T GetById(int id);      IEnumerable<T> List();      void Create(T ...
ISP OK (for CQRS for example)    public IRepository<T> : IReadRepository<T>,                             IWriteRepository<...
Dependency Inversion Principle   High-level modules should not depend on low-level     modules. Both should depend on abst...
Dependency Inversion Principle   • Depend on Abstractions        – Interfaces, not concrete types   • Inject Dependencies ...
Application Layerswww.devreach.com
Compile Time                     Runtime                   User Interface                                           ...
Compile Time                       Runtime                      User Interface                          Helper Class   ...
Compile Time                                           Runtime                                 User Interface          ...
DIP “Onion” Architecturewww.devreach.com
Common Dependencies   •   Framework                  See also responsibilities:   •   Third Party Libraries      • Persist...
Common Refactorings   •   Extract Class   •   Extract Interface / Apply Strategy Pattern   •   Extract Method   •   Introd...
DIP Failwww.devreach.com
Some Improvement (Façade)www.devreach.com
DIP OK (Strategy)www.devreach.com
DIP OK (Strategy)www.devreach.com
Summary   • Maintain / Improve Application Code   • Follow DRY/SOLID Principles   • Use Characterization Tests to “fix”   ...
                                         www.devreach.com
Thank You! – Благодаря!   Find Me Online:   Blog: http://ardalis.com   Twitter: @ardalis   http://facebook.com/StevenAndre...
www.devreach.com
Refactoring Applications using SOLID Principles
Refactoring Applications using SOLID Principles
Refactoring Applications using SOLID Principles
Refactoring Applications using SOLID Principles
Refactoring Applications using SOLID Principles
Refactoring Applications using SOLID Principles
Refactoring Applications using SOLID Principles
Refactoring Applications using SOLID Principles
Refactoring Applications using SOLID Principles
Upcoming SlideShare
Loading in …5
×

Refactoring Applications using SOLID Principles

10,845 views

Published on

We’ve all heard about well-designed software projects, where things aren’t (yet) a big ball of mud that’s painful to work with, but many of us aren’t lucky enough to work on these. Nor is it an option for us to get to start a brand new “greenfield” project, where we can leave behind the legacy of spaghetti code and technical debt our current project might have.


But there is hope! By applying refactoring steps based on SOLID principles of object oriented design, we can reduce the technical debt of our existing application, improve our code quality, and hopefully make our application more enjoyable and productive to work with.


In this session, we’ll briefly introduce the SOLID principles and several design patterns, and then we’ll apply these principles and patterns by improving the design of an existing application through several refactoring steps.

Published in: Technology

Refactoring Applications using SOLID Principles

  1. 1. Refactoring Applications using SOLID Principles Steve Smith Telerik ardalis.com @ardaliswww.devreach.com
  2. 2.    www.devreach.com
  3. 3. Preventive Maintenance • Refactoring – Eliminate Duplication – Simplify Design • Automated Tests – Verify correctness – Avoid regressions – Increase Confidencewww.devreach.com
  4. 4. Refactoring Process • Verify existing behavior • Write Characterization Tests if none exist – Find test points – Break dependencies • Apply Refactoring • Confirm existing behavior is preservedwww.devreach.com
  5. 5. Characterization Tests Process 1. Write a test you know will fail 2. Use the output of the failing test to determine the existing behavior to assert 3. Update the test with the new value/behavior 4. Run the test again – it should passwww.devreach.com
  6. 6. SOLID Principles http://flickr.com/photos/kevinkemmerer/2772526725
  7. 7. Principles of OO Design 0. Don’t Repeat Yourself (DRY) 1. Single Responsibility 2. Open/Closed 3. Liskov Substitution 4. Interface Segregation 5. Dependency Inversionwww.devreach.com
  8. 8. Don’t Repeat Repeat Yourself • Duplication in logic calls for abstraction • Duplication in process calls for automationwww.devreach.com
  9. 9. Common Refactorings • Replace Magic Number/String • Parameterize Method • Pull Up Field • Pull Up Method • Replace Conditional With Polymorphism • Introduce Methodwww.devreach.com
  10. 10. Role Checks if(user.IsInRole(“Admins”) { // allow access to resource } // favor privileges over role checks // ardalis.com/Favor-Privileges-over-Role-Checks var priv = new ContentPrivilege(user, article); if(priv.CanEdit()) { // allow access }www.devreach.com
  11. 11. Single Responsibility Principle The Single Responsibility Principle states that every object should have a single responsibility, and that responsibility should be entirely encapsulated by the class. Wikipedia There should never be more than one reason for a class to change. Robert C. “Uncle Bob” Martinwww.devreach.com
  12. 12. Example Responsibilities • Persistence • Validation • Notification • Error Handling • Logging • Class Selection / Construction • Formatting • Parsing • Mappingwww.devreach.com
  13. 13. Dependency and Coupling • Excessive coupling makes changing legacy software difficult • Breaking apart responsibilities and dependencies is a large part of working with existing codewww.devreach.com
  14. 14. Common Refactorings • Extract Class • Move Methodwww.devreach.com
  15. 15. Heuristics and Code Smells • Visual Studio Metricswww.devreach.com
  16. 16. Code Smell: Regions More on Regions: http://ardalis.com/regional-differenceswww.devreach.com
  17. 17. Open / Closed Principle The Open / Closed Principle states that software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification. Wikipediawww.devreach.com
  18. 18. Open / Closed Principle Open to Extension New behavior can be added in the future Closed to Modification Changes to source or binary code are not required Dr. Bertrand Meyer originated the OCP term in his 1988 book, Object Oriented Software Constructionwww.devreach.com
  19. 19. Common Refactorings • Extract Interface / Apply Strategy Pattern • Parameterize Method • Form Template Methodwww.devreach.com
  20. 20. OCP Failwww.devreach.com
  21. 21. OCP Fail public bool IsSpecialCustomer(Customer c) { if(c.Country == “US” && c.Balance < 50) return false; if(c.Country == “DE” && c.Balance < 25) return false; if(c.Country == “UK” && c.Balance < 35) return false; if(c.Country == “FR” && c.Balance < 27) return false; if(c.Country == “BG” && c.Balance < 29) return false; if(c.Age < 18 || c.Age > 65) return false; if(c.Income < 50000 && c.Age < 30) return false; return true; }www.devreach.com
  22. 22. OCP OK private IEnumerable<ICustomerRule> _rules; public bool IsSpecialCustomer(Customer c) { foreach(var rule in _rules) { if(rule.Evaluate(c) == false) return false; } return true; }www.devreach.com
  23. 23. Liskov Substitution Principle The Liskov Substitution Principle states that Subtypes must be substitutable for their base types. Agile Principles, Patterns, and Practices in C# Named for Barbara Liskov, who first described the principle in 1988.www.devreach.com
  24. 24. Common Refactorings • Collapse Hierarchy • Pull Up / Push Down Field • Pull Up / Push Down Methodwww.devreach.com
  25. 25. Liskov Substitution Fail foreach(var employee in employees) { if(employee is Manager) { Helpers.PrintManager(employee as Manager); break; } Helpers.PrintEmployee(employee); }www.devreach.com
  26. 26. Liskov Substitution OK foreach(var employee in employees) { employee.Print(); // or Helpers.PrintEmployee(employee); }www.devreach.com
  27. 27. Interface Segregation Principle The Interface Segregation Principle states that Clients should not be forced to depend on methods they do not use. Agile Principles, Patterns, and Practices in C# Corollary: Prefer small, cohesive interfaces to “fat” interfaceswww.devreach.com
  28. 28. Common Refactorings • Extract Interfacewww.devreach.com
  29. 29. ISP Fail (sometimes) public IRepository<T> { T GetById(int id); IEnumerable<T> List(); void Create(T item); void Update(T item); void Delete(T item); }www.devreach.com
  30. 30. ISP OK (for CQRS for example) public IRepository<T> : IReadRepository<T>, IWriteRepository<T> { } public IReadRepository<T> { T GetById(int id); IEnumerable<T> List(); } public IWriteRepository<T> void Create(T item); void Update(T item); void Delete(T item); }www.devreach.com
  31. 31. Dependency Inversion Principle High-level modules should not depend on low-level modules. Both should depend on abstractions. Abstractions should not depend on details. Details should depend on abstractions. Agile Principles, Patterns, and Practices in C#www.devreach.com
  32. 32. Dependency Inversion Principle • Depend on Abstractions – Interfaces, not concrete types • Inject Dependencies into Classes • Structure Solution so Dependencies Flow Toward Core – Onion Architecturewww.devreach.com
  33. 33. Application Layerswww.devreach.com
  34. 34. Compile Time Runtime User Interface       Databasewww.devreach.com
  35. 35. Compile Time Runtime  User Interface   Helper Class  Databasewww.devreach.com
  36. 36. Compile Time Runtime  User Interface   Core Infrastructure IFooRepository SqlFooRepository    Databasewww.devreach.com
  37. 37. DIP “Onion” Architecturewww.devreach.com
  38. 38. Common Dependencies • Framework See also responsibilities: • Third Party Libraries • Persistence • Validation • Database • Notification • File System • Error Handling • Email • Logging • Web Services • Class Selection / Construction • System Resources (Clock) • Formatting • Configuration • Parsing • The new Keyword • Mapping • Static methods • Thread.Sleep • Randomwww.devreach.com
  39. 39. Common Refactorings • Extract Class • Extract Interface / Apply Strategy Pattern • Extract Method • Introduce Service Locator / Containerwww.devreach.com
  40. 40. DIP Failwww.devreach.com
  41. 41. Some Improvement (Façade)www.devreach.com
  42. 42. DIP OK (Strategy)www.devreach.com
  43. 43. DIP OK (Strategy)www.devreach.com
  44. 44. Summary • Maintain / Improve Application Code • Follow DRY/SOLID Principles • Use Characterization Tests to “fix” behavior • Apply Common Refactorings • Re-run Tests After Refactoringswww.devreach.com
  45. 45.        www.devreach.com
  46. 46. Thank You! – Благодаря! Find Me Online: Blog: http://ardalis.com Twitter: @ardalis http://facebook.com/StevenAndrewSmithwww.devreach.com
  47. 47. www.devreach.com

×