Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

William Durand

May 23, 2013
Tweet

More Decks by William Durand

Other Decks in Programming

Transcript

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

    rules to writing better Object Oriented code.
  2. 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 ( ) ; } }
  3. 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
  4. 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 ' ) ; } }
  5. 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 ' ) ; }
  6. 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 ) ; }
  7. 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)
  8. 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 ( ) ; } }
  9. 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 ( ) ) ; } }
  10. 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 ( ) ; } }
  11. WRITE THE SAME NAME OVER AND OVER AGAIN? Then, your

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

    Violation of the Single Responsibility Principle.
  13. 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/
  14. 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
  15. 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