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.

SOLID principles

274 views

Published on

A short introduction to the SOLID principles of Object Oriented Programming in (mostly) Dutch.
- Single responsibility
- Open/Closed
- Lishkov Substitution
- Interface Segregation
- Dependency Inversion
This presentation was given at a meetup for Working Spirit in Deventer.

Published in: Software
  • Be the first to comment

  • Be the first to like this

SOLID principles

  1. 1. SOLIDMARTIJN DASHORST topicus
  2. 2. AGENDA INTRODUCTIE SOLID CONCLUSIE & DISCUSSIE
  3. 3. INTRO
  4. 4. Acroniemen TCP IP XP SOLID JAVA EE JSP JPA SOAP SMTP SNMP OSI HTTP HATEOAS POM PINO JAREAR EJB C# JAX-B JAX-P JAX-WS JAX-RS SAAJ k8sl10n i18n GRASPKISS STAVAZA MOSCOW YAGNI
  5. 5. SOLID Robert C. Martin "Uncle Bob"
  6. 6. SOLID Robert C. Martin Copyright (c) 2000 by Robert C. Martin. All Rights Reserved. www.objectmentor.com 1 Design Principles and Design Patterns Robert C. Martinwww.objectmentor.com What is software architecture? The answer is multitiered. At the highest level, there are the architecture patterns that define the overall shape and structure of software applications1 . Down a level is the architecture that is specifically related to the pur- pose of the software application. Yet another level down resides the architecture of the modules and their interconnections. This is the domain of design patterns2 , pack- akges, components, and classes. It is this level that we will concern ourselves with in this chapter. Our scope in this chapter is quite limitted. There is much more to be said about the principles and patterns that are exposed here. Interested readers are referred to [Martin99]. Architecture and DependenciesWhat goes wrong with software? The design of many software applications begins as a vital image in the minds of its designers. At this stage it is clean, elegant, and com- pelling. It has a simple beauty that makes the designers and implementers itch to see it working. Some of these applications manage to maintain this purity of design through the initial development and into the first release.But then something begins to happen. The software starts to rot. At first it isn’t so bad. An ugly wart here, a clumsy hack there, but the beauty of the design still shows through. Yet, over time as the rotting continues, the ugly festering sores and boils accumulate until they dominate the design of the application. The program becomes a festering mass of code that the developers find increasingly hard to maintain. Eventu-1. [Shaw96] 2. [GOF96]
  7. 7. SOLID Single Responsibility Principle
 Open Closed Principle
 Lishkov Substitution Principle 
 Interface Segregation Principle
 Dependency Inversion Principle
  8. 8. SOLID
  9. 9. SOLID
  10. 10. A class should only have a single responsibility, that is, only changes to one part of the software's specification should be able to affect the specification of the class. wikipedia.org
  11. 11. Één verantwoordelijkheid per klasse: 
 één reden om te wijzigen.
  12. 12. public static void main(String[] args) {     Person user = new Person();     user.setVoornaam(System.console().readLine("Wat is je voornaam? "));     user.setAchternaam(System.console().readLine("Wat is je achternaam? "));     if (user.getVoornaam() == null || user.getVoornaam().isBlank()) {         console().printf("Je hebt geen geldige voornaam opgegeven");         return;     }     if (user.getAchternaam() == null || user.getAchternaam().isBlank()) {         console().printf("Je hebt geen geldige achternaam opgegeven");         return;     }     console().printf("Je accountnaam is: %snn",             user.getVoornaam().substring(0, 1) + user.getAchternaam()); }
  13. 13. public static void main(String[] args) {     Person user = new Person();     user.setVoornaam(System.console().readLine("Wat is je voornaam? "));     user.setAchternaam(System.console().readLine("Wat is je achternaam? "));     if (user.getVoornaam() == null || user.getVoornaam().isBlank()) {         console().printf("Je hebt geen geldige voornaam opgegeven");         return;     }     if (user.getAchternaam() == null || user.getAchternaam().isBlank()) {         console().printf("Je hebt geen geldige achternaam opgegeven");         return;     }     console().printf("Je accountnaam is: %snn",             user.getVoornaam().substring(0, 1) + user.getAchternaam()); }
  14. 14. public static void main(String[] args) {     Person user = new Person();     user.setVoornaam(System.console().readLine("Wat is je voornaam? "));     user.setAchternaam(System.console().readLine("Wat is je achternaam? "));     if (user.getVoornaam() == null || user.getVoornaam().isBlank()) {         console().printf("Je hebt geen geldige voornaam opgegeven");         return;     }     if (user.getAchternaam() == null || user.getAchternaam().isBlank()) {         console().printf("Je hebt geen geldige achternaam opgegeven");         return;     }     console().printf("Je accountnaam is: %snn",             user.getVoornaam().substring(0, 1) + user.getAchternaam()); }
  15. 15. public static void main(String[] args) {     Person user = new Person();     user.setVoornaam(System.console().readLine("Wat is je voornaam? "));     user.setAchternaam(System.console().readLine("Wat is je achternaam? "));     if (user.getVoornaam() == null || user.getVoornaam().isBlank()) {         console().printf("Je hebt geen geldige voornaam opgegeven");         return;     }     if (user.getAchternaam() == null || user.getAchternaam().isBlank()) {         console().printf("Je hebt geen geldige achternaam opgegeven");         return;     }     console().printf("Je accountnaam is: %snn",             user.getVoornaam().substring(0, 1) + user.getAchternaam()); }
  16. 16. public static void main(String[] args) {     Person user = new Person();     user.setVoornaam(System.console().readLine("Wat is je voornaam? "));     user.setAchternaam(System.console().readLine("Wat is je achternaam? "));     if (user.getVoornaam() == null || user.getVoornaam().isBlank()) {         console().printf("Je hebt geen geldige voornaam opgegeven");         return;     }     if (user.getAchternaam() == null || user.getAchternaam().isBlank()) {         console().printf("Je hebt geen geldige achternaam opgegeven");         return;     }     console().printf("Je accountnaam is: %snn",             user.getVoornaam().substring(0, 1) + user.getAchternaam()); }
  17. 17. public class PersonDataCapture {     public Person getUserData() {         Person user = new Person();         user.setVoornaam(System.console().readLine("Wat is je voornaam? "));         user.setAchternaam(System.console().readLine("Wat is je achternaam? "));         return user;     } }
  18. 18. public static void main(String[] args) {     PersonDataCapture input = new PersonDataCapture();     Person user = input.getUserData();     if (user.getVoornaam() == null || user.getVoornaam().isBlank()) {         console().printf("Je hebt geen geldige voornaam opgegeven");         return;     }     if (user.getAchternaam() == null || user.getAchternaam().isBlank()) {         console().printf("Je hebt geen geldige achternaam opgegeven");         return;     }     console().printf("Je accountnaam is: %snn",             user.getVoornaam().substring(0, 1) + user.getAchternaam()); }
  19. 19. public static void main(String[] args) {     PersonDataCapture input = new PersonDataCapture();     Person user = input.getUserData();     if (user.getVoornaam() == null || user.getVoornaam().isBlank()) {         console().printf("Je hebt geen geldige voornaam opgegeven");         return;     }     if (user.getAchternaam() == null || user.getAchternaam().isBlank()) {         console().printf("Je hebt geen geldige achternaam opgegeven");         return;     }     console().printf("Je accountnaam is: %snn",             user.getVoornaam().substring(0, 1) + user.getAchternaam()); }
  20. 20. public class PersonValidator {     public boolean isValidUser(Person user) {         if (user.getVoornaam() == null || user.getVoornaam().isBlank()) {             console().printf("Je hebt geen geldige voornaam opgegeven");             return false;         }         if (user.getAchternaam() == null || user.getAchternaam().isBlank()) {             console().printf("Je hebt geen geldige achternaam opgegeven");             return false;         }         return true;     } }
  21. 21. public static void main(String[] args) {     PersonDataCapture input = new PersonDataCapture();     Person user = input.getUserData();     PersonValidator validator = new PersonValidator();     if (!validator.isValidUser(user)) {         return;     }     console().printf("Je accountnaam is: %snn",             user.getVoornaam().substring(0, 1) + user.getAchternaam()); }
  22. 22. public static void main(String[] args) {     PersonDataCapture input = new PersonDataCapture();     Person user = input.getUserData();     PersonValidator validator = new PersonValidator();     if (!validator.isValidUser(user)) {         return;     }     console().printf("Je accountnaam is: %snn",             user.getVoornaam().substring(0, 1) + user.getAchternaam()); }
  23. 23. public class AccountGenerator {     public String generateAccountFor(Person user) {         return user.getVoornaam().substring(0, 1) + user.getAchternaam();     } }
  24. 24. public static void main(String[] args) {     PersonDataCapture input = new PersonDataCapture();     Person user = input.getUserData();     PersonValidator validator = new PersonValidator();     if (!validator.isValidUser(user)) {         return;     }     AccountGenerator generator = new AccountGenerator();     String accountnaam = generator.generateAccountFor(user);     System.console().printf("Je accountnaam is: %snn", accountnaam); }
  25. 25. public static void main(String[] args) {     PersonDataCapture input = new PersonDataCapture();     Person user = input.getUserData();     PersonValidator validator = new PersonValidator();     if (!validator.isValidUser(user)) {         return;     }     AccountGenerator generator = new AccountGenerator();     String accountnaam = generator.generateAccountFor(user);     System.console().printf("Je accountnaam is: %snn", 
         accountnaam); } public class AccountGenerator {     public String generateAccountFor(Person user) {         return user.getVoornaam().substring(0, 1) + user.getA     } } public class PersonValidator {     public boolean isValidUser(Person user) {         if (user.getVoornaam() == null || user.getVoornaam().isBlan             console().printf("Je hebt geen geldige voornaam opgegev             return false;         }         if (user.getAchternaam() == null || user.getAchternaam().is             console().printf("Je hebt geen geldige achternaam opgeg             return false;         }         return true;     } } public class PersonDataCapture {     public Person getUserData() {         Person user = new Person();         user.setVoornaam(console().readLine("Wat is je voorna         user.setAchternaam(console().readLine("Wat is je acht         return user;     } }
  26. 26. SOLID
  27. 27. open for extension closed for modification
  28. 28. class Rectangle {     int width;     int height; }
  29. 29. class AreaCalculator {     public double area(Rectangle... rectangles) {         double area = 0;         for (var r : rectangles) {             area += r.height * r.width;         }         return area;     } } Rectangle r1 = new Rectangle(); r1.width = 2; r1.height = 3; var calc = new AreaCalculator(); System.out.println(calc.area(r1));
  30. 30. class Rectangle {     int width;     int height; } class Circle {     int radius; }
  31. 31. class AreaCalculator {     public double area(Object... shapes) {         double area = 0;         for (var s : shapes) {             if (s instanceof Rectangle) {                 var r = (Rectangle) s;                 area += r.height * r.width;             } else if (s instanceof Circle) {                 var c = (Circle) s;                 area += c.radius * c.radius * Math.PI;             }         }         return area;     } }
  32. 32. var rect = new Rectangle(); rect.width = 2; rect.height = 3; var circle = new Circle(); circle.radius = 2; System.out.println(new AreaCalculator().area(rect, circle));
  33. 33. abstract class Shape {     public abstract double area(); } class Rectangle extends Shape {     int height, width;     public double area() {         return width * height;     } } class Circle extends Shape {     int radius;     public double area() {         return radius * radius * Math.PI;     } }
  34. 34. class AreaCalculator {     public double area(Shape... shapes) {         double area = 0;         for (var s : shapes) {             area += s.area();         }         return area;     } }
  35. 35. SOLID
  36. 36. ...in a computer program, if S is a subtype of T, then objects of type T may be replaced with objects of type S without altering any of the desirable properties of the program (correctness, task performed, etc.) wikipedia.org Liskov substitution principle
  37. 37. Objecten moeten zich netjes gedragen... TLDR; principe
  38. 38. Waar een A verwacht wordt, moet een B zich gelijksoortig gedragen B A
  39. 39. interface Sender {     void send(String s); } class SmtpSender implements Sender {     @Override     public void send(String s) {     } } class FtpSender implements Sender {     @Override     public void send(String s) {     } }
  40. 40. interface Sender {     void send(String s); } class SmtpSender implements Sender {     @Override     public void send(String s) {         if (s.startsWith("banaan"))             throw new IllegalStateException();     } } class FtpSender implements Sender {     @Override     public void send(String s) {     } }
  41. 41. interface Sender {     void send(String s); } class SmtpSender implements Sender {     @Override     public boolean send(String s) {     } } class FtpSender implements Sender {     @Override     public void send(Integer s) {     } }
  42. 42. class Filer {     public boolean file(String x) throws FileAlreadyExistsException {         return false;     } }
  43. 43. class Filer {     public boolean file(String x) throws FileAlreadyExistsException {         return false;     } } class NetworkFiler extends Filer {     public boolean file(String x)             throws FileAlreadyExistsException, SocketException {         return false;     } }
  44. 44. class Rectangle {     private int width, height;     public void setHeight(int h) {}     public void setWidth(int w) {}     public int getHeight() {}     public int getWidth() {} } static void fillRect(Rectangle r) {     r.setHeight(50);     r.setWidth(150);     assert (r.getHeight() == 50);     assert (r.getWidth() == 150); } Rectangle r = new Rectangle(); fillRect(r);
  45. 45. class Rectangle {     private int width, height;     public void setHeight(int h) {}     public void setWidth(int w) {}     public int getHeight() {}     public int getWidth() {} } class Square extends Rectangle {     public void setHeight(int h) {         super.setHeight(h);         super.setWidth(h);     }     public void setWidth(int w) {         super.setWidth(w);         super.setHeight(w);     } }
 static void fillRect(Rectangle r) {     r.setHeight(50);     r.setWidth(150);     assert (r.getHeight() == 50);     assert (r.getWidth() == 150); } Square s = new Square(); s.setHeight(100); fillRect(s);
  46. 46. SOLID
  47. 47. No client should be forced to depend on methods it does not use wikipedia.org Interface Segregation Principle
  48. 48. interface Shape {     public double getArea();     boolean isCongruentWith(Shape other);     void draw(); }
  49. 49. interface Shape {     public double getArea();     boolean isCongruentWith(Shape other);     void draw(); } class Rectangle implements Shape {     private int width, height;     public double getArea() {         return width * height;     }     boolean isCongruentWith(Shape othe     public void draw() {} }
  50. 50. interface Shape {     public double getArea();     boolean isCongruentWith(Shape other);     void draw(); } class Rectangle implements Shape {     private int width, height;     public double getArea() {         return width * height;     }     boolean isCongruentWith(Shape othe     public void draw() {} } class Circle implements Shape {     private int radius;     public double getArea() {         return radius * radius * Math.PI;     }     boolean isCongruentWith(Shape other)    public void draw() {} }
  51. 51. interface Shape {     public double getArea();     boolean isCongruentWith(Shape other);     void draw(); } class Rectangle implements Shape {     private int width, height;     public double getArea() {         return width * height;     }     boolean isCongruentWith(Shape othe     public void draw() {} } class Circle implements Shape {     private int radius;     public double getArea() {         return radius * radius * Math.PI;     }     boolean isCongruentWith(Shape other)    public void draw() {} } class Point implements Shape {     private int x, y;     public void draw() {}     boolean isCongruentWith(Shape other) }
  52. 52. interface Drawable {     void draw(); } interface Shape {     boolean congruentWith(Shape other); } interface Area extends Shape {     double area(); }
  53. 53. interface Drawable {     void draw(); } interface Shape {     boolean isCongruentWith(Shape other); } interface Area extends Shape {     double area(); } class Rectangle implements Drawable, Area, Shape {     private int height, width;     public void draw() { }     public boolean isCongruentWith(Shape }     public double area() { } }

  54. 54. interface Drawable {     void draw(); } interface Shape {     boolean isCongruentWith(Shape other); } interface Area extends Shape {     double area(); } class Circle implements Drawable, Area, Shape {     private int radius;     public void draw() { }     public boolean congruentWith(Shape ot }     public double area() { } }
  55. 55. interface Drawable {     void draw(); } interface Shape {     boolean isCongruentWith(Shape other); } interface Area extends Shape {     double area(); } class Point implements Drawable, Shape {     private int x, y;     public void draw() { }     public boolean congruentWith(Shape ot } }
  56. 56. • Java Collections • Java IO streams
  57. 57. SOLID
  58. 58. Depend upon abstractions, 
 not concretions Dependency Inversion Principle
  59. 59. 1. High-level modules should not depend on low-level modules. Both should depend on abstractions. 2. Abstractions should not depend on details. Details should depend on abstractions. 1. High-level modules should not depend on low-level modules. Both should depend on abstractions. 2. Abstractions should not depend on details. Details should depend on abstractions.
  60. 60. LeerlingDAO RapportService
  61. 61. LeerlingDAOImpl RapportService LeerlingDAO
  62. 62. Wanneer je het Open/Closed Principle toepast, volgt "automatisch" 
 Dependency Inversion iemand op internet
  63. 63. CONC
 LUSIE
  64. 64. SOLID Single Responsibility Principle
 Open Closed Principle
 Lishkov Substitution Principle Interface Segregation Principle
 Dependency Inversion Principle
  65. 65. SOLID Single Responsibility Principle
 Open Closed Principle
 Lishkov Substitution Principle Interface Segregation Principle
 Dependency Inversion Principle GRASP General Responsibility Assignment Software Patterns
  66. 66. SOLID GRASP Het *wat* Het *hoe* en waarom
  67. 67. Refactoring Code Ownership Continuous Delivery
  68. 68. SOLID DRY YAGNI GRASP PATTERNS REFACTORING
  69. 69. Meer lezen/zien? • GRASP
 (wikipedia) • Refactoring (2nd Edition) 
 Martin Fowler (boek) • Clean Code
 Robert C. Martin (boek) • Readable code - and the long lost secret of how to achieve it
 Christin Gorman (video, 10min)
  70. 70. Discussie

×