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

Objects, Testing, and Responsibility

Objects, Testing, and Responsibility

Talk from Laracon EU on August 31, 2013. Style issues due to reveal.js output.

8f9f6a577da77a9add9cadbb90e66b75?s=128

Matthew Machuga

August 31, 2013
Tweet

Transcript

  1. OBJECTS, TESTING, AND RESPONSIBILITY MATTHEW MACHUGA LARACON EU AUGUST 2013

  2. HI, I'M MATT MACHUGA! SOFTWARE DEVELOPER RUBY | JS |

    PHP
  3. ONLINE: MACHUGA IRC: machuga GitHub: machuga Twitter: @machuga I WEAR

    MANY HATS IN IRC "Have you checked the docs first?"
  4. MORE MACHUGA'S HALI AND VAEDA VIM

  5. THINK THROUGH LEARNING THINK THROUGH MATH HELP KIDS LEARN MATH

    SENIOR SOFTWARE DEVELOPER I HAVE THE BEST COWORKERS EVER!
  6. BEFORE WE BEGIN... LARAVEL COMMUNITY! THANK YOU, YOU'RE ALL AMAZING!

  7. OBJECTS, TESTING, AND RESPONSIBILITY WAT

  8. OBJECTS Object Oriented Programming Object Oriented Design Pro's and Con's

    Improvements to code
  9. TESTING Correlation between good OOD and good tests Tests are

    good No, seriously. Tests are good. Stop hating.
  10. RESPONSIBILITY See also: Accountability Holding components accountable Giving objects explicit

    responsibilities 1:1 Object:Responsibility Ratio (when possible) Responsibilty to code Responsibilty to team Responsibilty to your future self
  11. OBJECTS

  12. Alan Kay Father of OOP "I thought of objects being

    like biological cells and/or individual computers on a network, only able to communicate with messages"
  13. OBJECT-ORIENTED PROGRAMMING Originated from Functional and Procedural Solution to code

    organization, data-hiding, reuse Solution to easier testing Solution to structure and protocols
  14. PHP'S OOP HISTORY

  15. QUESTION Which version of PHP first gained objects? PHP 3

  16. OOP: OBJECT ORIENTED PHP THE LIVE ACTION SERIES

  17. OOP: OBJECT ORIENTED PHP 16 years and 4 days ago:

    PHP codebase gets classes PHP 3 released in 1998 Associative Array ++
  18. OOP: OBJECT ORIENTED PHP PHP 3 & 4 CAPABILITIES Classes

    Objects Simple single inheritance Pass-by-value All public visibility
  19. OOP: OBJECT ORIENTED PHP PHP 5.0 - 5.2.X ENHANCEMENTS Pass-by-reference

    p u b l i c / p r i v a t e / p r o t e c t e d visibility Static methods/properties Class constants __construct() Destructors Abstract and Final classes Interfaces
  20. OOP: OBJECT ORIENTED PHP PHP 5.3 ENHANCEMENTS Usable single inheritance!

    Late Static Binding Namespaces Closures
  21. OOP: OBJECT ORIENTED PHP PHP 5.3 ANTIPATTERNS g o t

    o No full namespace import
  22. OOP: OBJECT ORIENTED PHP PHP 5.4 ENHANCEMENTS Traits Closure Rebinding

  23. IT TOOK ABOUT 14 YEARS But we now have a

    very capable object model in PHP
  24. THE FOUR PILLARS OF OOP

  25. ABSTRACTION Remove and isolate related behavior or data Responsibility

  26. EXAMPLES

  27. PROCEDURAL < ? p h p f u n c

    t i o n g e t _ d b ( ) { / * r e t u r n t h e d b c o n n e c i t o n * / } f u n c t i o n u s e r _ s h o w ( $ u s e r ) { / * A w e s o m e p r o c e d u r a l c o d e * / } f u n c t i o n u s e r _ f e t c h ( $ u s e r ) { $ d b = g e t _ d b ( ) ; / * A w e s o m e p r o c e d u r a l c o d e * / f u n c t i o n u s e r _ d e l e t e ( $ u s e r ) { $ d b = g e t _ d b ( ) ; / * A w e s o m e p r o c e d u r a l c o d e * / f u n c t i o n u s e r _ c r e a t e ( $ u s e r , $ d a t a ) { $ d b = g e t _ d b ( ) ; / * A w e s o m e p r o c e d u r a l c o f u n c t i o n u s e r _ u p d a t e ( $ u s e r , $ d a t a ) { $ d b = g e t _ d b ( ) ; / * A w e s o m e p r o c e d u r a l c o f u n c t i o n u s e r _ s t o r e _ d a t a ( $ u s e r , $ u s e r _ d a t a ) { i f ( u s e r _ f e t c h ( $ u s e r ) ) { r e t u r n u s e r _ u p d a t e ( $ u s e r , $ u s e r _ d a t a ) ; } e l s e { r e t u r n u s e r _ c r e a t e ( $ u s e r , $ u s e r _ d a t a ) ; }
  28. ABSTRACTED < p h p c l a s s

    U s e r e x t e n d s E l o q u e n t { / / A l l p r o v i d e d b y E l o q u e n t p u b l i c s t a t i c f u n c t i o n f i n d ( $ i d ) { } p u b l i c f u n c t i o n d e l e t e ( ) { } p u b l i c f u n c t i o n c r e a t e ( $ a t t r i b u t e s ) { } p u b l i c f u n c t i o n u p d a t e ( $ a t t r i b u t e s ) { } p u b l i c f u n c t i o n s a v e ( ) { } }
  29. ENCAPSULATION Keep data and behavior in a black box Use

    a public interface to interact with the black box Much like a function - data in, data out Prevents leaky abstractions
  30. EXAMPLE...KIND OF

  31. ILLUMINATE\DATABASE\ELOQUENT\MODEL PROPERTIES 4 Public Instance/Class 19 Protected Instance/Class 0 Private

    Instance/Class METHODS 126 Public Instance/Class 25 Protected Instance/Class 0 Private Instance/Class
  32. INHERITANCE The double edged sword Allows classes to be extended

    from other classes Properties and methods can ascend the ancestry Saves a lot of code
  33. EXAMPLE - PLAIN CLASSES < ? p h p c

    l a s s R e c t a n g l e { p u b l i c f u n c t i o n _ _ c o n s t r u c t ( $ c o o r d s ) { } p u b l i c f u n c t i o n g e t C o o r d i n a t e s ( ) { } p u b l i c f u n c t i o n s e t C o o r d i n a t e s ( $ c o o r d s ) { } p u b l i c f u n c t i o n g e t X X ( ) { } p u b l i c f u n c t i o n g e t X Y ( ) { } p u b l i c f u n c t i o n g e t Y X ( ) { } p u b l i c f u n c t i o n g e t Y Y ( ) { } p u b l i c f u n c t i o n s e t X X ( $ c o o r d ) { } p u b l i c f u n c t i o n s e t X Y ( $ c o o r d ) { } p u b l i c f u n c t i o n s e t Y X ( $ c o o r d ) { } p u b l i c f u n c t i o n s e t Y Y ( $ c o o r d ) { }
  34. EXAMPLE - INHERITED < ? p h p c l

    a s s S q u a r e e x t e n d s R e c t a n g l e { } c l a s s D i a m o n d e x t e n d s R e c t a n g l e { } c l a s s R e c t a n g l e { p u b l i c f u n c t i o n _ _ c o n s t r u c t ( $ c o o r d s ) { } p u b l i c f u n c t i o n g e t C o o r d i n a t e s ( ) { } p u b l i c f u n c t i o n s e t C o o r d i n a t e s ( $ c o o r d s ) { } p u b l i c f u n c t i o n g e t X X ( ) { } p u b l i c f u n c t i o n g e t X Y ( ) { } p u b l i c f u n c t i o n g e t Y X ( ) { } p u b l i c f u n c t i o n g e t Y Y ( ) { } p u b l i c f u n c t i o n s e t X X ( $ c o o r d ) { }
  35. POLYMORPHISM Probably the best feature of OOP Any object may

    be used if it implements expected method/property Allows code branching without if/else logic PHP is a duck typed language - "If it walks like a duck" PHP also allows type hinting - "You will be a duck and you will like it!"
  36. EXAMPLE < p h p c l a s s

    B l o g P o s t W i d g e t { p u b l i c f u n c t i o n r e n d e r ( ) { } } c l a s s G a l l e r y W i d g e t { p u b l i c f u n c t i o n r e n d e r ( ) { } } c l a s s P o l l W i d g e t { p u b l i c f u n c t i o n r e n d e r ( ) { } }
  37. EXAMPLE W/ TYPE HINTING < p h p i n

    t e r f a c e W i d g e t { p u b l i c f u n c t i o n r e n d e r ( ) { } } c l a s s B l o g P o s t W i d g e t i m p l e m e n t s W i d g e t { p u b l i c f u n c t i o n r e n d e r ( ) { } } c l a s s G a l l e r y W i d g e t i m p l e m e n t s W i d g e t { p u b l i c f u n c t i o n r e n d e r ( ) { } } c l a s s P o l l W i d g e t i m p l e m e n t s W i d g e t
  38. HOW IS THIS USABLE? Phill Sparks and Fabien showed you

    yesterday! Pay attention!
  39. DESIGN PATTERNS Finding common patterns in code and making it

    reusable Take advantage of OO constructs
  40. CODE REUSE AND EXTENSIBILITY Proper abstraction leads to reusable code

    Fluent Class in Laravel 3 as an example (not the DB one) Validators in Laravel Drivers
  41. LATE-STATIC BINDING s e l f never worked like it

    should've s t a t i c is what s e l f wanted to be s e l f will call the class the method was defined on, not the subclass you likely expecting s t a t i c however will
  42. EXAMPLE < p h p c l a s s

    A { p u b l i c f u n c t i o n s a d f a c e ( ) { r e t u r n n e w s e l f ( ) ; } p u b l i c f u n c t i o n h a p p y f a c e ( ) { r e t u r n n e w s t a t i c ( ) ; } } c l a s s B e x t e n d s A { } $ b = n e w B ( ) ; $ b - > s a d f a c e ( ) ; / / A o b j e c t
  43. TRAITS Traits allow for methods/properties to be added to a

    class at compile-time Not quite mixins, but close In a sense, allows for multiple inheritance This scares people Not always the right solution, but often suited Another great form of reusable abstraction
  44. EXAMPLE < p h p t r a i t

    B a r { p r o t e c t e d $ b a z ; p u b l i c f u n c t i o n b a z ( ) { r e t u r n $ t h i s - > b a z ; } } c l a s s F o o { u s e B a r ; p u b l i c f u n c t i o n s e t B a z ( $ b a z ) {
  45. GET THE MOST OUT OF YOUR OBJECTS

  46. TELL, DON'T ASK Tell your objects what you want them

    to do Don't ask them data about themselves. Remember: Black box
  47. COMPOSITION OVER INHERITANCE Composing two or more objects together The

    sum is greater than the parts Provides more flexibility Not always the right solution, but often the better suited More code to compose (usually) "Does X belong on this object?"
  48. COMPOSITION WITH TRAITS SOME PEOPLE REALLY HATE TRAITS Traits allow

    for methods/properties to be added to a class at compile-time Not quite mixins, but close In a sense, allows for multiple inheritance This scares people Not always the right solution, but often the better suited Another great form of reusable abstraction
  49. TESTING

  50. TESTING CAN BE HARD ESPECIALLY IF YOU'RE MAKING IT HARD

  51. TDD SERVES MANY PURPOSES Guiding you to make well abstracted

    solutions Help you write the least code possible Ensure your code works Ensure your code works as it is intended Ensure tests become executable documentation for your code and acceptance criteria
  52. TDD CYCLE Red Green Refactor

  53. FULL TDD CYCLE Red Red Green Refactor Green Refactor

  54. BASE TESTS OFF ACCEPTANCE CRITERIA Stakeholders want their features You

    want the features to work You want to guarantee your unit tests come together
  55. TDD IS NOT THE ONLY WAY Tests don't need to

    drive or guide your code Testing after is perfectly reasonable BUT ALWAYS LISTEN TO YOUR TESTS
  56. LISTENING TO TESTS Tests will let you know if somethign

    smells funny A class that does too many things is hard to test A test with too many dependencies is hard to test A test with too many mocks is hard to mantain A test that is too difficult is easy to abandon
  57. DON'T BE AFRAID TO ADD MORE OBJECTS/CLASSES

  58. EXAMPLE - AUTHORITY < p h p p r o

    t e c t e d $ d i s p a t c h e r ; p u b l i c f u n c t i o n _ _ c o n s t r u c t ( $ c u r r e n t U s e r , $ d i s p a t c h e r = n u l l ) { $ t h i s - > r u l e s = n e w R u l e R e p o s i t o r y ; $ t h i s - > s e t D i s p a t c h e r ( $ d i s p a t c h e r ) ; $ t h i s - > s e t C u r r e n t U s e r ( $ c u r r e n t U s e r ) ; $ t h i s - > d i s p a t c h ( ' a u t h o r i t y . i n i t i a l i z e d ' , a r r a y ( ' u s e r ' = > $ t h i s - > g e t C u r r e n t U s e r ( ) , ) ) ; } p u b l i c f u n c t i o n d i s p a t c h ( $ e v e n t N a m e , $ p a y l o a d = a r r a y ( ) ) { i f ( $ t h i s - > d i s p a t c h e r ) { r e t u r n $ t h i s - > d i s p a t c h e r - > f i r e ( $ e v e n t N a m e , $ p a y l o a d ) ;
  59. EXAMPLE - AUTHORITY TESTS < p h p p u

    b l i c f u n c t i o n t e s t I n i t i a l i z e E v e n t ( ) { $ t e s t = n e w s t d C l a s s ; $ u s e r = n e w s t d C l a s s ; $ u s e r - > n a m e = ' T e s t e r ' ; $ t h i s - > d i s p a t c h e r - > l i s t e n ( ' a u t h o r i t y . i n i t i a l i z e d ' , f u n c t i o n ( $ p a y l o a d $ t e s t - > u s e r = $ p a y l o a d - > u s e r ; $ t e s t - > t i m e s t a m p = $ p a y l o a d - > t i m e s t a m p ; } ) ; $ a u t h o r i t y = n e w A u t h o r i t y ( $ u s e r , $ t h i s - > d i s p a t c h e r ) ; $ t h i s - > a s s e r t S a m e ( $ t e s t - > u s e r , $ u s e r ) ; $ t h i s - > a s s e r t I n s t a n c e O f ( ' D a t e T i m e ' , $ t e s t - > t i m e s t a m p ) ; }
  60. SOME THINGS ON TESTING You do not need a test

    for every method Sometimes you need more than one test for a method Mocking can fall short and lose sync. If you don't test everything, test areas of high churn Do not reach for AspectMock right away because something is hard Test your own code, not third party
  61. SOME MORE THINGS ON TESTING This is not a good

    test < p h p t e s t F o o ( ) { $ f o o = n e w F o o ( ) ; $ b a r = n e w B a r ( ) ; $ b a z = $ f o o - > d o S o m e t h i n g E p i c ( $ b a r ) ; i f ( i s _ a r r a y ( $ b a z ) a n d ! i s _ e m p t y ( $ b a z ) ) { $ t h i s - > a s s e r t T r u e ( t r u e ) ; } e l s e { $ t h i s - > a s s e r t F a l s e ( t r u e ) ; } }
  62. SOME MORE THINGS ON TESTING Nor this < p h

    p t e s t S o m e t h i n g ( ) { $ f o o = n e w F o o ( ) ; $ b a r = n e w B a r ( ) ; $ b a z = $ f o o - > d o S o m e t h i n g E p i c ( $ b a r ) ; / / B a z d o e s n ' t s e e m t o e v a l r i g h t , p a s s i n g f o r n o w / / @ T O D O : C o m e b a c k l a t e r $ t h i s - > a s s e r t T r u e ( t r u e ) ; }
  63. SOME MORE THINGS ON TESTING Nor this < p h

    p t e s t S t r i n g R e v e r s e ( ) { $ s t r = n e w A w e s o m e S t r i n g ( ) ; $ s t r i n g = ' H e l l o ' ; / / I m p l e m e n t a t i o n : r e t u r n s t r r e v ( $ s t r i n g ) $ r e v e r s e d = $ s t r - > r e v e r s e S t r i n g ( $ s t r i n g ) ; $ t h i s - > a s s e r t E q u a l s ( s t r r e v ( $ s t r i n g ) , $ r e v e r s e d ) ; }
  64. SOME MORE THINGS ON TESTING Nor this...I don't even... <

    p h p t e s t W e i r d F e a t u r e ( ) { / / 2 + 2 s h o u l d b e 4 i f ( 2 + 2 = = 3 ) { $ t h i s - > a s s e r t T r u e ( t r u e ) ; } e l s e { $ t h i s - > a s s e r t T r u e ( f a l s e ) ; } }
  65. CAN IT BE CLEANED UP? ABSOLUTELY! BUT IT WORKS!

  66. RESPONSIBILITY

  67. RESPONSIBILITY You have a responsibility not to make tests like

    what I've just shown
  68. RESPONSIBILITY: OBJECTS Give your objects a task Do not overwork

    your objects Give your objects some proper tests Like profiling and logging, objects can help with accountability
  69. RESPONSIBILITY: YOU You have a responsibility to yourself You have

    a responsibility to your team You have a responsibility to your consumers You have a responsibility to your future self Become responsible and be accountable for your code
  70. QUESTIONS?

  71. THANK YOU! IRC: machuga GitHub: machuga Twitter: @machuga