SOLID Principles of Refactoring Presentation - Inland Empire User Group

108
REFACTORING CODE TO A SOLID FOUNDATION Adnan Masood http://blog.adnanmasood.com @adnanmasood [email protected] Presented at Inland Empire .NET UG – 12/11/2012 Slides Courtesy of Steve Smith Pluralsight and Derick Bailey, Los Techies

description

Abstract: SOLID is a mnemonic acronym coined by Robert C. Martin (aka Uncle Bob) referring to a collection of design principles of object-oriented programming and design. By using these principles, developers are much more likely to create a system that more maintainable and extensible. SOLID can be used to remove code smells by refactoring. In this session, you will learn about the following SOLID principles with code examples demonstrating the corresponding refactoring. S – Single Responsibility Principle – An Object should have only one reason to change. O – Open/Closed Principle – A software entity(module, library, routine) should be closed to any modification but be open to extension L – Liskov Substitution Principle – Derived classes should be substitutable for the base classes I – Interface Segregation Principle – Having more fine grained interfaces over fat interfaces D – Dependency Inversion Principle – Depending on abstractions, not concrete implementations.

Transcript of SOLID Principles of Refactoring Presentation - Inland Empire User Group

  • 1.REFACTORING CODE TO A SOLIDFOUNDATIONAdnan Masoodhttp://blog.adnanmasood.com@[email protected] at Inland Empire .NETUG 12/11/2012Slides Courtesy of Steve Smith Pluralsight and Derick Bailey, Los Techies

