Object Oriented Concepts and Principles

8,670 views

Published on

This presentation can be used to introduce OO concepts and the SOLID principles to developers

0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
8,670
On SlideShare
0
From Embeds
0
Number of Embeds
9
Actions
Shares
0
Downloads
281
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

Object Oriented Concepts and Principles

  1. 1. Smart People · Smart Solutions
  2. 2. Object Oriented Design Principles Session 1 – Getting a S.O.L.I.D understanding of the basic principles
  3. 3. Why do we need to know this? <ul><li>Dependency Management is an issue that most of us have faced. </li></ul><ul><li>Poor dependency management leads to code that is hard to change, fragile, and non-reusable. </li></ul><ul><li>When dependencies are well managed, the code remains flexible, robust, and reusable. </li></ul><ul><li>- Robert C Martin (father of OOD) </li></ul>
  4. 4. What would we like to achieve here… <ul><li>Write more maintainable code </li></ul><ul><li>Write more reusable code </li></ul><ul><li>Write more testable code </li></ul><ul><li>Write packages that are easier to deploy </li></ul>
  5. 5. The Basic Concepts of OO - Encapsulation <ul><li>Encapsulation is the hiding of non-essential features </li></ul>
  6. 6. The Basic Concepts of OO - Abstraction <ul><li>The mechanism and practice of abstraction is to reduce and factor out details so that one can focus on a few concepts at a time i.e. make things simpler </li></ul><ul><li>Abstraction is the representation of only the essential features of an object </li></ul>
  7. 7. The Basic Concepts of OO - Inheritance <ul><li>A way to form new classes (instances of which are called objects) using classes that have already been defined. </li></ul><ul><li>Inheritance is intended to help reuse existing code with little or no modification. </li></ul>
  8. 8. The Basic Concepts of OO - Polymorphism <ul><li>Polymorphism refers to the ability to define multiple classes with functionally different, yet identically named methods or properties that can be used interchangeably by client code at run time </li></ul><ul><li>See code Example </li></ul>
  9. 9. The Basic Concepts of OO - Polymorphism public void ShowPolyMorphismExample() { DerivedClass B = new DerivedClass(); DoWork( B ); BaseClass A = (BaseClass) B ; DoWork( A ); DerivedClass2 C = new DerivedClass2(); DoWork( C ); } public void DoWork (BaseClass baseClass) { baseClass.DoWork(); } public class DerivedClass2 : BaseClass { public override void DoWork() { } public override int WorkProperty { get { return 0; } } } public class DerivedClass : BaseClass { public override void DoWork() { } public override int WorkProperty { get { return 0; } } } public class BaseClass { public virtual void DoWork() { } public virtual int WorkProperty { get { return 0; } } }
  10. 10. The Basic Concepts of OO – Decoupling <ul><li>Decoupling allows for the separation of object interactions from classes and inheritance into distinct layers of abstraction, for ex. Decoupling business logic from presentation (front end) logic </li></ul><ul><li>A common use of decoupling is to polymorphically decouple the encapsulation, which is the practice of using reusable code to prevent discrete code modules from interacting with each other. </li></ul><ul><li>In practice, decoupling often involves trade-offs with regard to which patterns of change to favor. </li></ul>
  11. 11. The Basic Concepts of OO - Getting a S.O.L.I.D understanding of the basic principles
  12. 12. What is S.O.L.I.D.? <ul><li>S.O.L.I.D. is a collection of best-practice, object-oriented design principles which can be applied to your design, allowing you to accomplish various desirable goals such as loose-coupling, higher maintainability, intuitive location of interesting code, etc. </li></ul>
  13. 13. What is S.O.L.I.D.? <ul><li>Each of the various letters in the S.O.L.I.D. acronym is yet another acronym </li></ul><ul><li>SRP: Single Responsibility Principle </li></ul><ul><li>THERE SHOULD NEVER BE MORE THAN ONE REASON FOR A CLASS TO CHANGE. </li></ul><ul><li>OCP: Open Closed Principle </li></ul><ul><li>SOFTWARE ENTITIES (CLASSES, MODULES, FUNCTIONS, ETC.) SHOULD BE OPEN FOR EXTENSION BUT CLOSED FOR MODIFICATION . </li></ul><ul><li>LSP: Liskov Substitution Principle </li></ul><ul><li>FUNCTIONS THAT USE ... REFERENCES TO BASE CLASSES MUST BE ABLE TO USE OBJECTS OF DERIVED CLASSES WITHOUT KNOWING IT. </li></ul><ul><li>ISP: Interface Segregation Principle </li></ul><ul><li>CLIENTS SHOULD NOT BE FORCED TO DEPEND UPON INTERFACES THAT THEY DO NOT USE </li></ul><ul><li>DIP: Dependency Inversion Principle </li></ul><ul><li>A. HIGH LEVEL MODULES SHOULD NOT DEPEND UPON LOW LEVEL MODULES. BOTH SHOULD DEPEND UPON ABSTRACTIONS </li></ul><ul><li>B. ABSTRACTIONS SHOULD NOT DEPEND UPON DETAILS. DETAILS SHOULD DEPEND UPON ABSTRACTIONS </li></ul>
  14. 14. SRP: Single Responsibility Principle <ul><li>THERE SHOULD NEVER BE MORE THAN ONE REASON FOR A CLASS TO CHANGE. </li></ul>
  15. 15. SRP: Single Responsibility Principle <ul><li>Method/object should only have one reason to change </li></ul><ul><li>Some of the factors that should be taken into account when applying SRP: </li></ul><ul><ul><li>Is this code reusable? </li></ul></ul><ul><ul><li>How often will it change? </li></ul></ul><ul><ul><li>What is required of the code now vs how you want to refactor it </li></ul></ul><ul><ul><li>Which costs will be involved should you refactor this </li></ul></ul><ul><ul><ul><li>Money </li></ul></ul></ul><ul><ul><ul><li>Time </li></ul></ul></ul><ul><ul><ul><li>Applications affected </li></ul></ul></ul><ul><ul><ul><li>Etc… </li></ul></ul></ul>
  16. 16. SRP: Single Responsibility Principle <ul><li>Whats wrong/right with these pics? </li></ul>
  17. 17. SRP – Problem vs Solution [code example] <ul><li>How can we improve this code: </li></ul><ul><ul><li>Lets create a type against which we can store the product info </li></ul></ul><ul><ul><li>Lets extract the loading of products to a separate component </li></ul></ul><ul><ul><li>How are things looking now? Can we still refactor? </li></ul></ul>
  18. 18. SRP – Problem vs Solution [code example] <ul><li>How can we improve this code: </li></ul><ul><ul><li>Lets separate the logic not related to the form (using the MVP pattern in this case) </li></ul></ul><ul><ul><li>This pattern must separate the concerns of </li></ul></ul><ul><ul><ul><li>a) visualization, </li></ul></ul></ul><ul><ul><ul><li>b) orchestration (task delegation) and </li></ul></ul></ul><ul><ul><ul><li>c) (data-) model </li></ul></ul></ul>
  19. 19. SRP – Problem vs Solution [code example] <ul><li>A quick rundown of the MVP </li></ul><ul><ul><li>Model-view-presenter (MVP) is a user interface design pattern engineered to facilitate automated unit testing and improve the separation of concerns in presentation logic – Wikipedia </li></ul></ul><ul><ul><li>Advantages: </li></ul></ul><ul><ul><ul><li>Allows us to write test scripts to test the UI, for ex. </li></ul></ul></ul><ul><ul><ul><li>By decoupling code in the presenter level, we can now reuse this code in different presentation technologies, like Winforms or Webforms </li></ul></ul></ul><ul><ul><ul><li>You can code the logic before you have the UI coded </li></ul></ul></ul>
  20. 20. SRP – Problem vs Solution [code example] <ul><li>Let's analyze what the responsibility of the view should be </li></ul><ul><ul><li>delegate the user's request to choose an XML document to the presenter </li></ul></ul><ul><ul><li>delegate the user's request to load the data from the selected XML document to the presenter </li></ul></ul><ul><ul><li>provide the name of the selected XML document to the presenter </li></ul></ul><ul><ul><li>accept a file name (of a selected XML document) from the presenter </li></ul></ul><ul><ul><li>display a given list of products provided by the presenter (in a ListView control) </li></ul></ul>
  21. 21. SRP – Problem vs Solution [code example] <ul><li>How can we improve this code: </li></ul><ul><ul><li>There are still 3 concerns handled by the repository class </li></ul></ul><ul><ul><ul><li>Retrieval of data </li></ul></ul></ul><ul><ul><ul><li>Looping over nodes in the XML document </li></ul></ul></ul><ul><ul><ul><li>Mapping the xml node to a product </li></ul></ul></ul>
  22. 22. SRP – Problem vs Solution [code example] <ul><li>Lets extract separate components what will load the data and map the data </li></ul>
  23. 23. SRP – Problem vs Solution [code example] <ul><li>Lets extract separate components what will load the data and map the data </li></ul>
  24. 24. SRP – Problem vs Solution [code example] <ul><li>All done! </li></ul><ul><li>Each component now has a single responsibility </li></ul>
  25. 25. OCP: Open Closed Principle <ul><li>SOFTWARE ENTITIES (CLASSES, MODULES, FUNCTIONS, ETC.) SHOULD BE OPEN FOR EXTENSION BUT CLOSED FOR MODIFICATION . </li></ul>
  26. 26. OCP: Open Closed Principle <ul><li>Open for extension </li></ul><ul><ul><li>the behavior can be extended </li></ul></ul><ul><li>Closed for modification </li></ul><ul><ul><li>No one should ever need change that class’s code </li></ul></ul><ul><li>This means that: </li></ul><ul><ul><li>New requirement = new code, not changing existing, working code </li></ul></ul><ul><ul><li>Depending on where OCP is implemented, some classes will never be 100% closed.. Thus strategic closure is required </li></ul></ul><ul><ul><li>Make sure the OCP is implemented for most probable changes </li></ul></ul>
  27. 27. OCP: Open Closed Principle <ul><li>Bertrand Meyer’s Version </li></ul><ul><li>Robert C Martin </li></ul>Logger BaseLogger Logger DBLogger Logger DBLogger Logger DBLogger DBLogger Logger DBLogger DBLogger Logger DBLogger BaseLogger DBLogger Logger DBLogger Logger BaseLogger DBLogger Logger DBLogger
  28. 28. OCP: Where and when View Business Database System 1
  29. 29. OCP: Where and when View Business Database System 1
  30. 30. OCP: Where and when View Business Database System 1 View Database System 2
  31. 31. OCP: Where and when View Business Database System 1 View Database System 2
  32. 32. OCP: Possible Approach: Public vs Private <ul><li>Make all public member/global variables private </li></ul><ul><ul><li>This will reduce the impact that changing that variable has </li></ul></ul><ul><ul><ul><li>In OOD, we expect that methods of the class are not closed to its member variable </li></ul></ul></ul><ul><ul><ul><li>We do expect that any other class (incl subclasses) are closed against changes to those variables </li></ul></ul></ul><ul><ul><ul><li>If the variable is public and never changes, rather wrap it inside a public read-only property </li></ul></ul></ul><ul><ul><li>Whichever route is taken, the designer must asses how much closure is sacrificed and what the cost is of the public/global convenience </li></ul></ul>
  33. 33. OCP: Possible Approach: Inheritance using Interfaces <ul><li>Create interfaces representing the various contracts (howbeit a very shallow contract… ito the real definition of a contract) </li></ul><ul><li>Pros </li></ul><ul><ul><li>Every new requirement will result in a new class adhering to that interface </li></ul></ul><ul><ul><li>Changes to closed classes will only result in changes made to one specific class… should you need to change the class, at least its encapsulated </li></ul></ul><ul><ul><li>Very flexible classes </li></ul></ul><ul><li>Cons </li></ul><ul><ul><li>Classes can be come very cluttered </li></ul></ul>
  34. 34. OCP: Possible Approach: Polymorphism <ul><li>Create base classes that subclasses can extend </li></ul><ul><li>Pros </li></ul><ul><ul><li>Code can be reused since the subclass may choose to override certain base methods (where virtual methods are used) </li></ul></ul><ul><li>Cons </li></ul><ul><ul><li>Should the base class need to change for some reason, the knock-on effect may be huge ie more difficult to reuse </li></ul></ul>
  35. 35. OCP: Code Example – The Logger <ul><li>We have an AuthenticationService that uses a Logger to write debug, info and error messages. The client has requested that it should also be able to log to the database. </li></ul><ul><li>How can we improve our current “bad” solution to conform to the OCP </li></ul>
  36. 36. OCP: Code Example – The Logger Inheritance using Interfaces <ul><li>We create a logger Interface that our two loggers (the original logger and new DBLogger will implement) </li></ul>
  37. 37. OCP: Code Example – The Logger Polymorphism <ul><li>We create an abstract class that the logger and db logger will inherit off from. </li></ul><ul><li>Reusable functionality between the two loggers can be captured in the abstract class </li></ul>
  38. 38. OCP: Code Example – Practicalities <ul><li>So OCP is achieved for the following scenario: </li></ul><ul><ul><li>Changing the Authentication service to use a different logger when required…. </li></ul></ul><ul><ul><li>1) We don’t need to change AuthenticationService if we want to use a new logger </li></ul></ul><ul><ul><li>2) AuthenticationService can now use any logger </li></ul></ul><ul><li>Lets say we want to add another Logging method just to the logging class (not the DBLogger), called “Warning”. </li></ul><ul><ul><li>Does the current solution conform to the OCP for the new requirement? Why? </li></ul></ul>
  39. 39. OCP: Code Example – Field Validation <ul><li>We have class that uses validation. Since we know that these validation methods can be reused, we decide to abstract them into a separate class… </li></ul><ul><ul><li>How would we apply OCP in order to make the validation class extendable, ito adding new rules, but closed to modification? </li></ul></ul>
  40. 40. <ul><li>We have closed the validation class so that no changes should ever need to be made if you want to add new validation rules </li></ul><ul><li>The class is extendable in the sense that it can validate any set of validation rules </li></ul>OCP: Code Example – Field Validation
  41. 41. LSP: Liskov Substitution Principle <ul><li>If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T. </li></ul>
  42. 42. LSP: Liskov Substitution Principle <ul><li>FUNCTIONS THAT USE ... REFERENCES TO BASE CLASSES MUST BE ABLE TO USE OBJECTS OF DERIVED CLASSES WITHOUT KNOWING IT. </li></ul>
  43. 43. LSP: Violation 1 <ul><li>Whats wrong with this code? </li></ul><ul><li>This function violates both LSP and OCP… </li></ul><ul><ul><li>This function is aware of all the various implementations of shape </li></ul></ul><ul><ul><li>The extension of shape has not been closed properly </li></ul></ul>
  44. 44. LSP: Violation 2 <ul><li>Consider the following class diagram… </li></ul>
  45. 45. LSP: Violation 2 <ul><li>Given the previous class diagram… what will happen here…. </li></ul>
  46. 46. LSP: Liskov Substitution Principle <ul><li>A model viewed in isolation, can not be meaningfully validated </li></ul><ul><ul><li>When considering whether a particular design is correct or not, review the solution according to the assumptions that will be made by its users </li></ul></ul><ul><li>When using an object via its base class interface, you must accept anything the base class could accept </li></ul><ul><ul><li>Bertrand Meyer’s Design by Contract </li></ul></ul><ul><ul><ul><li>...when redefining a routine [in a derivative], you may only replace its precondition by a weaker one, and its postcondition by a stronger one </li></ul></ul></ul>
  47. 47. ISP: Interface Segregation Principle <ul><li>CLIENTS SHOULD NOT BE FORCED TO DEPEND UPON INTERFACES THAT THEY DO NOT USE </li></ul>
  48. 48. ISP: Interface Segregation Principle <ul><li>If you have an abstract class or interface, its implementers should not be forced to implement parts it doesn’t care about </li></ul><ul><ul><li>Any changes made to these fat interfaces or abstract classes are most likely force a change to its implementers. </li></ul></ul>
  49. 49. ISP: Example 1 <ul><li>The carconfigurator class implements an interface that exposes 3 properties: EngineType, ExteriorColour and InteriorColour. </li></ul><ul><li>3 separate classes are used to draw each property (they each accept an implementation of carconfigurator)… </li></ul><ul><li>Whats wrong with this…. </li></ul>
  50. 50. ISP: Example 1 <ul><li>Now, the interfaces are less likely to become bloated. </li></ul><ul><li>Changes to the interfaces are now only restricted to the classes that use those interfaces </li></ul>
  51. 51. ISP: Example 2 <ul><li>There are two animals (dog and rattlesnake) that inherit off an abstract animal class. Both classes override the feed and groom methods </li></ul><ul><li>But would really groom a rattlesnake? In this case, you wont, so the method is ignored… </li></ul><ul><li>Whats wrong with this? </li></ul>
  52. 52. ISP: Example 2 <ul><li>The animal class is no longer bloated. This gives us the option to customize our derived classes to be more specific to our needs </li></ul><ul><li>Also, should any changes be made to IPet, it will only affect Dog </li></ul>
  53. 53. DIP: Dependency Inversion Principle <ul><li>HIGH LEVEL MODULES SHOULD NOT DEPEND UPON LOW LEVEL MODULES. BOTH SHOULD DEPEND UPON ABSTRACTIONS </li></ul><ul><li>ABSTRACTIONS SHOULD NOT DEPEND UPON DETAILS. DETAILS SHOULD DEPEND UPON ABSTRACTIONS </li></ul>
  54. 54. DIP: Dependency Inversion Principle <ul><li>DIP is used to alleviate badly designed code, that is code that is: </li></ul><ul><ul><li>Rigid (single change will affect many other parts) </li></ul></ul><ul><ul><li>Fragile (single change may cause unexpected parts to break) </li></ul></ul><ul><ul><li>Immobile (hard to reuse code in another application since it can’t be decoupled) </li></ul></ul><ul><li>DIP is not Dependency Injection </li></ul><ul><ul><li>Dependency Injection is a form of DIP </li></ul></ul><ul><li>DIP can be seen as a combination of 3 SOLID principles </li></ul><ul><ul><li>SRP, OCP and LSP </li></ul></ul>
  55. 55. DIP: Dependency Inversion Principle <ul><li>According to Grady Booch: “...all well structured object-oriented architectures have clearly-defined layers, with each layer providing some coherent set of services though a well-defined and controlled interface.” </li></ul><ul><li>So whats wrong with this…. </li></ul>
  56. 56. DIP: Dependency Inversion Principle <ul><li>According to DIP.. It should look something like this: </li></ul>
  57. 57. DIP: Example 1 <ul><li>We have an Order Processor that will calculate the total of an order. It takes the following into account: </li></ul><ul><ul><li>Item total </li></ul></ul><ul><ul><li>Discount amount (if any) </li></ul></ul><ul><ul><li>Tax amount </li></ul></ul><ul><li>In this case, tax strategies from either US or UK can be applied… depending in which country the order was placed. </li></ul><ul><li>Whats wrong with this code? </li></ul>
  58. 58. DIP: Example 1 <ul><li>What’s wrong with the code: </li></ul><ul><ul><li>OrderProcessor has too many responsibilities (Violates SRP) </li></ul></ul><ul><ul><li>It’s not closed to the various possibilities of tax strategies (Violates OCP) </li></ul></ul><ul><li>So… how do we fix this? </li></ul><ul><ul><li>Remove its external dependencies: DiscountCalculator and Tax Decisions </li></ul></ul>
  59. 59. DIP: Example 1 <ul><li>Two patterns introduced in order to help solve our problem </li></ul><ul><ul><li>Adapter Pattern </li></ul></ul><ul><ul><li>Strategy Pattern </li></ul></ul><ul><li>Adapter Pattern (according to Wikipedia) </li></ul><ul><ul><li>translates one interface for a class into a compatible interface. </li></ul></ul><ul><ul><li>An adapter allows classes to work together that normally could not because of incompatible interfaces, by providing its interface to clients while using the original interface. </li></ul></ul><ul><li>Strategy Pattern (according to Wikipedia) </li></ul><ul><ul><li>is a particular software design pattern, whereby algorithms can be selected at runtime </li></ul></ul><ul><ul><li>The strategy pattern is useful for situations where it is necessary to dynamically swap the algorithms used in an application </li></ul></ul>
  60. 60. DIP: Example 1 – Adapter Pattern <ul><li>Since DiscountCalculator is a static class, we can’t change it from a static to non-static class, since it might be reused by other apps </li></ul><ul><li>Applying that Adapter Pattern will allow us to write our own wrapper for the class. </li></ul><ul><li>Should the mechanism for calculating discounts changes, the OrderProcessor doesn’t need to change </li></ul>
  61. 61. DIP: Example 1 – Strategy Pattern <ul><li>Since we have various tax strategies with the possibility of many more, this pattern makes perfect sense… </li></ul><ul><li>We can now swap out the various strategies without having to change the OrderProcessor </li></ul>
  62. 62. DIP: Example 1 – Final Solution
  63. 63. DIP: Example 1 – Final Solution <ul><li>Instead of the OrderProcessor depending directly on details, it depends solely on the abstracted interfaces </li></ul><ul><li>I can reuse the existing Discount Calculator with the added benefit that should it change, OrderProcessor wont need to change </li></ul><ul><li>I can now swap out the various tax strategies without OrderProcessor having to change </li></ul><ul><li>Since OrderProcessors dependencies have been factored out, its single responsibility can easily be discerned from looking at the code. </li></ul>
  64. 64. DIP: Other Example(s) <ul><li>Refer to the SRP code example (the Xml File Loading solution) </li></ul>
  65. 65. S.O.L.I.D – Conclusion (benefits) <ul><li>Low Coupling </li></ul><ul><ul><li>With OCP and DIP introduced, our system will have very low coupling… meaning we can modify behavior as needed, with little modification to the overall system </li></ul></ul><ul><li>High Cohesion </li></ul><ul><ul><li>Def : a measure of how strongly-related or focused the responsibilities of a single module are. </li></ul></ul><ul><ul><li>In a highly-cohesive system, code readability and the likelihood of reuse is increased, while complexity is kept manageable </li></ul></ul><ul><ul><li>With Low coupling and DIP, we can tie the small pieces of code together like building blocks </li></ul></ul>
  66. 66. S.O.L.I.D – Conclusion (benefits) <ul><li>Encapsulation </li></ul><ul><ul><li>Not just making fields private but hiding implementation details from other objects </li></ul></ul><ul><ul><li>LSP, DIP and SRP all work together to create true encapsulation </li></ul></ul><ul><ul><li>We’ve prevented implementations of various objects to leak into each other while ensuring the dependencies by encapsulating them behind a known interface </li></ul></ul><ul><ul><li>We’ve hidden implementation details and allowed for any implementation to be put in its place using DIP </li></ul></ul><ul><ul><li>We’ve also ensured that we don’t violate any of the individual abstraction’s semantics (using LSP) so that we can safely replace the implementation as needed </li></ul></ul>
  67. 67. S.O.L.I.D – Conclusion <ul><li>So did we meet our original requirements of what we wanted to archive through these sessions? </li></ul><ul><ul><li>Write more maintainable code </li></ul></ul><ul><ul><li>Write more reusable code </li></ul></ul><ul><ul><li>Write more testable code </li></ul></ul><ul><ul><li>Write packages that are easier to deploy </li></ul></ul>
  68. 68. S.O.L.I.D – Conclusion <ul><li>So did we meet our original requirements of what we wanted to archive through these sessions? </li></ul><ul><ul><li>Write more maintainable code </li></ul></ul><ul><ul><li>Write more reusable code </li></ul></ul><ul><ul><li>Write more testable code </li></ul></ul><ul><ul><li>Write packages that are easier to deploy </li></ul></ul><ul><ul><li>YES </li></ul></ul><ul><ul><li>YES </li></ul></ul><ul><ul><li>YES </li></ul></ul><ul><ul><li>YES </li></ul></ul>

×