Object Calisthenics (APIHour #2)

Object Calisthenics (APIHour #2)

Object Calisthenics are basically exercises to writing better oriented object code. It is a set of 9 rules introduced by Jeff Bay in "The ThoughtWorks Anthology".

Online slides: http://williamdurand.fr/object-calisthenics-slides/
Source: https://github.com/willdurand/object-calisthenics-slides

F59d2f1ed66b8d9c6ceebea5a748494b?s=128

William Durand

May 23, 2013
Tweet

Transcript

  1. OBJECT CALISTHENICS Your code sucks, let's fix it!

  2. OBJECT Related to Object Oriented Programming.

  3. CALISTHENICS Term derived from greek, exercise, under the context of

    gymnastics.
  4. OBJECT CALISTHENICS Jeff Bay, in The ThoughtWorks Anthology, lists 9

    rules to writing better Object Oriented code.
  5. MOTIVATION Readable Code, Comprehensible, Testable, Maintainable.

  6. 1. ONLY ONE LEVEL OF INDENTATION PER METHOD

  7. YAY! c l a s s B o a r

    d { p u b l i c S t r i n g b o a r d ( ) { S t r i n g B u i l d e r b u f = n e w S t r i n g B u i l d e r ( ) ; / / 0 f o r ( i n t i = 0 ; i < 1 0 ; i + + ) { / / 1 f o r ( i n t j = 0 ; j < 1 0 ; j + + ) { / / 2 b u f . a p p e n d ( d a t a [ i ] [ j ] ) ; } b u f . a p p e n d ( " \ n " ) ; } r e t u r n b u f . t o S t r i n g ( ) ; } }
  8. EXTRACT METHOD p u b l i c S t

    r i n g b o a r d ( ) { S t r i n g B u i l d e r b u f = n e w S t r i n g B u i l d e r ( ) ; c o l l e c t R o w s ( b u f ) ; r e t u r n b u f . t o S t r i n g ( ) ; } p r i v a t e v o i d c o l l e c t R o w s ( S t r i n g B u i l d e r b u f ) { f o r ( i n t i = 0 ; i < 1 0 ; i + + ) { c o l l e c t R o w ( b u f , i ) ; } } p r i v a t e v o i d c o l l e c t R o w ( S t r i n g B u i l d e r b u f , i n t r o w ) { f o r ( i n t i = 0 ; i < 1 0 ; i + + ) { b u f . a p p e n d ( d a t a [ r o w ] [ i ] ) ; } b u f . a p p e n d ( " \ n " ) ; } http://refactoring.com/catalog/extractMethod.html
  9. 2. DON'T USE THE ELSE KEYWORD

  10. EXAMPLE p u b l i c v o i

    d l o g i n ( S t r i n g u s e r n a m e , S t r i n g p a s s w o r d ) { i f ( u s e r R e p o s i t o r y . i s V a l i d ( u s e r n a m e , p a s s w o r d ) ) { r e d i r e c t ( ' h o m e p a g e ' ) ; } e l s e { a d d F l a s h ( ' e r r o r ' , ' B a d c r e d e n t i a l s ' ) ; r e d i r e c t ( ' l o g i n ' ) ; } }
  11. EARLY RETURN p u b l i c v o

    i d l o g i n ( S t r i n g u s e r n a m e , S t r i n g p a s s w o r d ) { i f ( ! u s e r R e p o s i t o r y . i s V a l i d ( u s e r n a m e , p a s s w o r d ) ) { a d d F l a s h ( ' e r r o r ' , ' B a d c r e d e n t i a l s ' ) ; r e t u r n r e d i r e c t ( ' l o g i n ' ) ; } r e d i r e c t ( ' h o m e p a g e ' ) ; }
  12. VARIABLE p u b l i c v o i

    d l o g i n ( S t r i n g u s e r n a m e , S t r i n g p a s s w o r d ) { S t r i n g r e d i r e c t R o u t e = ' h o m e p a g e ' ; i f ( ! u s e r R e p o s i t o r y . i s V a l i d ( u s e r n a m e , p a s s w o r d ) ) { a d d F l a s h ( ' e r r o r ' , ' B a d c r e d e n t i a l s ' ) ; r e d i r e c t R o u t e = ' l o g i n ' ; } r e d i r e c t ( r e d i r e c t R o u t e ) ; }
  13. BUT ALSO Polymorphism Null Object Pattern Strategy Pattern State Pattern

  14. 3. WRAP ALL PRIMITIVES AND STRINGS

  15. Encapsulate all the primitives within objects. http://c2.com/cgi/wiki?PrimitiveObsession

  16. If the variable of primitive type has a behavior, it

    MUST be encapsulated.
  17. It is especially true for Domain Driven Design.

  18. 4. FIRST CLASS COLLECTIONS

  19. Any class that contains a collection should contain no other

    member variables.
  20. Each collection gets wrapped in its own class, so now

    behaviors related to the collection have a home. (e.g. filter methods, applying a rule to each element)
  21. 5. ONE DOT PER LINE

  22. LAW OF DEMETER Only talk to your immediate friends, don't

    talk to strangers.
  23. EXAMPLE c l a s s L o c a

    t i o n { c l a s s P i e c e { p u b l i c P i e c e c u r r e n t ; p u b l i c S t r i n g r e p r e s e n t a t i o n ; } } c l a s s B o a r d { p u b l i c S t r i n g b o a r d R e p r e s e n t a t i o n ( ) { S t r i n g B u i l d e r b u f = n e w S t r i n g B u i l d e r ( ) ; f o r ( L o c a t i o n l o c : s q u a r e s ( ) ) { b u f . a p p e n d ( l o c . c u r r e n t . r e p r e s e n t a t i o n . s u b s t r i n g ( 0 , 1 ) ) ; } r e t u r n b u f . t o S t r i n g ( ) ; } }
  24. TALK TO YOUR FRIENDS! c l a s s L

    o c a t i o n { p r i v a t e P i e c e c u r r e n t ; p u b l i c v o i d a d d T o ( S t r i n g B u i l d e r b u f ) { c u r r e n t . a d d T o ( b u f ) ; } } c l a s s P i e c e { p r i v a t e S t r i n g r e p r e s e n t a t i o n ; p u b l i c S t r i n g c h a r a c t e r ( ) { r e t u r n r e p r e s e n t a t i o n . s u b s t r i n g ( 0 , 1 ) ; } p u b l i c v o i d a d d T o ( S t r i n g B u i l d e r b u f ) { b u f . a p p e n d ( c h a r a c t e r ( ) ) ; } }
  25. TALK TO YOUR FRIENDS! / / B e f o

    r e : / / b u f . a p p e n d ( l o c . c u r r e n t . r e p r e s e n t a t i o n . s u b s t r i n g ( 0 , 1 ) ) ; / / A f t e r : c l a s s B o a r d { p u b l i c S t r i n g b o a r d R e p r e s e n t a t i o n ( ) { S t r i n g B u i l d e r b u f = n e w S t r i n g B u i l d e r ( ) ; f o r ( L o c a t i o n l o c a t i o n : s q u a r e s ( ) ) { l o c a t i o n . a d d T o ( b u f ) ; } r e t u r n b u f . t o S t r i n g ( ) ; } }
  26. 6. DON'T ABBREVIATE

  27. WHY DO YOU WANT TO ABBREVIATE?

  28. WRITE THE SAME NAME OVER AND OVER AGAIN? Then, your

    method is reused multiple times. Looks like code duplication.
  29. METHOD NAME TOO LONG? Maybe your class has multiple responsabilities.

    Violation of the Single Responsibility Principle.
  30. Me — 2 hours ago If you can't find a

    decent name for a class or a method, something is probably wrong with your conception. Rethink! http://williamdurand.fr/2012/01/24/designing-a-software-by-naming-things/
  31. 7. KEEP ALL ENTITIES SMALL

  32. No class over 50 lines and no package over 10

    files.
  33. 8. NO CLASSES WITH MORE THAN TWO INSTANCE VARIABLES

  34. YES, I KNOW!

  35. WHY? Low cohesion, better encapsulation.

  36. HOW? https://github.com/TheLadders/object-calisthenics#rule-8-no-classes-with-more...

  37. 9. NO GETTERS/SETTERS/PROPERTIES

  38. Tell, don't ask. http://pragprog.com/articles/tell-dont-ask http://c2.com/cgi/wiki?TellDontAsk

  39. Getters/Setters violate the Open/Closed Principle.

  40. GETTERS/SETTERS ARE EVIL / / G a m e p

    r i v a t e i n t s c o r e ; p u b l i c v o i d s e t S c o r e ( i n t s c o r e ) { t h i s . s c o r e = s c o r e ; } p u b l i c i n t g e t S c o r e ( ) { r e t u r n s c o r e ; } / / U s a g e g a m e . s e t S c o r e ( g a m e . g e t S c o r e ( ) + E N E M Y _ D E S T R O Y E D _ S C O R E ) ; / / G a m e p u b l i c v o i d a d d S c o r e ( i n t d e l t a ) { s c o r e + = d e l t a ; } / / U s a g e g a m e . a d d S c o r e ( E N E M Y _ D E S T R O Y E D _ S C O R E ) ; http://stackoverflow.com/questions/565095/are-getters-and-setters-evil http://whitewashing.de/2012/08/22/building_an_object_model__no_setters_allowed.html
  41. RECAP' 1. Only One Level Of Indentation Per Method 2.

    Don't Use The ELSE Keyword 3. Wrap All Primitives And Strings 4. First Class Collections 5. One Dot Per Line 6. Don't Abbreviate 7. Keep All Entities Small 8. No Classes With More Than Two Instance Variables 9. No Getters/Setters/Properties
  42. THANK YOU, QUESTIONS? williamdurand.fr github.com/willdurand twitter.com/couac