Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.

How much do we know about Object-Oriented Programming?

2.225 visualizaciones

Publicado el

This talk goes through many of the Object-Oriented Programming principles and characteristics. Things that all developers should have in mind while writing code.

Publicado en: Tecnología
  • Sé el primero en comentar

How much do we know about Object-Oriented Programming?

  1. 1. Software Craftsmanship by Sandro Mancuso Twitter: @sandromancuso How much do we know about OOP/OOD?
  2. 2. Inheritance >> Before we start What can we expect from this session?
  3. 3. Class Invariant >> Inheritance
  4. 4. public class Rectangle {      private int height;      private int width;        public Rectangle( int height, int width) {          this. height = height;          this. width = width;      }      public int getHeight() {          return this .height;      }      public void setHeight( int height) {          this .height = height;      }      public int getWidth() {          return this .width;      }      public void setWidth( int width) {          this. width = width;      } }   public class Square extends Rectangle {        public Square( int size) {          super(size, size);      }       public int setHeight( int height) {          return super. setHeight(height);      }      public int setWidth( int width) {          return super. setWidth(width);      } } What will happen when we call the setters? Class Invariant Invariant fix >>
  5. 5. public class Square extends Rectangle {        public Square( int size) {          super (size, size);      }       public void setHeight( int height) {          super .setHeight(height);          super .setWidth(height);      }      public void setWidth( int width) {          super .setWidth(width);          super .height(width);      } } <ul><li>In isolation, Rectangle and Square are consistent valid; </li></ul><ul><li>A sub-class is not a sub-class when: </li></ul><ul><ul><li>Needs to be adapted so it keeps its invariant </li></ul></ul><ul><ul><li>State becomes invalid when used in the context of a super class. </li></ul></ul>Should Square extend Rectangle? Class invariant – a fix but not a solution LSP >>
  6. 6. “ Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it. “ LSP violation public void drawShape(Shape s) {      if (s instanceof Square) {          drawSquare((Square) s);      } else if (s instanceof Circle){          drawCircle((Circle) s);      } } Liskov Substitution Principle - LSP Behavioral subtyping LSP violations >>
  7. 7. A more subtle violation of LSP Rectangle r = new Square(); r.setHeight(5); r.setWidth(6); Violations - Without the fix, Square would be in an invalid state when used as a Rectangle; - With the fix, the Square setter methods weaken (violate) Rectangle’s post conditions, which state that dimensions can be modified independently Liskov Substitution Principle - LSP Fixing the design >>
  8. 8. What we’ve learnt? <ul><li>We can not validate a model in isolation. </li></ul><ul><li>Looking at how the classes can be used by a client program, we realise that the model is broken. </li></ul><ul><li>A model should be validated just in terms of its clients. </li></ul>Liskov Substitution Principle - LSP public class Square {      int size;            public Square( int size) {          this .size = size;      }       public int getSize() {          return this .size;      }      public void setSize( int size) {          this. size = size;      } } DbC >>
  9. 9. - Term was coined by Bertrand Meyer in 1986 Based on the mutual obligations and benefits principle. - Pre-condition : obligation for the client, benefit for the supplier - Post-condition : obligation for the supplier, benefit for the client - Invariant : Assumed on entry, guaranteed on exit Design by Contract DbC implications >>
  10. 10. <ul><li>Subclasses are allowed to: </li></ul><ul><ul><li>Weaken pre-conditions (but not strengthen them) </li></ul></ul><ul><ul><li>Strengthen post-conditions and invariants (not not weaken them) </li></ul></ul><ul><ul><li>This is the foundation of LSP </li></ul></ul>Design by Contract implications public class ClassA {      public void someMethod() {…} } public class ClassB extends ClassA {      public void someMethod() { // Stronger pre-condition // Weaker post-condition & invariant } } public class Client {      public void doSomething(ClassA a) { a.someMethod(); } } <ul><li>What would happen if: </li></ul><ul><ul><li>Client client = new Client(); </li></ul></ul><ul><ul><li>client.doSomething( new ClassB()); // Would it be fair to the client? </li></ul></ul>Defensive Programming >>
  11. 11. - DbC : It’s the client’s responsibility (obligation) to respect supplier’s pre-condition. Code should “fail-hard” - Defensive Programming : Supplier takes the responsibility to validate pre-condition In both cases, client needs to take an action. DbC vs Defensive Programming - Whatever you do, don’t hide bugs. If a pre-condition is not met, let the system blow or let the client handle it. - Don’t code default behaviour unless this is part of the requirement. Side effect >>
  12. 12. A code is said to have side effect when it modifies some state or has an observable interaction with calling functions or outside world. (linked to DbC post-condition) Side effect <ul><li>Problems: </li></ul><ul><ul><li>Order of evaluation matters; </li></ul></ul><ul><ul><li>Understanding requires knowledge about context; </li></ul></ul><ul><ul><li>Hard to read and debug </li></ul></ul><ul><ul><li>Nightmare for multi-threading applications </li></ul></ul><ul><ul><li>Action at a distance anti-pattern </li></ul></ul>Very common in imperative programming and rare in functional programming. Avoiding problems >>
  13. 13. Side effect <ul><li>Avoiding undesirable side effect problems: </li></ul><ul><ul><li>Use side effect free functions whenever possible </li></ul></ul><ul><ul><li>Never use global variables </li></ul></ul><ul><ul><li>Prefer returning a value instead of manipulating a parameter’s state </li></ul></ul><ul><ul><li>Localise state changes, putting state and respective behaviour together </li></ul></ul><ul><ul><li>Use “Tell don’t ask” design approach </li></ul></ul><ul><ul><li>Prefer immutable classes </li></ul></ul><ul><ul><li>CQRS – Command Query Responsibility Segregation </li></ul></ul>POLA/POLS >>
  14. 14. Principle of least astonishment/surprise <ul><ul><li>Applied to all type of interfaces, not just code. </li></ul></ul><ul><ul><li>Methods should be self-documenting </li></ul></ul><ul><ul><li>Methods should do the least surprising thing it could, given its name </li></ul></ul>The result of performing some operation should be obvious, consistent, and predictable, based upon the name of the operation, parameters and return value. All programmers are API designers – Joshua Bloch <ul><li>Problems when violated </li></ul><ul><ul><li>Bugs are created when a method does not do what it is supposed to do </li></ul></ul><ul><ul><li>If you can’t find a good name, re-analyse your design </li></ul></ul>Violation >>
  15. 15. Violation of POLA / POLS public class EventProcessor {      public void processEvent(Event event) throws EventProcessorException { try { doSomethingWith(event); event.setState( PROCESSED ); // violation } catch (Exception e) { event.setState( FAILED ); // violation throw new EventProcessorException(e); } } } Possible undesired side effect. SRP >>
  16. 16. Single Responsibility Principle - SRP <ul><li>How do we know a class or method has a single responsibility? </li></ul><ul><ul><ul><li>- Outside view </li></ul></ul></ul><ul><ul><ul><li>- Inside view </li></ul></ul></ul>SRP violations >> What about the “else” keyword? What does it imply when we use it?
  17. 17. Single Responsibility Principle - SRP Where do things go wrong? - SRP violations are most seen in systems developed without TDD and refactoring. - Classes closer to the system interface have a more generic and broader responsibility - Failure do identify responsibility / delegation ratio Cohesion >>
  18. 18. Cohesion The cornerstone of Object-Oriented Programming Class level >> Cambridge Dictionary Cohesion (noun) : when the members of a group or society are united. Cohesive (adjective) : united and working together effectively. Wikipedia In computer programming, cohesion is a measure of how strongly-related and focused the various responsibilities of a software module are. LCOM4: Lack of Cohesion Methods (metrics used by Sonar)
  19. 19. Cohesion at class level The cornerstone of Object-Oriented Programming Method level >> <ul><ul><li>Coincidental (worst) : Methods grouped arbitrarily and have no significant relationship (E.g. Util classes with methods handling strings, lists, mathematical calculations) </li></ul></ul><ul><ul><li>Logical : Methods grouped because they logically are categorized to do the same thing, even if different by nature (E.g. grouping all I/O handling routine, all database selects, inserts, etc.). </li></ul></ul><ul><ul><li>Temporal : Methods grouped by when they are processed at a particular time in program execution (E.g. validates data, persist the data, create audit information, notifies user via email). </li></ul></ul><ul><ul><li>Procedural : Methods grouped because they always follow a certain sequence of execution. (Verify is user exist, performs login, write logs, retrieve user's detail) </li></ul></ul><ul><ul><li>Communicational : Methods grouped because they work on the same data (E.g. Insert, delete, validate, update a client entity). </li></ul></ul><ul><ul><li>Sequential : Methods grouped because the output of one method can be used as an input of other methods. (reads a file, process the file). </li></ul></ul><ul><ul><li>Functional (best) :  Methods grouped because they all contribute to a single well-defined task. (parsing XML) </li></ul></ul>
  20. 20. Cohesion at method level The cornerstone of Object-Oriented Programming God object >> <ul><ul><li>Coincidental (worst) : Performs multiple operations and some times they are not related to each other. </li></ul></ul><ul><ul><li>Conditional : According to an if statement, different attributes are modified or different values are set to the different attributes . </li></ul></ul><ul><ul><li>Iterative : Several attributes (Array variables) are modified as a result of a looping. </li></ul></ul><ul><ul><li>Communicational : More than one attribute is modified according to only one input. </li></ul></ul><ul><ul><li>Sequential : More than one variable (object) modification result in the change to only one attribute. </li></ul></ul><ul><ul><li>Functional (best) : Method modifies fewer than 2 attributes </li></ul></ul>
  21. 21. God Object Coupling >>
  22. 22. Coupling Types >> Coupling or dependency is the degree to which each program module relies on each one of the other modules - Low coupling often correlates with high cohesion, and vice versa. - Sign of good design and well maintainable code.
  23. 23. Coupling general types other types >> <ul><ul><li>Content coupling (high) : One module modifies or relies on the internal workings of another module (e.g., accessing local data of another module). </li></ul></ul><ul><ul><li>Common coupling : When two modules share the same global data (e.g., a global variable). </li></ul></ul><ul><ul><li>External coupling : Occurs when two modules share an externally imposed data format, communication protocol, or device interface. </li></ul></ul><ul><ul><li>Control coupling : One module controlling the flow of another, by passing it information on what to do (e.g., passing a what-to-do flag). </li></ul></ul><ul><ul><li>Stamp coupling (Data-structured coupling) : When modules share a composite data structure and use only a part of it, possibly a different part (e.g., passing a whole record to a function that only needs one field of it). </li></ul></ul><ul><ul><li>Data coupling : When modules share data through, for example, parameters. Each datum is an elementary piece, and these are the only data shared (e.g., passing an integer to a function that computes a square root). </li></ul></ul><ul><ul><li>Message coupling (low) : It can be achieved by state decentralization (as in objects) and component communication is done via parameters or message passing. </li></ul></ul>
  24. 24. Coupling – other types Ripple effect >> <ul><ul><li>Subclass Coupling : Describes the relationship between a child and its parent. The child is connected to its parent, but the parent isn't connected to the child. </li></ul></ul><ul><ul><li>Temporal coupling : When two actions are bundled together into one module just because they happen to occur at the same time. </li></ul></ul>
  25. 25. Coupling – The ripple effect ISP >>
  26. 26. Interface Segregation Principle - ISP ISP >>
  27. 27. Interface Segregation Principle - ISP Role interface >>
  28. 28. Role Interface DIP >> <ul><ul><li>Defined by looking at a specific interaction between consumers and suppliers </li></ul></ul><ul><ul><li>A supplier component may implement several role interfaces one for each pattern of interaction </li></ul></ul><ul><ul><li>Opposed to Header Interface , that contains all the public methods of a class. Good when alternative implementations may be used </li></ul></ul><ul><ul><li>Coined by Martin Fowler in 2006 </li></ul></ul>
  29. 29. Dependency Inversion Principle - DIP DIP >> <ul><ul><li>High-level modules should not depend on low-level modules. Both should depend on abstractions </li></ul></ul><ul><ul><li>Abstractions should not depend upon details. Details should depend upon abstractions </li></ul></ul>Violation What if we want to write it to disk? How can we reuse Copier?
  30. 30. Dependency Inversion Principle - DIP IoC & DI >> High and low-level modules now depend on an abstraction
  31. 31. DIP, IoC and DI Encapsulation Jump >> <ul><ul><li>DIP : One of the SOLID principles. Refers to decoupling high-level modules from low-level modules, inverting/reversing their dependencies. </li></ul></ul><ul><ul><li>IoC : Abstract principle where the caller’s code deals with the program’s execution order, but the business knowledge is encapsulated by the called subroutines. Can be implemented via: </li></ul></ul><ul><ul><ul><li>Abstract Factory / Factory method </li></ul></ul></ul><ul><ul><ul><li>Service Locator Pattern </li></ul></ul></ul><ul><ul><li>DI : It’s a design pattern used for separating behaviour from dependency resolution. </li></ul></ul><ul><ul><ul><li>Involves a dependent consumer, definition of dependencies and an injector (container) </li></ul></ul></ul><ul><ul><ul><li>Injection types are: </li></ul></ul></ul><ul><ul><ul><ul><li>Constructor / Setter injection </li></ul></ul></ul></ul><ul><ul><ul><ul><li>Interface injection </li></ul></ul></ul></ul><ul><ul><ul><ul><li>Field injection </li></ul></ul></ul></ul><ul><ul><ul><ul><li>Bijection </li></ul></ul></ul></ul>
  32. 32. Encapsulation Information Hiding >> <ul><ul><li>Restrict access to some of the object’s components </li></ul></ul><ul><ul><li>Facilitates the bundling of data with the methods operating on that data </li></ul></ul>Information Hiding != Data encapsulation
  33. 33. Information Hiding & Protected Variation OCP >> Information Hiding : Hide information about the design from other modules, at the points of difficult or likely to change. David Parnas Information hiding is Protected Variation, not data encapsulation To minimise change impacts, we aim for low coupling. To design for low coupling, we design for protected variations. Craig Larman Protected Variation : Identify points of predicted variation and create a stable interface around them. Alistair Cockburn
  34. 34. Open Closed Principle (OCP) LoD >> Software entities (classes, modules, functions, etc) should be open for extension, but closed for modification <ul><li>Achieved via </li></ul><ul><ul><li>Inheritance and override (Bertand Meyer – 1988) </li></ul></ul><ul><ul><li>Use of abstract classes to define the interface and multiple concrete implementations </li></ul></ul><ul><ul><li>Achieved by template method, proxy, delegate, chain of responsibility, specification and other patterns. </li></ul></ul>Misconception : Closed to modification does not mean that we cannot change a class. It means that we should avoid modifications that affect clients. Is it still a good idea today?
  35. 35. Law of Demeter - LoD Feature Envy >> <ul><li>Also known as: </li></ul><ul><ul><li>Principle of Least Knowledge (PLK) </li></ul></ul><ul><ul><li>Don’t talk to strangers </li></ul></ul><ul><ul><li>Train wreck </li></ul></ul>Violation context.getCar().getEngine().getPiston().getSparkPlug(),doSomething(); parent.getChildren().delete(child);
  36. 36. Feature Envy Other topics >> public void doSomething() { BigDecimal baseMonthlySalary = employee.getBaseMontlySalary(); int overtimeInHours = employee.getOverTimeInHours(); BigDecimal overtimeHourRate = employee.getOvertimeHourRate(); BigDecimal salaryToBePaid = baseMonthlySalary + (overtimeInHours * overtimeHourRate); // Do more stuff with the salary } public void doSomething() { BigDecimal salaryToBePaid = employee.getMonthlySalaryToBePaid(); // Do more stuff with the salary } A better implementation
  37. 37. A few other related topics Wrap up >> <ul><ul><li>DRY – Don’t Repeat Yourself </li></ul></ul><ul><ul><li>CQRS – Command Query Responsibility Segregation </li></ul></ul><ul><ul><li>Tell don’t ask </li></ul></ul><ul><ul><li>Object orgy – loss of the benefits of encapsulation </li></ul></ul><ul><ul><li>BDUF – Big Design Up Front </li></ul></ul><ul><ul><li>DDD - Domain Driven Design </li></ul></ul><ul><ul><li>Patterns – GoF, JEE Patterns, DDD patterns </li></ul></ul><ul><ul><li>Anti-patterns </li></ul></ul><ul><ul><li>Code smells – symptom that indicates a deeper problem </li></ul></ul><ul><ul><li>Missing concept </li></ul></ul><ul><ul><li>TDD – Test Driven Development </li></ul></ul><ul><ul><li>BDD – Behaviour Driven Development </li></ul></ul>
  38. 38. Wrap up There is always a good reason to break a rule or law, but it really needs to be a good one. The critical design tool for software development is a mind well educated in design principles. It is not the UML or any other technology Craig Larman Most software engineers don’t set out to create “bad designs”. Yet most software eventually degrades to the point where someone will declare the design to be unsound. Why does this happen? Was the design poor to begin with, or did the design actually degrade like a piece of rotten meat? At the heart of this issue is our lack of a good working definition of “bad” design . Uncle Bob Martin Questions >>
  39. 39. Questions London Software Craftsmanship Community – LSCC – Twitter: @sandromancuso