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

Stick to the rules

Avatar for Adam Nowak Adam Nowak
September 25, 2014

Stick to the rules

I talk about a few rules I tend to follow on a daily basis when I work with the code. I also talk a lot about adding abstraction layers everywhere.

Avatar for Adam Nowak

Adam Nowak

September 25, 2014
Tweet

More Decks by Adam Nowak

Other Decks in Programming

Transcript

  1. WHAT RULES?! spoiler alert: this presentation will be about my

    code-related rules, most of them relatead to stuff I do working day to day with Ruby on Rails
  2. RESPECT CODE STYLE GUIDES IF YOU'RE UNSURE HOW TO DO

    SOMETHING... JUST STICK TO THE RULES PROPOSED BY THE COMMUNITY https://github.com/bbatsov/ruby-style-guide
  3. METHOD NAMES RETURNING BOOL VALUES use ? sign / /

    s o m e _ v i e w . h a m l % h 1 = b o o k . p e r m i s s i o n s . f o r _ u s e r ( c u r r e n t _ u s e r ) = = ' r e a d ' vs # b o o k . r b d e f r e a d a b l e ? # s o m e c o d e r e t u r n i n g b o o l v a l u e t r u e e n d # b o o k . r e a d a b l e ? you should be able to read code like a newspaper
  4. ASK EXPLICITLY i f s o m e _ v

    a l u e . . . i f ! s o m e _ v a l u e . . . # u n l e s s s o m e _ v a l u e i f i t e m s vs i f s u m e _ v a l u e . p r e s e n t ? . . . i f s o m e _ v a l u e . n i l ? i f i t e m s . a n y ? all if statements should operate on boolean (t r u e /f a l s e ) values p r e s e n t ? n i l ? a n y ? a l l ? e x i s t s ? b l a n k ? e m p t y ?
  5. BANG BANG BANG! c l a s s T h

    i n g # i t ' s f o r m a t t e d b a d l y b e c a u s e i t w a s h a r d t o f i t i t h e r e d e f b r e a k ! @ b r o k e n = t r u e ; s e l f e n d d e f b r o k e n ? @ b r o k e n | | f a l s e e n d e n d t h i n g = T h i n g . n e w # > T h i n g : 0 x 0 0 7 f d b 6 c a e 0 a 2 0 t h i n g . b r o k e n ? # > f a l s e t h i n g . b r e a k ! # > T h i n g : 0 x 0 0 7 f d b 6 c a e 0 a 2 0 @ b r o k e n = t r u e t h i n g . b r o k e n ? # > t r u e CORE-LIB EXAMPLES WITH ! EQUIVALENTS: d o w n c a s e , u p c a s e , m e r g e , r e j e c t , etc.
  6. DIFFERENT RESPONSIBILITIES c l a s s P o s

    t h a s _ m a n y : c o m m e n t s e n d vs c l a s s A d m i n : : P o s t v a l i d a t e s : t i t l e , p r e s e n c e : t r u e e n d same object in different contexts has a different meaning
  7. c l a s s R a c e R

    e s u l t d e f i n i t i a l i z e ( u s e r 1 , u s e r 2 ) . . . e n d e n d vs c l a s s R a c e R e s u l t d e f i n i t i a l i z e ( w i n n e r , r u n n e r u p ) . . . e n d e n d R a c e R e s u l t . n e w ( b i k e r _ j o h n , b i k e r _ s a m ) R a c e R e s u l t . n e w ( h o n d a _ c a r , b m w _ c a r )
  8. NAME OBJECTS SO SOMEONE ELSE IS ABLE TO UNDERSTAND ITS

    MEANING c o l l e c t i o n . e a c h d o | i t m | i t m . d e l ! e n d vs c a r t _ i t e m s . e a c h d o | i t e m | i t e m . b u y ! e n d
  9. TRY TO AVOID TOO GENERAL NAMING FOR OBJECT HOLDERS (CONTAINERS)

    e.g. c o n t a i n e r , a r r a y , h a s h - just name it after items it contains
  10. PASS ALL THE ITEMS REQUIRED BY PARTIAL - # a

    p p / v i e w s / u s e r s / s o m e / n e s t e d / c o n t e x t / _ u s e r _ i n f o . h a m l = f r i e n d . n a m e vs - # a p p / v i e w s / f r i e n d s / s h o w . h a m l . . . = r e n d e r ' u s e r _ i n f o ' , u s e r : f r i e n d . . .
  11. LOGALLTHETHINGS! c l a s s U p d a

    t e U s e r s A d d r e s s e s d e f u p s a y " N u m b e r o f u s e r s t o u p d a t e : # { U s e r . c o u n t } " s a y _ w i t h _ t i m e ' U p d a t i n g u s e r s a d d r e s s e s . . . ' d o . . . i f u s e r _ u p d a t e . f a i l e d ? s a y " U s e r # # { u s e r _ u p d a t e . u s e r _ i d } r e f u s e d t o b e u p d a t e d " e n d . . . e n d e n d e n d = = 2 0 1 4 1 0 0 9 0 9 4 2 1 4 U p d a t e U s e r s A d d r e s s e s s : m i g r a t i n g = = = = = = = = = = = = = - - N u m b e r o f u s e r s t o u p d a t e : 4 1 3 - - U p d a t i n g u s e r s a d d r e s s e s . . . - - U s e r # 6 6 6 r e f u s e d t o b e u p d a t e d - > 1 . 3 3 7 s
  12. GOOD APPROACH b i n / r a k e

    d b : m i g r a t e d b : r o l l b a c k & & b i n / r a k e d b : m i g r a t e http://robots.thoughtbot.com/workflows-for-writing- migrations-with-rollbacks-in-mind
  13. View Object c l a s s S h o

    p p i n g C a r t V i e w a t t r _ a c c e s s o r : i t e m s d e f i n i t i a l i z e ( i t e m s ) s e l f . i t e m s = i t e m s e n d d e f t o t a l " # { i t e m s . s u m ( : p r i c e ) } R u b i e s " e n d d e f p o p u l a r _ i t e m s i t e m s . s e l e c t { | i | i . p o p u l a r ? } e n d e n d
  14. Decorator c l a s s C a r t

    I t e m D e c o r a t o r < D r a p e r : : D e c o r a t o r d e f s h o r t _ t i t l e o b j e c t . t i t l e . t r u n c a t e _ w o r d s ( 5 ) e n d d e f l i _ c s s _ c l a s s ' p o p u l a r ' i f p o p u l a r ? e n d e n d
  15. Template (view) % h 1 S h o p p

    i n g C a r t % u l - c a r t . i t e m s . e a c h d o | i t e m | % l i { c l a s s : i t e m . l i _ c s s _ c l a s s } = i t e m . s h o r t _ t i t l e = " # { c a r t . p o p u l a r _ i t e m s . c o u n t } o f y o u r i t e m s a r e v e r y p o p u l a r " e n d
  16. don't use models directly - decorate them if you have

    complex a logic - create an object wrapping all the data you need on a page it's good to have one object per page (it may contain other decorated objects) no need to use nested data (p o s t . a u t h o r . a d d r e s s . c i t y ) - structure your wrapping object as you need it in the template
  17. COMPARISON (1) # a p p / c o n

    t r o l l e r s / u s e r s _ c o n t r o l l e r . r b c l a s s U s e r s C o n t r o l l e r d e f i n d e x @ u s e r s = U s e r . a l l e n d e n d and view % h 1 U s e r s : = @ u s e r s . c o u n t
  18. COMPARISON (2) # a p p / c o n

    t r o l l e r s / u s e r s _ c o n t r o l l e r . r b c l a s s U s e r s C o n t r o l l e r h e l p e r _ m e t h o d : u s e r s d e f i n d e x ; e n d p r i v a t e d e f u s e r s U s e r . a l l e n d e n d and view % h 1 U s e r s : = u s e r s . c o u n t
  19. COMPARISON (3) # a p p / c o n

    t r o l l e r s / u s e r s _ c o n t r o l l e r . r b c l a s s U s e r s C o n t r o l l e r e x p o s e ( : u s e r s ) # e x p o s e ( : u s e r s ) { U s e r . a l l } d e f i n d e x ; e n d e n d and view % h 1 U s e r s : = u s e r s . c o u n t
  20. SAMPLE REPOSITORY c l a s s I t e

    m R e p o s i t o r y a t t r _ a c c e s s o r : u s e r d e f i n i t i a l i z e ( u s e r ) s e l f . u s e r = u s e r e n d d e f a l l I t e m . w h e r e ( u s e r _ i d : u s e r . i d ) e n d d e f a c t i v e a l l . w h e r e ( a c t i v e : t r u e ) e n d e n d I t e m R e p o s i t o r y . n e w ( c u r r e n t _ u s e r ) . a c t i v e
  21. WHY? easy to test easy to use you can avoid

    scopes in model (good/bad) use with AR first, then easy to migrate to API-based solution
  22. RECENT IDEAS return collections as arrays, not A R :

    : R e l a t i o n focus on optimization encapsulated it repository no more n + 1 queries? no need for relations anymore?
  23. SAMPLE SEARCH OBJECT c l a s s I d

    e a S e a r c h s e a r c h _ o n I d e a s e a r c h e s : n a m e , : p o p u l a r d e f s e a r c h _ n a m e s e a r c h . w h e r e ( n a m e : n a m e ) e n d d e f s e a r c h _ p o p u l a r s e a r c h . w h e r e ( ' u s e r s _ c o u n t > 1 0 ' ) e n d e n d s e a r c h = I d e a S e a r c h . n e w ( p o p u l a r : t r u e ) s e a r c h . r e s u l t s
  24. TYPICAL FLOW IN CONTROLLER JUST DISPLAYING THINGS get data (model)

    display data (model) VS get data (repository) display data (view object / decorator)
  25. MODEL # a r / p o s t .

    r b c l a s s P o s t < A c t i v e R e c o r d : : B a s e b e l o n g s _ t o : a u t h o r h a s _ m a n y : c o m m e n t s e n d REPOSITORY # r e p o s i t o r i e s / p o s t _ r e p o s i t o r y . r b c l a s s P o s t R e p o s i t o r y d e f a l l b a s e _ r e l a t i o n . o r d e r ( a u t h o r : : i d ) e n d p r i v a t e d e f b a s e _ r e l a t i o n P o s t . i n c l u d e s ( : c o m m e n t s , : a u t h o r ) e n d e n d
  26. VIEW OBJECT # v i e w _ o b

    j e c t s / p o s t _ v i e w . r b c l a s s P o s t V i e w a t t r _ a c c e s s o r : p o s t d e l e g a t e : t i t l e , : a u t h o r , t o : : p o s t d e f i n i t i a l i z e ( p o s t ) s e l f . p o s t = p o s t e n d d e f a u t h o r _ n a m e a u t h o r . n a m e e n d d e f a u t h o r _ a v a t a r g r a v a t a r ( a u t h o r . e m a i l ) e n d e n d
  27. CONTROLLER # c o n t r o l l

    e r s / p o s t s _ c o n t r o l l e r . r b c l a s s P o s t s C o n t r o l l e r d e f i n d e x @ p o s t s = d e c o r a t e d _ p o s t s e n d p r i v a t e d e f d e c o r a t e d _ p o s t s p o s t _ r e p o s i t o r y . a l l . m a p { | p | P o s t V i e w . n e w ( p o s t ) } e n d d e f p o s t _ r e p o s i t o r y P o s t R e p o s i t o r y . n e w e n d e n d
  28. VIEW # v i e w s / p o

    s t s / i n d e x . h a m l % h 1 A l l p o s t s % u l - @ p o s t s . e a c h d o | p o s t | % l i = p o s t . t i t l e b y = p o s t . a u t h o r _ n a m e
  29. TYPICAL SERVICE c l a s s U s e

    r s : : C r e a t e a t t r _ a c c e s s o r : e m a i l , : u s e r _ m a i l e r d e f i n i t i a l i z e ( e m a i l : , u s e r _ m a i l e r = n i l ) s e l f . e m a i l = e m a i l s e l f . u s e r _ m a i l e r = u s e r _ m a i l e r | | U s e r M a i l e r . n e w e n d d e f c a l l u s e r = c r e a t e _ d b _ u s e r ( e m a i l ) s e n d _ i n t r o _ e m a i l ( u s e r ) u s e r e n d p r i v a t e d e f c r e a t e _ d b _ u s e r ( e m a i l ) ; e n d d e f s e n d _ i n t r o _ e m a i l ( u s e r ) u s e r _ m a i l e r . i n t r o ( u s e r ) . d e l i v e r e n d e n d
  30. RESPONSE OBJECTS c l a s s R e p

    o n s e : : S u c c e s s d e f s u c c e s s ? t r u e e n d e n d c l a s s R e p o n s e : : E r r o r d e f s u c c e s s ? f a l s e e n d e n d # . . . s e r v i c e c l a s s d e f c a l l . . . R e s p o n s e : : S u c c e s s . n e w e n d
  31. CONTROLLER GETS SMALLER c l a s s U s

    e r s C o n t r o l l e r d e f c r e a t e u s e r _ c r e a t i o n = U s e r s : : C r e a t e . n e w ( p a r a m s [ : u s e r ] ) . c a l l i f u s e r _ c r e a t i o n . s u c c e s s ? r e n d e r t e x t : ' O K ' e l s e r e n d e r t e x t : ' N O T O K ' , s t a t u s : : u n p r o c e s s a b l e _ e n t i t y e n d e n d e n d
  32. SERVICES: SUMMARY pass all the dependencies use only one public

    method `call` try them as special forces to do one job particulary well plurar namespace `Users::*` - avoid namespace clashes use response objects if needed read Pewniak's blogpost
  33. ALWAYS HAVE YOUR GREENPATH COVERED WITH ACCEPTANCE TESTS remember: buisness

    is the most important thing (almost all the time)