Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

OBJECT Related to Object Oriented Programming.

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

OBJECT CALISTHENICS Jeff Bay, in The ThoughtWorks Anthology, lists 9 rules to writing better Object Oriented code.

Slide 5

Slide 5 text

MOTIVATION Readable Code, Comprehensible, Testable, Maintainable.

Slide 6

Slide 6 text

1. ONLY ONE LEVEL OF INDENTATION PER METHOD

Slide 7

Slide 7 text

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 ( ) ; } }

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

2. DON'T USE THE ELSE KEYWORD

Slide 10

Slide 10 text

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 ' ) ; } }

Slide 11

Slide 11 text

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 ' ) ; }

Slide 12

Slide 12 text

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 ) ; }

Slide 13

Slide 13 text

BUT ALSO Polymorphism Null Object Pattern Strategy Pattern State Pattern

Slide 14

Slide 14 text

3. WRAP ALL PRIMITIVES AND STRINGS

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

If the variable of primitive type has a behavior, it MUST be encapsulated.

Slide 17

Slide 17 text

It is especially true for Domain Driven Design.

Slide 18

Slide 18 text

4. FIRST CLASS COLLECTIONS

Slide 19

Slide 19 text

Any class that contains a collection should contain no other member variables.

Slide 20

Slide 20 text

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)

Slide 21

Slide 21 text

5. ONE DOT PER LINE

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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 ( ) ; } }

Slide 24

Slide 24 text

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 ( ) ) ; } }

Slide 25

Slide 25 text

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 ( ) ; } }

Slide 26

Slide 26 text

6. DON'T ABBREVIATE

Slide 27

Slide 27 text

WHY DO YOU WANT TO ABBREVIATE?

Slide 28

Slide 28 text

WRITE THE SAME NAME OVER AND OVER AGAIN? Then, your method is reused multiple times. Looks like code duplication.

Slide 29

Slide 29 text

METHOD NAME TOO LONG? Maybe your class has multiple responsabilities. Violation of the Single Responsibility Principle.

Slide 30

Slide 30 text

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/

Slide 31

Slide 31 text

7. KEEP ALL ENTITIES SMALL

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

8. NO CLASSES WITH MORE THAN TWO INSTANCE VARIABLES

Slide 34

Slide 34 text

YES, I KNOW!

Slide 35

Slide 35 text

WHY? Low cohesion, better encapsulation.

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

9. NO GETTERS/SETTERS/PROPERTIES

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

Getters/Setters violate the Open/Closed Principle.

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

THANK YOU, QUESTIONS? williamdurand.fr github.com/willdurand twitter.com/couac