2. E X A MP L E A P P : B E F O R E A N DAFTEROR HOW TO GET FROM HERE TOTHERE? Before AfterCourtesy Steve Smith, PluralSight Training - SOLID Principles of Object Oriented Design 3. CREDITS & REFERENCES Robert C Martin Clean Coder https://sites.google.com/site/unclebobconsultingllc/ Pablos SOLID Software Development | LosTechies.comDerick Bailey - McLane Advanced Technologies, LLC PluralSight Training - SOLID Principles of Object Oriented Designhttp://pluralsight.com/training/Courses/TableOfContents/principles-oo-design Marcin Zajczkowski - http://solidsoft.wordpress.com/ Images Used Under License http://www.lostechies.com/blogs/derickbailey/archive/2009/02/11/solid-development-principles-in-motivational-pictures.aspx SRP Article http://www.objectmentor.com/resources/articles/srp.pdf Solid for your Language http://stefanroock.files.wordpress.com/2011/09/solidforyourlanguage.pdf 4. HELP : ABOUTAdnan Masood works as a system architect / technical lead for Green dot Corporation where hedevelops SOA based middle-tier architectures, distributed systems, and web-applications usingMicrosoft technologies. He is a Microsoft Certified Trainer holding several technicalcertifications, including MCPD (Enterprise Developer), MCSD .NET, and SCJP-II. Adnan isattributed and published in print media and on the Web; he also teaches WindowsCommunication Foundation (WCF) courses at the University of California at San Diego andregularly presents at local code camps and user groups. He is actively involved in the .NETcommunity as cofounder and president of the of San Gabriel Valley .NET Developers group.Adnan holds a Masters degree in Computer Science; he is currently a doctoral student workingtowards PhD in Machine Learning; specifically discovering interestingness measures in outliersusing Bayesian Belief Networks. He also holds systems architecture certification from MIT andSOA Smarts certification from Carnegie Melon University. 5. ADDITIONAL RESOURCESUncle Bobs Principle Of Object Oriented Development: http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOodPablos Topic Of The Month: SOLIDhttp://www.lostechies.com/blogs/chad_myers/archive/2008/03/07/pablo-s-topic-of-the-month-march-solid-principles.aspxAgile Principles, Patterns, And Practices In C#by Robert (Uncle Bob) Martin and Micah MartinPablos SOLID E-Book http://www.lostechies.com/content/pablo_ebook.aspx 6. OBJECT ORIENTED PRINCIPLES -QUIZ COHESION: A measure of how strongly-related and focused the various responsibilities of a software module are - Wikipedia COUPLING: The degree to which each program module relies on each one of the other modules WikipediaENCAPSULATION: The hiding of design decisions in a computer program that are most likely to change - Wikipedia 7. S.O.L.I.D. PRINCIPLESSRP: SINGLE RESPONSIBILITY PRINCIPLEOCP: OPEN CLOSED PRINCIPLE LSP: LISKOV SUBSTITUTION PRINCIPLE ISP: INTERFACE SEGREGATION PRINCIPLE DIP: DEPENDENCY INVERSION PRINCIPLE 8. THE SINGLE RESPONSIBILITYPRINCIPLE 9. SRP: THE SINGLE RESPONSIBILITYPRINCIPLEThe Single Responsibility Principle states that every objectshould have a single responsibility, and that responsibilityshould be entirely encapsulated by the class. WikipediaThere should never be more than one reason for a class tochange. Robert C. Uncle Bob Martin 10. COHESION AND COUPLING Cohesion: how strongly-related and focused are the various responsibilities of a module Coupling: the degree to which each program module relies on each one of the other modulesStrive for low coupling and highcohesion! 11. RESPONSIBILITIES ARE AXES OFCHANGE Requirements changes typically map to responsibilities More responsibilities == More likelihood of change Having multiple responsibilities within a class couplestogether these responsibilities The more classes a change affects, the more likelythe change will introduce errors. 12. DemoThe Problem With Too ManyResponsibilities 13. WHAT IS A RESPONSIBILITY?a reason to changeA difference in usage scenarios from the clients perspectiveMultiple small interfaces (follow ISP) can help to achieve SRP 14. SRP: SINGLERESPONSIBILITYFILE AND SEND AN EMAILEXAMPLE APP: READ A FLAT 15. SRP: SINGLE RESPONSIBILITYEXAMPLE APP NEW REQUIREMENTS: SEND FROM NON -WINFORMS APP. READ XML ORFLAT FILE 16. EXAMPLE APP: A BETTER STRUCTURE 17. SUMMARY Following SRP leads to lower coupling and higher cohesion Many small classes with distinct responsibilities result in a moreflexible design Related Fundamentals: o Open/Closed Principle o Interface Segregation Principle o Separation of Concerns Recommended Reading: o Clean Code by Robert C. Martin [http://amzn.to/Clean-Code] 18. THE OPEN / CLOSED PRINCIPLE 19. OCP: THE OPEN/CLOSED PRINCIPLEThe Open / Closed Principle states that software entities (classes, modules, functions, etc.) should be open for extension, but closed for modificationWikipedia 20. THE OPEN / 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 21. CHANGE BEHAVIOR WITHOUTCHANGING CODE?Rely on abstractionsNo limit to variety of implementations of each abstractionIn .NET, abstractions include: Interfaces Abstract Base ClassesIn procedural code, some level of OCP can beachieved via parameters 22. THE PROBLEM Adding new rules require changes to the calculator every time Each change can introduce bugs and requires re-testing, etc. We want to avoid introducing changes that cascade throughmany modules in our application Writing new classes is less likely to introduce problems o Nothing depends on new classes (yet) o New classes have no legacy coupling to make them hard to design or test 23. THREE APPROACHES TO ACHIEVEOCP Parameters (Procedural Programming) o Allow client to control behavior specifics via a parameter o Combined with delegates/lambda, can be very powerful approach Inheritance / Template Method Pattern o Child types override behavior of a base class (or interface) Composition / Strategy Pattern o Client code depends on abstraction o Provides a plug in model o Implementations utilize Inheritance; Client utilizes Composition 24. WHEN DO WE APPLY OCP? Experience Tells You If you know from your own experience in the problem domain that a particular class of change is likely to recur, you can apply OCP up front in your designOtherwise Fool me once, shame on you; fool me twice, shame on me Dont apply OCP at first If the module changes once, accept it. If it changes a second time, refactor to achieve OCPRemember TANSTAAFL There Aint No Such Thing As A Free Lunch OCP adds complexity to design No design can be closed against all changes 25. SUMMARY Conformance to OCP yields flexibility, reusability, and maintainability Know which changes to guard against, and resist premature abstraction Related Fundamentals: o Single Responsibility Principle o Strategy Pattern o Template Method Pattern Recommended Reading: o Agile Principles, Patterns, and Practices by Robert C. Martin and Micah Martin [http://amzn.to/agilepppcsharp] 26. THE LISKOV SUBSTITUTIONPRINCIPLE 27. LSP: THE LISKOV SUBSTITUTIONPRINCIPLEThe Liskov Substitution Principle states thatSubtypes must be substitutable for their basetypes. Agile Principles, Patterns, and Practices in C#Named for Barbara Liskov, who first described the principle in 1988. 28. SUBSTITUTABILITYChild classes must not:1) Remove base class behavior2) Violate base class invariantsAnd in general must not require calling code to know they aredifferent from their base type. 29. INHERITANCE AND THE IS-ARELATIONSHIPNave OOP teaches use of IS-A to describe child classesrelationship to base classesLSP suggests that IS-A should be replaced withIS-SUBSTITUTABLE-FOR 30. LSP: LISKOV SUBSTITUTIONPRINCIPLEEXAMPLE APP: VIOLATING LSP WITH DATABASE CONNECTION INFO 31. LSP: LISKOV SUBSTITUTIONPRINCIPLE EXAM PL E APP: CO RRECTI NG FO R LSP M O VE THE DAT AB A SE RE ADE R 32. INVARIANTS Consist of reasonable assumptions of behavior by clients Can be expressed as preconditions and postconditions for methods Frequently, unit tests are used to specify expected behavior of amethod or class Design By Contract is a technique that makes defining these pre- andpost-conditions explicit within code itself. To follow LSP, derived classes must not violate any constraints defined(or assumed by clients) on the base classes 33. THE PROBLEM Non-substitutable code breaks polymorphism Client code expects child classes to work in place of their base classes Fixing substitutability problems by adding if- then or switch statements quickly becomes a maintenance nightmare (and violates OCP) 34. LSP VIOLATION SMELLSforeach (var emp in Employees){if( emp is Manager ){ _printer.PrintManager( emp as Manager );}else{ _printer.PrintEmployee( emp );}} 35. LSP VIOLATION SMELLSpublic abstract class Base{ Follow ISP!public abstract void Method1();public abstract void Method2();Use small interfaces so you} dont require classes topublic class Child : Base implement more than they{ need!public override void Method1(){ throw new NotImplementedException();}public override void Method2(){// do stuff}} 36. WHEN DO WE FIX LSP?If you notice obvious smells like those shownIf you find yourself being bitten by the OCP violations LSP invariably causes 37. LSP TIPS Tell, Dont Ask o Dont interrogate objects for their internals move behavior to the object o Tell the object what you want it to do Consider Refactoring to a new Base Class o Given two classes that share a lot of behavior but are not substitutable o Create a third class that both can derive from o Ensure substitutability is retained between each class and the new base 38. SUMMARY Conformance to LSP allows for proper use of polymorphism and produces moremaintainable code Remember IS-SUBSTITUTABLE-FOR instead of IS-A Related Fundamentals:o Polymorphismo Inheritanceo Interface Segregation Principleo Open / Closed Principle Recommended Reading:o Agile Principles, Patterns, and Practices by Robert C. Martin and Micah Martin[http://amzn.to/agilepppcsharp] 39. THE INTERFACE SEGREGATIONPRINCIPLE 40. ISP: THE INTERFACE SEGREGATIONPRINCIPLEThe Interface Segregation Principle statesthat Clients should not be forced to dependon methods they do not use.Agile Principles, Patterns, and Practices in C#Corollary:Prefer small, cohesive interfaces to fat interfaces 41. WHATS AN INTERFACE?Interface keyword/type public interface IDoSomething { }Public interface of a class public class SomeClass { }What does the client see and use? 42. ISP: INTERFACESEGREGATION THE DISADVANTAGES OF THIS PRINCIPLE DEALS WITHPRINCIPLECLASSES CLASSESINTERFACES FAT FAT INTERFACES. INTERFACES AREWHOSE THAT HAVE ARENOT COHESIVE. IN OTHER WORDS, THE INTERFACESOF THE CLASS CAN BE BROKEN UP INTO GROUPS OFMEMBER FUNCTIONS. EACH GROUP SERVES ADIFFERENT SET OF CLIENTS. THUS SOME CLIENTS USE ONE GROUP OF MEMBER FUNCTIONS, AND OTHER CLIENTS USE THE OTHER GROUPS.- ROBERT MARTIN 43. Demo 44. ISP: INTERFACESEGREGATIONPRINCIPLEEXAMPLE APP: CLARIFYING THE EMAIL SENDER AND MESSAGE INFOPARSING 45. THE PROBLEMClient Class (Login Control) Needs This: 46. THE PROBLEM AboutPage simply needs ApplicationName and AuthorName Forced to deal with huge ConfigurationSettings class Forced to deal with actual configuration filesInterface Segregation violations result in classes that depend onthings they do not need, increasing coupling and reducingflexibility and maintainability 47. ISP SMELLS Unimplemented interface methods:public override string ResetPassword( string username, string answer) { throw new NotImplementedException(); }Remember these violate Liskov Substitution Principle! 48. ISP SMELLSClient references a class but only uses small portion of it 49. WHEN DO WE FIX ISP? Once there is pain o If there is no pain, theres no problem to address. If you find yourself depending on a fat interface you own o Create a smaller interface with just what you need o Have the fat interface implement your new interface o Reference the new interface with your code If you find fat interfaces are problematic but you do not own them o Create a smaller interface with just what you need o Implement this interface using an Adapter that implements the fullinterface 50. ISP TIPS Keep interfaces small, cohesive, and focused Whenever possible, let the client define the interfaceWhenever possible, package theinterface with the client o Alternately, package in a third assembly client and implementation both depend upon o Last resort: Package interfaces with their implementation 51. SUMMARY Dont force client code to depend on things it doesntneed Keep interfaces lean and focused Refactor large interfaces so they inherit smaller interfaces Related Fundamentals: o Polymorphism o Inheritance o Liskov Substitution Principle o Faade Pattern Recommended Reading: o Agile Principles, Patterns, and Practices by Robert C. Martin and Micah Martin [http://amzn.to/agilepppcsharp] 52. THE DEPENDENCY INVERSIONPRINCIPLE 53. DIP: DEPENDENCY INVERSIONPRINCIPLE WHAT IS IT THAT MAKES A DESIGN RIGID, FRAGILE AND IMMOBILE? IT IS THE INTERDEPENDENCE OF THE MODULES WITHIN THAT DESIGN. A DESIGN IS RIGID IF IT CANNOT BE EASILY CHANGED. SUCH RIGIDITY IS DUE TO THE FACT THAT A SINGLE CHANGE TO HEAVILYINTERDEPENDENT SOFTWARE BEGINS A CASCADE OF CHANGES INDEPENDENT MODULES.- ROBERT MARTIN 54. DIP: THE DEPENDENCY INVERSIONPRINCIPLEHigh-level modules should not depend onlow-level modules. Both should depend onabstractions.Abstractions should not depend on details.Details should depend on abstractions.o Agile Principles, Patterns, and Practices in C# 55. DIP: DEPENDENCYINVERSIONPRINCIPLE 56. DIP: DEPENDENCYINVERSIONPRINCIPLE 57. DIP: DEPENDENCYINVERSIONPRINCIPLE 58. DIP:DEPENDENCYINVERSIONPRINCIPLE 59. DIP:DEPENDENCYINVERSIONPRINCIPLEEXAMPLE APP: CONSTRUCTOR DEPENDENCIES IN A PROCESSING SERVICE 60. WHAT ARE DEPENDENCIES? Framework Third Party Libraries Database File System Email Web Services System Resources (Clock) Configuration The new Keyword Static methods Thread.Sleep Random 61. TRADITIONAL PROGRAMMING ANDDEPENDENCIES High Level Modules Call Low Level Modules User Interface depends ono Business Logic depends ono Infrastructureo Utilityo Data Access Static methods are used for convenience or as Faade layers Class instantiation / Call stack logic is scattered through all moduleso Violation of Single Responsibility Principle 62. CLASS DEPENDENCIES: BE HONEST! Class constructors should require any dependencies the class needs Classes whose constructors make this clear have explicit dependencies Classes that do not have implicit, hidden dependencies public class HelloWorldHidden { public string Hello(string name) {if (DateTime.Now.Hour < 12) return "Good morning, " + name; if (DateTime.Now.Hour < 18) return "Good afternoon, " + name; return "Good evening, " + name; } } 63. CLASSES SHOULD DECLARE WHATTHEY NEEDpublic class HelloWorldExplicit { private readonly DateTime _timeOfGreeting; public HelloWorldExplicit(DateTime timeOfGreeting) { _timeOfGreeting = timeOfGreeting; } public string Hello(string name) { if (_timeOfGreeting.Hour < 12) return "Good morning, " + name; if (_timeOfGreeting.Hour < 18) return "Good afternoon, " + name; return "Good evening, " + name; }} 64. THE PROBLEM Order has hidden dependencies:o MailMessageo SmtpCliento InventorySystemo PaymentGatewayo Loggero DateTime.Now Resulto Tight couplingo No way to change implementation details (OCP violation)o Difficult to test 65. DEPENDENCY INJECTION Dependency Injection is a technique that is used to allow calling code toinject the dependencies a class needs when it is instantiated. The Hollywood Principleo Dont call us; well call you Three Primary Techniqueso Constructor Injectiono Property Injectiono Parameter Injection Other methods exist as well 66. CONSTRUCTOR INJECTION Dependencies are passed in via constructorStrategy Pattern ProsoClasses self-document what they need to perform their workoWorks well with or without a containeroClasses are always in a valid state once constructed ConsoConstructors can have many parameters/dependencies (design smell)oSome features (e.g. Serialization) may require a default constructoroSome methods in the class may not require things other methods require (design smell) 67. PROPERTY INJECTION Dependencies are passed in via a property o Also known as setter injection Pros o Dependency can be changed at any time during object lifetime o Very flexible Cons o Objects may be in an invalid state between construction and setting of dependencies via setters o Less intuitive 68. PARAMETER INJECTION Dependencies are passed in via a method parameter Pros o Most granular o Very flexible o Requires no change to rest of class Cons o Breaks method signature o Can result in many parameters (design smell) Consider if only one method has the dependency, otherwise prefer constructor injection 69. REFACTORINGExtract Dependencies into InterfacesInject implementations of interfaces into OrderReduce Orders responsibilities (apply SRP) 70. DIP SMELLS Use of new keywordforeach(var item in cart.Items){try{var inventorySystem = new InventorySystem();inventorySystem.Reserve(item.Sku, item.Quantity);}} 71. DIP SMELLSUse of static methods/propertiesmessage.Subject = "Your order placed on " +DateTime.Now.ToString();OrDataAccess.SaveCustomer(myCustomer); 72. WHERE DO WE INSTANTIATEOBJECTS? Applying Dependency Injection typically results in many interfaces that eventually need to be instantiatedsomewhere but where? Default Constructor o You can provide a default constructor that news up the instances you expect to typically need in your application o Referred to as poor mans dependency injection or poor mans IoC Main o You can manually instantiate whatever is needed in your applications startup routine or main() method IoC Container o Use an Inversion of Control Container 73. IOC CONTAINERS Responsible for object graph instantiation Initiated at application startup via code or configuration Managed interfaces and the implementation to be used areRegistered with the container Dependencies on interfaces are Resolved at applicationstartup or runtime Examples of IoC Containers for .NET o Microsoft Unity o StructureMap o Ninject o Windsor o Funq / Munq 74. SUMMARY Depend on abstractions. Dont force high-level modules to depend on low-level modules throughdirect instantiation or static method calls Declare class dependencies explicitly in their constructors Inject dependencies via constructor, property, or parameter injection Related Fundamentals:o Single Responsibility Principleo Interface Segregation Principleo Faade Patterno Inversion of Control Containers Recommended Reading:o Agile Principles, Patterns, and Practices by Robert C. Martin and MicahMartin [http://amzn.to/agilepppcsharp]o http://www.martinfowler.com/articles/injection.html 75. TRADITIONAL (NAVE) LAYEREDARCHITECTURE 76. INVERTED ARCHITECTURE 77. THE PROBLEM Dependencies Flow Toward Infrastructure Core / Business / Domain Classes Depend on ImplementationDetails Result o Tight coupling o No way to change implementation details without recompile (OCP violation) o Difficult to test 78. DEPENDENCY INJECTION Dependency is transitive oIf UI depends on BLL depends on DAL depends on Database Then *everything* depends on the Database Depend on abstractions (DIP) Package interfaces (abstractions) with the client (ISP) Structure Solutions and Projects so Core / BLL is atcenter, with fewest dependencies 79. SUMMARY Dont Depend on Infrastructure Assemblies from Core Apply DIP to reverse dependencies Related Fundamentals: o Open Closed Principle o Interface Segregation Principle o Strategy Pattern Recommended Reading: oAgile Principles, Patterns, and Practices by Robert C. Martin and Micah Martin [http://amzn.to/agilepppcsharp] o http://www.martinfowler.com/articles/injection.html 80. DONT REPEAT YOURSELFEvery piece of knowledge must have a single, unambiguousrepresentation in the system. The Pragmatic ProgrammerRepetition in logic calls for abstraction. Repetition in processcalls for automation.97 Things Every Programmer ShouldKnowVariations include: Once and Only Once Duplication Is Evil (DIE) 81. ANALYSIS Magic Strings/Values Duplicate logic in multiple locations Repeated if-then logic Conditionals instead of polymorphism Repeated Execution Patterns Lots of duplicate, probably copy-pasted, code Only manual tests Static methods everywhere 82. MAGIC STRINGS / VALUES 83. DUPLICATE LOGIC IN MULTIPLELOCATIONS 84. REPEATED IF-THEN LOGIC 85. CONDITIONAL INSTEAD OFPOLYMORPHISM Example of Flags Over Objects anti-pattern Violates the Tell, Dont Ask principle (aka DIP) 86. SUMMARY Repetition breeds errors and waste Refactor code to remove repetition Recommended Reading: o The Pragmatic Programmer: From Journeyman to Master http://amzn.to/b2gJdK o 97 Things Every Programmer Should Know http://amzn.to/cAse1Y 87. STATIC METHODS Tightly coupled Difficult to test Difficult to change behavior (violates OCP) Cannot use object oriented design techniques o Inheritance o Polymorphism 88. SUMMARY Repetition breeds errors and waste Abstract repetitive logic in code Related Fundamentals: o Template Method Pattern o Command Pattern o Dependency Inversion Principle Recommended Reading: o The Pragmatic Programmer: From Journeyman to Master http://amzn.to/b2gJdK o 97 Things Every Programmer Should Know http://amzn.to/cAse1Y 89. REPEATED EXECUTION PATTERNS 90. DUPLICATE, COPY PASTED CODEToo Numerous to ListCommercial Tool (free version available)o Atomiq (http://GetAtomiq.com) 91. CONSIDER CODE GENERATION T4 Templates o Custom code generation templates o Built into Visual Studio 2010 ORM Tools (LINQ to SQL, Entity Framework, nHibernate, LLBLGen) o Reduce repetitive data access code o Eliminate common data access errors Commercial Tools: o CodeSmith o CodeBreeze o CodeHayStack 92. REPETITION IN PROCESS Testing o Performing testing by hand is tedious and wasteful Builds o Performing builds by hand is tedious and wasteful Deployments o Performing deployments by hand is tedious and wasteful Are you seeing a trend here? String.Format(Performing {0} by hand is tedious and wasteful, action); 93. SUMMARY Repetition breeds errors and waste Use an ORM tool to eliminate repeated data access code Use Tools to Locate Repeated Code Automate repetitive actions in your processes Recommended Reading: o The Pragmatic Programmer: From Journeyman to Master http://amzn.to/b2gJdK o 97 Things Every Programmer Should Know http://amzn.to/cAse1Y Related Tool o Atomiq http://GetAtomiq.com 94. E X A MP L E A P P : B E F O R E A N DS.O.L.I.D. CONVERSION SUMMARY AFTERBeforeAfter 95. S.O.L.I.D. -> OO LOW COUPLING: OCP, DIP, ISPPRINCIPLES 96. S.O.L.I.D. -> OO H IGH C OH E S ION : L OW C OU P L IN G + S R P , L S PPRINCIPLES 97. S.O.L.I.D. -> OO PRINCIPLES ENCAPSULATION: SRP, LSP, DIP 98. QUESTIONS? 99. THANK YOU!Adnan [email protected]@adnanmasood Blog: blog.AdnanMasood.com Pasadena .NET User Group: www.sgvdotnet.org