Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

ONLINE: MACHUGA IRC: machuga GitHub: machuga Twitter: @machuga I WEAR MANY HATS IN IRC "Have you checked the docs first?"

Slide 4

Slide 4 text

MORE MACHUGA'S HALI AND VAEDA VIM

Slide 5

Slide 5 text

THINK THROUGH LEARNING THINK THROUGH MATH HELP KIDS LEARN MATH SENIOR SOFTWARE DEVELOPER I HAVE THE BEST COWORKERS EVER!

Slide 6

Slide 6 text

BEFORE WE BEGIN... LARAVEL COMMUNITY! THANK YOU, YOU'RE ALL AMAZING!

Slide 7

Slide 7 text

OBJECTS, TESTING, AND RESPONSIBILITY WAT

Slide 8

Slide 8 text

OBJECTS Object Oriented Programming Object Oriented Design Pro's and Con's Improvements to code

Slide 9

Slide 9 text

TESTING Correlation between good OOD and good tests Tests are good No, seriously. Tests are good. Stop hating.

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

OBJECTS

Slide 12

Slide 12 text

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"

Slide 13

Slide 13 text

OBJECT-ORIENTED PROGRAMMING Originated from Functional and Procedural Solution to code organization, data-hiding, reuse Solution to easier testing Solution to structure and protocols

Slide 14

Slide 14 text

PHP'S OOP HISTORY

Slide 15

Slide 15 text

QUESTION Which version of PHP first gained objects? PHP 3

Slide 16

Slide 16 text

OOP: OBJECT ORIENTED PHP THE LIVE ACTION SERIES

Slide 17

Slide 17 text

OOP: OBJECT ORIENTED PHP 16 years and 4 days ago: PHP codebase gets classes PHP 3 released in 1998 Associative Array ++

Slide 18

Slide 18 text

OOP: OBJECT ORIENTED PHP PHP 3 & 4 CAPABILITIES Classes Objects Simple single inheritance Pass-by-value All public visibility

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

OOP: OBJECT ORIENTED PHP PHP 5.3 ENHANCEMENTS Usable single inheritance! Late Static Binding Namespaces Closures

Slide 21

Slide 21 text

OOP: OBJECT ORIENTED PHP PHP 5.3 ANTIPATTERNS g o t o No full namespace import

Slide 22

Slide 22 text

OOP: OBJECT ORIENTED PHP PHP 5.4 ENHANCEMENTS Traits Closure Rebinding

Slide 23

Slide 23 text

IT TOOK ABOUT 14 YEARS But we now have a very capable object model in PHP

Slide 24

Slide 24 text

THE FOUR PILLARS OF OOP

Slide 25

Slide 25 text

ABSTRACTION Remove and isolate related behavior or data Responsibility

Slide 26

Slide 26 text

EXAMPLES

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

EXAMPLE...KIND OF

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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!"

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

HOW IS THIS USABLE? Phill Sparks and Fabien showed you yesterday! Pay attention!

Slide 39

Slide 39 text

DESIGN PATTERNS Finding common patterns in code and making it reusable Take advantage of OO constructs

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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 ) {

Slide 45

Slide 45 text

GET THE MOST OUT OF YOUR OBJECTS

Slide 46

Slide 46 text

TELL, DON'T ASK Tell your objects what you want them to do Don't ask them data about themselves. Remember: Black box

Slide 47

Slide 47 text

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?"

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

TESTING

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

TDD CYCLE Red Green Refactor

Slide 53

Slide 53 text

FULL TDD CYCLE Red Red Green Refactor Green Refactor

Slide 54

Slide 54 text

BASE TESTS OFF ACCEPTANCE CRITERIA Stakeholders want their features You want the features to work You want to guarantee your unit tests come together

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

DON'T BE AFRAID TO ADD MORE OBJECTS/CLASSES

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

CAN IT BE CLEANED UP? ABSOLUTELY! BUT IT WORKS!

Slide 66

Slide 66 text

RESPONSIBILITY

Slide 67

Slide 67 text

RESPONSIBILITY You have a responsibility not to make tests like what I've just shown

Slide 68

Slide 68 text

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

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

QUESTIONS?

Slide 71

Slide 71 text

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