Refactoring with SOLID Principles (FalafelCon 2013)

Click here to load reader

  • date post

  • Category


  • view

  • download


Embed Size (px)


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.

Transcript of Refactoring with SOLID Principles (FalafelCon 2013)

  • 1. Follow me at Applicationsusing SOLID PrinciplesSteve @ardalis

2. Follow me at on this topicComing Soon: Refactoring Fundamentals 3. Follow me at 4. Follow me at Maintenance Refactoring Eliminate Duplication Simplify Design Automated Tests Verify correctness Avoid regressions Increase Confidence 5. Follow me at Process Verify existing behavior Write Characterization Tests if none exist Find test points Break dependencies Apply Refactoring Confirm existing behavior is preserved 6. Follow me at TestsProcess1. Write a test you know will fail2. Use the output of the failing test todetermine the existing behavior to assert3. Update the test with the newvalue/behavior4. Run the test again it should pass 7. S O L I DPrinciples 8. Follow me at of OO Design0. Dont Repeat Yourself (DRY)1. Single Responsibility2. Open/Closed3. Liskov Substitution4. Interface Segregation5. Dependency Inversion 9. Follow me at RepeatRepeat Yourself Duplication in logic calls for abstraction Duplication in process calls forautomation 10. Follow me at Refactorings Replace Magic Number/String Parameterize Method Pull Up Field Pull Up Method Replace Conditional With Polymorphism Introduce Method 11. Follow me at Checksif(user.IsInRole(Admins){// allow access to resource}// favor privileges over role checks// priv = new ContentPrivilege(user, article);if(priv.CanEdit()){// allow access} 12. Follow me at Responsibility PrincipleThe Single Responsibility Principle states that every objectshould have a single responsibility, and thatresponsibility should be entirely encapsulated by theclass.WikipediaThere should never be more than one reason for a class tochange.Robert C. Uncle Bob Martin 13. Follow me at Responsibilities Persistence Validation Notification Error Handling Logging Class Selection / Construction Formatting Parsing Mapping 14. Follow me at and Coupling Excessive coupling makes changinglegacy software difficult Breaking apart responsibilities anddependencies is a large part of workingwith existing code 15. Follow me at Refactorings Extract Class Move Method 16. Follow me at and Code Smells Visual Studio Metrics 17. Follow me at Smell: RegionsMore on Regions: 18. Follow me at / Closed PrincipleThe Open / Closed Principle states that software entities(classes, modules, functions, etc.) should be open forextension, but closed for modification.Wikipedia 19. Follow me at / Closed PrincipleOpen to ExtensionNew behavior can be added in the futureClosed to ModificationChanges to source or binary code are not requiredDr. Bertrand Meyer originated the OCP term in his 1988book, Object Oriented Software Construction 20. Follow me at Refactorings Extract Interface / Apply Strategy Pattern Parameterize Method Form Template Method 21. Follow me at Fail 22. Follow me at OK 23. Follow me at Failpublic 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;} 24. Follow me at OKprivate IEnumerable _rules;public bool IsSpecialCustomer(Customer c){foreach(var rule in _rules){if(rule.Evaluate(c) == false) return false;}return true;} 25. Follow me at Substitution PrincipleThe Liskov Substitution Principle states thatSubtypes must be substitutable for theirbase types.Agile Principles, Patterns, and Practices inC#Named for Barbara Liskov, who firstdescribed the principle in 1988. 26. Follow me at Refactorings Collapse Hierarchy Pull Up / Push Down Field Pull Up / Push Down Method 27. Follow me at Substitution Failforeach(var employee in employees){if(employee is Manager){Helpers.PrintManager(employee as Manager);break;}Helpers.PrintEmployee(employee);} 28. Follow me at Substitution OKforeach(var employee in employees){employee.Print();// orHelpers.PrintEmployee(employee);} 29. Follow me at Segregation PrincipleThe Interface Segregation Principle states thatClients should not be forced to depend onmethods they do not use.Agile Principles, Patterns, and Practices in C#Corollary:Prefer small, cohesive interfaces to fat interfaces 30. Follow me at Refactorings Extract Interface 31. Follow me at Fail (sometimes)public IRepository{T GetById(int id);IEnumerable List();void Create(T item);void Update(T item);void Delete(T item);} 32. Follow me at OK (for CQRS for example)public IRepository : IReadRepository,IWriteRepository{ }public IReadRepository{T GetById(int id);IEnumerable List();}public IWriteRepositoryvoid Create(T item);void Update(T item);void Delete(T item);} 33. Follow me at Inversion PrincipleHigh-level modules should not depend on low-levelmodules. Both should depend on abstractions.Abstractions should not depend on details. Detailsshould depend on abstractions.Agile Principles, Patterns, and Practices in C# 34. Follow me at Inversion Principle Depend on Abstractions Interfaces, not concrete types Inject Dependencies into Classes Structure Solution so Dependencies FlowToward Core Onion Architecture 35. Follow me at Layers 36. Follow me at InterfaceDatabaseCompile TimeRuntime 37. Follow me at InterfaceDatabaseCompile TimeRuntimeHelper Class 38. Follow me at InterfaceDatabaseCompile TimeRuntimeCoreIFooRepositoryInfrastructureSqlFooRepository 39. Follow me at Onion Architecture 40. Follow me at Dependencies Framework Third Party Libraries Database File System Email Web Services System Resources (Clock) Configuration The new Keyword Static methods Thread.Sleep RandomSee also responsibilities: Persistence Validation Notification Error Handling Logging Class Selection /Construction Formatting Parsing Mapping 41. Follow me at Refactorings Extract Class Extract Interface / Apply Strategy Pattern Extract Method Introduce Service Locator / Container 42. Follow me at Fail 43. Follow me at Improvement (Faade) 44. Follow me at OK (Strategy) 45. Follow me at OK (Strategy) 46. Follow me at Maintain / Improve Application Code Follow DRY/SOLID Principles Use Characterization Tests to fixbehavior Apply Common Refactorings Re-run Tests After (and during)Refactorings 47. Follow me at 48. Follow me at 49. Follow me at You!Find Me Online:Blog: http://ardalis.comTwitter: @ardalis 50. Follow me at