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.

Object Calisthenics - TDD Milano

233 views

Published on

Object Calisthenics workshop at #TDDMilano meetup
https://www.meetup.com/it-IT/TDD-Milano/
Thank to https://www.mikamai.com/ for the hospitality

Published in: Software
  • Be the first to comment

Object Calisthenics - TDD Milano

  1. 1. Object Calisthenics #TDDMilano Ferdinando Santacroce @jesuswasrasta
  2. 2. “ 2 The word calisthenics comes from the ancient Greek words kalòs (καλός), beauty, and sthénos (σθένος), strength. @jesuswasrasta #TDDMilano
  3. 3. “ 3 So, here’s an exercise that can help you to internalize principles of good object-oriented design and actually use them in real life. Jeff Bay @jesuswasrasta #TDDMilanobit.ly/ObjectCalisthenics
  4. 4. 4 class Board { public String print() { StringBuilder buffer = new StringBuilder(); //Level 0 for (int i = 0; i < 10; i++) { //Level 1: OK for (int j = 0; j < 10; j++) { //Level 2: NOT ALLOWED! buffer.append(data[i][j]); } buffer.append("n"); } return buffer.toString(); } } 1. Only one level of indentation per method @jesuswasrasta #TDDMilano
  5. 5. 5 if(status==Status.DONE){ doSomething(); } else {//ELSE NOT ALLOWED! doSomethingElse(); } 2. Don’t use ELSE keyword @jesuswasrasta #TDDMilano
  6. 6. 6 3. Wrap all primitives and strings class ZipCode{ String regex = "^[0-9]{5}(?:-[0- 9]{4})?$"; Pattern pattern = Pattern.compile(regex); String value; public ZipCode(String value) { this.value = value; } public boolean isWellFormed(){ return pattern.matcher(value).matches(); } } //Don't use primitives! String regex = "^[0-9]{5}(?:-[0-9]{4})?$"; Pattern pattern = Pattern.compile(regex); String zip = "12345"; if (pattern.matcher(value).matches()){ //... } //Use objects, we are doing OOP, after all.. ZipCode zipCode = new ZipCode("12345"); if(zipCode.isWellFormed()){ //... } @jesuswasrasta #TDDMilano
  7. 7. 7 //Don't use collections, directly List<String> players = new ArrayList<>(); String player = "John"; if(!(players.contains(player) || players.size() == 5)){ players.add(player); } 4. First class collections (1) @jesuswasrasta #TDDMilano
  8. 8. 8 //Wrap collections in meaningful objects Team team = new Team(); team.add(player); //... class Team { List<String> players = new ArrayList<>(); final int TEAM_SIZE = 5; public void add(String player){ if(players.contains(player)){ throw new DuplicatePlayer("Player " + player + " already present"); } if(players.size() == TEAM_SIZE){ throw new TeamFull("Team full, max " + TEAM_SIZE + " players"); } players.add(player); } 4. First class collections (2) @jesuswasrasta #TDDMilano
  9. 9. 9 public void update(){ //Only one dot per line context.getSession().update(); //That doesn't means this... Session session = context.getSession(); session.update(); //But this... context.update(); } 5. One dot per line @jesuswasrasta #TDDMilano
  10. 10. 10 //Don't do this String signOcr = "John Doe"; srep(signOcr); //But this String signatureFromOcr = "John Doe"; signReport(signatureFromOcr); 6. Don’t abbreviate @jesuswasrasta #TDDMilano
  11. 11. 11 7. Keep all entities small //But small and cohesive ones like these! class Player{ Identity identity; Address address; public Player(Identity identity){ this.identity = identity; } public changeAddress(Address address){ this.address = address; } } //Don’t create this kind of entities... class Player{ String firstName; String lastName; String nickName; String city; String street; String streetNumber; String zipCode; public void setFirstName(String firstName){ this.firstName = firstName; } //... //And so on, tons of getters and setter //... } class Identity{ String firstName; String lastName; String nickName; } class Address{ String city; String street; String streetNumber; String zipCode; } @jesuswasrasta #TDDMilano
  12. 12. 12 8. No classes with more than two instance variables //But you have to do this! class Identity{ FamilyName familyName; GivenName givenName; } //So, you can’t do this... class Identity{ String firstName; String lastName; String nickName; } class FamilyName{ String firstName; String lastName; } class GivenName{ String nickName; } @jesuswasrasta #TDDMilano
  13. 13. 13 9. No getters/setters/properties //You are not allowed to do this... class Player{ String firstName; //... public String zipCode; public void getFirstName(String firstName){ return this.firstName; } public void setFirstName(String firstName){ this.firstName = firstName; } //And so on... } @jesuswasrasta #TDDMilano
  14. 14. 14 @jesuswasrasta #TDDMilano Time to get stronger! Setup Farkle Kata 2 pomodoros Pair programming TDD Debriefing, Q&A
  15. 15. 15 @jesuswasrasta #TDDMilano github.com/jesuswasrasta/KataFarkle LET’S GO!
  16. 16. 16 @jesuswasrasta #TDDMilano Dice, Turn, Throwing, Player, Score? Too many objects? Did rules conflicted, sometimes? Does it felt weird or uncomfortable, maybe? Debriefing
  17. 17. 17 Summing up...
  18. 18. 18 Encapsulation
  19. 19. 19 Polimorphism
  20. 20. 20 Naming
  21. 21. 21 1. Only one level of indentation per method Promotes method cohesiveness Single Responsibility Principle (S.O.L.I.D.) Extract method Extract objects (collaborators) @jesuswasrasta #TDDMilano
  22. 22. 22 2. Don’t use ELSE keyword Polymorphism Behavioral Patterns Strategy Pattern (set algorithm at runtime) State Pattern (state machines) @jesuswasrasta #TDDMilano
  23. 23. 23 3. Wrap all primitives and strings Primitive Obsession Anti-Pattern: Using primitives to represent domain ideas @jesuswasrasta #TDDMilano
  24. 24. 24 4. First class collections Encapsulation: Any class that contains a collection should contain no other member variables Give behaviors related to the collection a home @jesuswasrasta #TDDMilano
  25. 25. 25 5. One dot per line Law of Demeter Only talk with your immediate friends, don’t talk to strangers Fluent interfaces allowed @jesuswasrasta #TDDMilano
  26. 26. 26 6. Don’t abbreviate Naming “Clean Code” book, Robert C. Martin, Ch. 2 Meaningful, intention-revealing, pronounceable, searchable names Method’s name too long? Maybe it does too many things... @jesuswasrasta #TDDMilano
  27. 27. 27 7. Keep all entities small Single Responsibility Principle (again...) Class with 50 l.o.c, methods with 5 The “class that fits in the monitor” rule There’s no black & white, it’s all about trade-offs @jesuswasrasta #TDDMilano
  28. 28. 28 8. No classes with more than two instance variables High cohesion, low coupling @jesuswasrasta #TDDMilano
  29. 29. 29 9. No getters/setters/properties Tell, don’t ask Feature envy code-smell (extensive use of another class) They violates Open/Closed Principle (S.O.L.I.D.) Anemic Domain anti-pattern @jesuswasrasta #TDDMilano
  30. 30. Con il patrocinio di
  31. 31. 31 Thanks! Any questions? You can find me at: ▫ @jesuswasrasta ▫ http://about.me/ferdinando.santacroce

×