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
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
27. PROCEDURAL
<?php
function get_db() { /* return the db conneciton */}
function user_show($user) { /* Awesome procedural code */ }
function user_fetch($user) { $db = get_db(); /* Awesome procedural code */
function user_delete($user) { $db = get_db(); /* Awesome procedural code */
function user_create($user, $data) { $db = get_db(); /* Awesome procedural co
function user_update($user, $data) { $db = get_db(); /* Awesome procedural co
function user_store_data($user, $user_data)
{
if (user_fetch($user)) {
return user_update($user, $user_data);
} else {
return user_create($user, $user_data);
}
28. ABSTRACTED
<php
class User extends Eloquent
{
// All provided by Eloquent
public static function find($id) {}
public function delete() {}
public function create($attributes) {}
public function update($attributes) {}
public function save() {}
}
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
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
<?php
class Rectangle
{
public function __construct($coords) {}
public function getCoordinates() {}
public function setCoordinates($coords) {}
public function getXX() {}
public function getXY() {}
public function getYX() {}
public function getYY() {}
public function setXX($coord) {}
public function setXY($coord) {}
public function setYX($coord) {}
public function setYY($coord) {}
34. EXAMPLE - INHERITED
<?php
class Square extends Rectangle {}
class Diamond extends Rectangle {}
class Rectangle
{
public function __construct($coords) {}
public function getCoordinates() {}
public function setCoordinates($coords) {}
public function getXX() {}
public function getXY() {}
public function getYX() {}
public function getYY() {}
public function setXX($coord) {}
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!"
37. EXAMPLE W/ TYPE HINTING
<php
interface Widget
{
public function render() {}
}
class BlogPostWidget implements Widget
{
public function render() {}
}
class GalleryWidget implements Widget
{
public function render() {}
}
class PollWidget implements Widget
38. HOW IS THIS USABLE?
Phill Sparks and Fabien showed you yesterday!
Pay attention!
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
selfnever worked like it should've
staticis what selfwanted to be
selfwill call the class the method was defined on, not the
subclass you likely expecting
statichowever will
42. EXAMPLE
<php
class A
{
public function sadface()
{
return new self();
}
public function happyface()
{
return new static();
}
}
class B extends A {}
$b = new B();
$b->sadface(); // A object
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
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
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
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
58. EXAMPLE - AUTHORITY
<php
protected $dispatcher;
public function __construct($currentUser, $dispatcher = null)
{
$this->rules = new RuleRepository;
$this->setDispatcher($dispatcher);
$this->setCurrentUser($currentUser);
$this->dispatch('authority.initialized', array(
'user' => $this->getCurrentUser(),
));
}
public function dispatch($eventName, $payload = array())
{
if ($this->dispatcher) {
return $this->dispatcher->fire($eventName, $payload);
59. EXAMPLE - AUTHORITY TESTS
<php
public function testInitializeEvent()
{
$test = new stdClass;
$user = new stdClass;
$user->name = 'Tester';
$this->dispatcher->listen('authority.initialized', function($payload
$test->user = $payload->user;
$test->timestamp = $payload->timestamp;
});
$authority = new Authority($user, $this->dispatcher);
$this->assertSame($test->user, $user);
$this->assertInstanceOf('DateTime', $test->timestamp);
}
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
<php
testFoo()
{
$foo = new Foo();
$bar = new Bar();
$baz = $foo->doSomethingEpic($bar);
if (is_array($baz) and !is_empty($baz)) {
$this->assertTrue(true);
} else {
$this->assertFalse(true);
}
}
62. SOME MORE THINGS ON TESTING
Nor this
<php
testSomething()
{
$foo = new Foo();
$bar = new Bar();
$baz = $foo->doSomethingEpic($bar);
// Baz doesn't seem to eval right, passing for now
// @TODO: Come back later
$this->assertTrue(true);
}
63. SOME MORE THINGS ON TESTING
Nor this
<php
testStringReverse()
{
$str = new AwesomeString();
$string = 'Hello';
// Implementation: return strrev($string)
$reversed = $str->reverseString($string);
$this->assertEquals(strrev($string), $reversed);
}
64. SOME MORE THINGS ON TESTING
Nor this...I don't even...
<php
testWeirdFeature()
{
// 2 + 2 should be 4
if (2+2 == 3) {
$this->assertTrue(true);
} else {
$this->assertTrue(false);
}
}
65. CAN IT BE CLEANED UP?
ABSOLUTELY! BUT IT WORKS!
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