SlideShare a Scribd company logo
OOP is More Than Cars
and Dogs
Chris Tankersley
Midwest PHP 2017
Midwest PHP 2017 1
Quick Vocabulary Lesson
• Class – Definition of code
• Object – Instantiation of a Class
• Member/Property – Variable belonging to a class
• Method – Function belonging to a class
There will be more as we go along
Midwest PHP 2017 2
Midwest PHP 2017 3
Class
class Employee {
protected $name; // This is a member
protected $number;
// This is a Method
public function setData($data) {
$this->name = $data['name'];
$this->number = $data['number'];
}
public function viewData() {
echo <<<ENDTEXT
Name: {$this->name}
Number: {$this->number}
ENDTEXT;
}
}
Object
<?php
$manager= new Manager();
// ^
// |
// `--- This is the Object
Midwest PHP 2017 4
Why are we using OOP?
Midwest PHP 2017 5
Let’s count the reasons
• Because we’re told to, procedural programming leads to spaghetti
code
• We deal with objects every day, so it shouldn’t be too hard
• We want to allow for code re-use
• We want to group like code together
• We want to easily extend our code
• We want to be able to easily test our code
Midwest PHP 2017 6
Getting OOP Right is Complicated
Midwest PHP 2017 7
Midwest PHP 2017 8
Midwest PHP 2017 9
Midwest PHP 2017 10
Midwest PHP 2017 11
Midwest PHP 2017 12
Midwest PHP 2017 13
Can a Dog have Wheels?
Midwest PHP 2017 14
Inheritance
Midwest PHP 2017 15
What we’re all taught
• Classes are “things” in the real world
• We should construct class members based on Attributes
• Number of wheels
• Sound it makes
• We should construct class methods based on “Actions”
• Running
• Speaking
• Jumping
Midwest PHP 2017 16
New Vocabulary
• Parent Class – Class that is extended
• Child Class – Class that is extending another class
In PHP, a class can be both a Child and a Parent at the same time
Midwest PHP 2017 17
Where I Learned It
Midwest PHP 2017 18
Our Structure
Midwest PHP 2017 19
Employee
Manager Scientist Laborer
The Employee Class
Midwest PHP 2017 20
abstract class Employee {
protected $name; // Employee Name
protected $number; // Employee Number
public function setData($data) {
$this->name = $data['name'];
$this->number = $data['number'];
}
public function viewData() {
echo <<<ENDTEXT
Name: {$this->name}
Number: {$this->number}
ENDTEXT;
}
}
The Manager Class
Midwest PHP 2017 21
class Manager extends Employee {
protected $title; // Employee Title
protected $dues; // Golf Dues
public function setData($data) {
parent::setData($data);
$this->title = $data['title'];
$this->dues = $data['dues'];
}
public function viewData() {
parent::viewData();
echo <<<ENDTEXT
Title: {$this->title}
Golf Dues: {$this->dues}
ENDTEXT;
}
}
The Scientist Class
Midwest PHP 2017 22
class Scientist extends Employee {
protected $pubs; // Number of Publications
public function setData($data) {
parent::setData($data);
$this->pubs = $data['pubs'];
}
public function viewData() {
parent::viewData();
echo <<<ENDTEXT
Publications: {$this->pubs}
ENDTEXT;
}
}
The Laborer Class
Midwest PHP 2017 23
class Laborer extends Employee {
}
What does this teach us?
• Inheritance
• Makes it easier to group code together and share it amongst classes
• Allows us to extend code as needed
• PHP allows Single inheritance
Midwest PHP 2017 24
We use it all the time
namespace ApplicationController;
use ZendMvcControllerAbstractActionController;
use ZendViewModelViewModel;
Class IndexController extends AbstractActionController {
public function indexAction() {
/** @var VendorVendorService $vendor */
$vendor = $this->serviceLocator->get('VendorVendorService');
$view = new ViewModel();
return $view;
}
} Midwest PHP 2017 25
Why it Works (Most of the time, Kinda)
• Allows us to extend things we didn’t necessarily create
• Encourages code re-use
• Allows developers to abstract away things
Midwest PHP 2017 26
How to use it
• Understand the difference between Public, Protected, and Private
• Public – Anyone can use this, even children
• Protected – Anything internal can use this, even children
• Private – This is mine, hands off
• Abstract vs Concrete Classes
• Abstract classes cannot be instantiated directly, they must be extended
Midwest PHP 2017 27
The Employee Class
Midwest PHP 2017 28
abstract class Employee {
protected $name; // Employee Name
protected $number; // Employee Number
public function setData($data) {
$this->name = $data['name'];
$this->number = $data['number'];
}
public function viewData() {
echo <<<ENDTEXT
Name: {$this->name}
Number: {$this->number}
ENDTEXT;
}
}
The Manager Class
Midwest PHP 2017 29
class Manager extends Employee {
protected $title; // Employee Title
protected $dues; // Golf Dues
public function setData($data) {
parent::setData($data);
$this->title = $data['title'];
$this->dues = $data['dues'];
}
public function viewData() {
parent::viewData();
echo <<<ENDTEXT
Title: {$this->title}
Golf Dues: {$this->dues}
ENDTEXT;
}
}
An Example
// Fatal error: Cannot instantiate abstract class Employee
$employee = new Employee();
// We can do this though!
$manager = new Manager();
// Fatal error: Cannot access protected property Manager::$name
$manager->name = 'Bob McManager’;
// setData is public, so we can use that
$manager->setData(['name' => 'Bob McManager’,'number' => 1]);
// We can also view the data, since it's public
$manager->viewData();
Midwest PHP 2017 30
Why can Inheritance Be Bad
• PHP only allows Single Inheritance on an Class
• You can have a series of Inheritance though, for example CEO extends
Manager, Manager extends Employee
• Long inheritance chains can be a code smell
• Private members and methods cannot be used by Child classes
• Single Inheritance can make it hard to ‘bolt on’ new functionality
between disparate classes
Midwest PHP 2017 31
Composition over Inheritance
Midwest PHP 2017 32
The General Idea
• Classes contain other classes to do work and extend that way, instead
of through Inheritance
• Interfaces define “contracts” that objects will adhere to
• Your classes implement interfaces to add needed functionality
Midwest PHP 2017 33
Interfaces
interface EmployeeInterface {
protected $name;
protected $number;
public function getName();
public function setName($name);
public function getNumber();
public function setNumber($number);
}
interface ManagerInterface {
protected $golfHandicap;
public function getHandicap();
public function setHandicap($handicap);
}
Midwest PHP 2017 34
Interface Implementation
class Employee implements EmployeeInterface {
public function getName() {
return $this->name;
}
public function setName($name) {
$this->name = $name;
}
}
class Manager implements EmployeeInterface, ManagerInterface {
// defines the employee getters/setters as well
public function getHandicap() {
return $this->handicap;
}
public function setHandicap($handicap) {
$this->handicap = $handicap;
}
}
Midwest PHP 2017 35
This is Good and Bad
• “HAS-A” is tends to be more flexible than “IS-A”
• Somewhat easier to understand, since there isn’t a hierarchy you
have to backtrack
• Each class must provide their own Implementation, so can lead to
code duplication
Midwest PHP 2017 36
Traits
• Allows small blocks of code to be defined that can be used by many
classes
• Useful when abstract classes/inheritance would be cumbersome
• My Posts and Pages classes shouldn’t need to extend a Slugger class just to
generate slugs.
Midwest PHP 2017 37
Avoid Code-Duplication with Traits
trait EmployeeTrait {
public function getName() {
return $this->name;
}
public function setName($name) {
$this->name = $name;
}
}
class Employee implements EmployeeInterface {
use EmployeeTrait;
}
class Manager implements EmployeeInterface, ManagerInterface {
use EmployeeTrait;
use ManagerTrait;
}
Midwest PHP 2017 38
Taking Advantage of OOP
Midwest PHP 2017 39
Coupling
Midwest PHP 2017 40
What is Coupling?
• Coupling is how dependent your code is on another class
• The more classes you are coupled to, the more changes affect your
class
Midwest PHP 2017 41
namespace ApplicationController;
use ZendMvcControllerAbstractActionController;
use ZendViewModelViewModel;
class MapController extends AbstractActionController
{
public function indexAction()
{
// Position is an array with a Latitude and Longitude object
$position = $this->getServiceLocator()->get('MapService’)
->getLatLong('123 Main Street', 'Defiance', 'OH');
echo $position->latitude->getPoint();
}
}
Midwest PHP 2017 42
Law of Demeter
Midwest PHP 2017 43
Dependency Injection
Midwest PHP 2017 44
What is Dependency Injection?
• Injecting dependencies into classes, instead of having the class create
it
• Allows for much easier testing
• Allows for a much easier time swapping out code
• Reduces the coupling that happens between classes
Midwest PHP 2017 45
Method Injection
class MapService {
public function getLatLong(GoogleMaps $map, $street, $city, $state) {
return $map->getLatLong($street . ' ' . $city . ' ' . $state);
}
public function getAddress(GoogleMaps $map, $lat, $long) {
return $map->getAddress($lat, $long);
}
}
Midwest PHP 2017 46
Constructor Injection
class MapService {
protected $map;
public function __construct(GoogleMaps $map) {
$this->map = $map;
}
public function getLatLong($street, $city, $state) {
return $this
->map
->getLatLong($street . ' ' . $city . ' ' . $state);
}
}
Midwest PHP 2017 47
Setter Injection
class MapService {
protected $map;
public function setMap(GoogleMaps $map) {
$this->map = $map;
}
public function getMap() {
return $this->map;
}
public function getLatLong($street, $city, $state) {
return $this->getMap()->getLatLong($street . ' ' . $city . ' ' . $state);
}
}
Midwest PHP 2017 48
Single Responsibility Principle
Midwest PHP 2017 49
Single Responsibility Principle
• Every class should have a single responsibility, and that responsibility
should be encapsulated in that class
Midwest PHP 2017 50
What is a Responsibility?
• Responsibility is a “Reason To Change” – Robert C. Martin
• By having more than one “Reason to Change”, code is harder to
maintain and becomes coupled
• Since the class is coupled to multiple responsibilities, it becomes
harder for the class to adapt to any one responsibility
Midwest PHP 2017 51
An Example
/**
* Create a new invoice instance.
*
* @param LaravelCashierContractsBillable $billable
* @param object
* @return void
*/
public function __construct(BillableContract $billable, $invoice)
{
$this->billable = $billable;
$this->files = new Filesystem;
$this->stripeInvoice = $invoice;
}
/**
* Create an invoice download response.
*
* @param array $data
* @param string $storagePath
* @return SymfonyComponentHttpFoundationResponse
*/
public function download(array $data, $storagePath = null)
{
$filename = $this->getDownloadFilename($data['product']);
$document = $this->writeInvoice($data, $storagePath);
$response = new Response($this->files->get($document), 200, [
'Content-Description' => 'File Transfer',
'Content-Disposition' => 'attachment; filename="'.$filename.'"',
'Content-Transfer-Encoding' => 'binary',
'Content-Type' => 'application/pdf',
]);
$this->files->delete($document);
return $response;
}
Midwest PHP 2017 52
https://github.com/laravel/cashier/blob/5.0/src/Laravel/Cashier/Invoice.php
Why is this Bad?
• This single class has the following responsibilities:
• Generating totals for the invoice (including discounts/coupons)
• Generating an HTML View of the invoice (Invoice::view())
• Generating a PDF download of the invoice(Invoice::download())
• This is coupled to a shell script as well
• Two different displays handled by the class. Adding more means more
responsibility
• Coupled to a specific HTML template, the filesystem, the Laravel
Views system, and PhantomJS via the shell script
Midwest PHP 2017 53
How to Improve
• Change responsibility to just building the invoice data
• Move the ‘output’ stuff to other classes
Midwest PHP 2017 54
Unit Testing
Midwest PHP 2017 55
Test Driven Development
• Write your tests
• Watch them fail
• Write code to make the tests pass
• Feel better! (and refactor)
Midwest PHP 2017 56
This is not a testing talk
• Using Interfaces makes it easier to mock objects
• Reducing coupling and following Demeter’s Law makes you have to
mock less objects
• Dependency Injection means you only mock what you need for that
test
• Single Responsibility means your test should be short and sweet
• Easier testing leads to more testing
Midwest PHP 2017 57
Final Thoughts
Midwest PHP 2017 58
We can make a dog with wheels!
• Abstract class for Animal
• Class for Dog that extends Animal
• Trait for Wheels
• With the correct methodology, we could even unit test this
As in the real world, we can now represent a crippled dog
Midwest PHP 2017 59
Here’s a cute dog instead
Midwest PHP 2017 60
Additional Resources
• Clean Code – Robert C. Martin
• PHP Objects, Patterns, and Practice – Matt Zandstra
Midwest PHP 2017 61
Thank You!
• Software Engineer for InQuest
• Author of “Docker for Developers”
• https://leanpub.com/dockerfordevs
• Co-Host of “Jerks Talk Games”
• http://jerkstalkgames
• http://ctankersley.com
• chris@ctankersley.com
• @dragonmantank
SunshinePHP 2017 62
Photos
• Slide 9 - http://bit.ly/1dkaoxS
• Slide 10 - http://bit.ly/1c4Gc8z
• Slide 11 - http://bit.ly/1R3isBp
• Slide 12 - http://bit.ly/1ScEWRZ
• Slide 13 - http://bit.ly/1Bc0qUv
• Slide 14 - http://bit.ly/1ILhfNV
• Slide 15 - http://bit.ly/1SeekA7
Midwest PHP 2017 63

More Related Content

PPTX
OOP Is More Than Cars and Dogs
PDF
Advanced Php - Macq Electronique 2010
PDF
Dependency Injection
PDF
Vision academy classes bcs_bca_bba_sybba_php
PPTX
Coming to Terms with OOP In Drupal - php[world] 2016
PDF
OOP Is More Than Cars and Dogs
PDF
PHPID online Learning #6 Migration from procedural to OOP
PDF
Dependency injection in Drupal 8
OOP Is More Than Cars and Dogs
Advanced Php - Macq Electronique 2010
Dependency Injection
Vision academy classes bcs_bca_bba_sybba_php
Coming to Terms with OOP In Drupal - php[world] 2016
OOP Is More Than Cars and Dogs
PHPID online Learning #6 Migration from procedural to OOP
Dependency injection in Drupal 8

What's hot (20)

PDF
OOP in PHP
PDF
Cfphp Zce 01 Basics
PDF
Benchmarking Perl (Chicago UniForum 2006)
PDF
The IoC Hydra
PDF
Business Rules with Brick
PDF
Fantastic DSL in Python
PDF
CGI::Prototype (NPW 2006)
PDF
Design Patterns in PHP5
ODP
Rich domain model with symfony 2.5 and doctrine 2.5
PDF
Forget about index.php and build you applications around HTTP!
ODP
Symfony2, creare bundle e valore per il cliente
PDF
Advanced php testing in action
PDF
Models and Service Layers, Hemoglobin and Hobgoblins
PDF
PHP Benelux 2012: Magic behind the numbers. Software metrics in practice
PDF
The IoC Hydra - Dutch PHP Conference 2016
PDF
The art of readable code (ch1~ch4)
PDF
OOP is more than Cars and Dogs
PDF
PHP Conference Asia 2016
PDF
Practice exam php
PDF
The Art Of Readable Code
OOP in PHP
Cfphp Zce 01 Basics
Benchmarking Perl (Chicago UniForum 2006)
The IoC Hydra
Business Rules with Brick
Fantastic DSL in Python
CGI::Prototype (NPW 2006)
Design Patterns in PHP5
Rich domain model with symfony 2.5 and doctrine 2.5
Forget about index.php and build you applications around HTTP!
Symfony2, creare bundle e valore per il cliente
Advanced php testing in action
Models and Service Layers, Hemoglobin and Hobgoblins
PHP Benelux 2012: Magic behind the numbers. Software metrics in practice
The IoC Hydra - Dutch PHP Conference 2016
The art of readable code (ch1~ch4)
OOP is more than Cars and Dogs
PHP Conference Asia 2016
Practice exam php
The Art Of Readable Code
Ad

Viewers also liked (20)

PPTX
How to Make Your Website Not Ugly: 10 Simple UX Tenets for Non-Designers
PPT
What does OOP stand for?
PPT
Object-oriented concepts
PDF
Midwest PHP 2017 DevOps For Small team
PDF
Expressive Microservice Framework Blastoff
PPTX
From Docker to Production - SunshinePHP 2017
PPS
Jump start to OOP, OOAD, and Design Pattern
PPTX
Standards: Don't pee in the pool
PPT
Java basic understand OOP
PDF
Los Angeles R users group - July 12 2011 - Part 2
PDF
Beginning OOP in PHP
PPT
Introduction to OOP with PHP
PDF
Practical PHP Deployment with Jenkins
PDF
Design patterns revisited with PHP 5.3
PPT
OOP in Java
PPTX
Java 8 new features
KEY
Object Relational Mapping in PHP
DOC
Lập trình c++ có lời giải 2
ODP
ORM, JPA, & Hibernate Overview
DOC
Lap trinh c++ có lời giải 1
How to Make Your Website Not Ugly: 10 Simple UX Tenets for Non-Designers
What does OOP stand for?
Object-oriented concepts
Midwest PHP 2017 DevOps For Small team
Expressive Microservice Framework Blastoff
From Docker to Production - SunshinePHP 2017
Jump start to OOP, OOAD, and Design Pattern
Standards: Don't pee in the pool
Java basic understand OOP
Los Angeles R users group - July 12 2011 - Part 2
Beginning OOP in PHP
Introduction to OOP with PHP
Practical PHP Deployment with Jenkins
Design patterns revisited with PHP 5.3
OOP in Java
Java 8 new features
Object Relational Mapping in PHP
Lập trình c++ có lời giải 2
ORM, JPA, & Hibernate Overview
Lap trinh c++ có lời giải 1
Ad

Similar to OOP Is More Then Cars and Dogs - Midwest PHP 2017 (20)

PDF
PHP: 4 Design Patterns to Make Better Code
PDF
PHP 5.3 Overview
PDF
Migration from Procedural to OOP
PDF
Why is crud a bad idea - focus on real scenarios
PDF
Phpspec tips&amp;tricks
PDF
Demystifying Object-Oriented Programming - PHP[tek] 2017
PPT
Reflection-In-PHP
PDF
Drupaljam xl 2019 presentation multilingualism makes better programmers
KEY
Unit testing zend framework apps
PDF
What's New In Laravel 5
PDF
PHPSpec BDD Framework
PDF
Solid principles
PPT
Part 2
PPTX
Ch8(oop)
PPTX
Drupal 8 migrate!
PPTX
12-OO-PHP.pptx
ODP
PHP Data Objects
PDF
Effective PHP. Part 3
ZIP
Object Oriented PHP5
PPTX
Php on the desktop and php gtk2
PHP: 4 Design Patterns to Make Better Code
PHP 5.3 Overview
Migration from Procedural to OOP
Why is crud a bad idea - focus on real scenarios
Phpspec tips&amp;tricks
Demystifying Object-Oriented Programming - PHP[tek] 2017
Reflection-In-PHP
Drupaljam xl 2019 presentation multilingualism makes better programmers
Unit testing zend framework apps
What's New In Laravel 5
PHPSpec BDD Framework
Solid principles
Part 2
Ch8(oop)
Drupal 8 migrate!
12-OO-PHP.pptx
PHP Data Objects
Effective PHP. Part 3
Object Oriented PHP5
Php on the desktop and php gtk2

More from Chris Tankersley (20)

PDF
8 Rules for Better Applications - PHP Tek 2025
PDF
The Art of API Design - PHP Tek 2025, Chris Tankersley
PDF
Docker is Dead: Long Live Containers
PDF
Bend time to your will with git
PDF
Using PHP Functions! (Not those functions, Google Cloud Functions)
PDF
Dead Simple APIs with OpenAPI
PDF
Killer Docker Workflows for Development
PDF
You Got Async in my PHP!
ODP
Docker for Developers - PHP Detroit 2018
ODP
Docker for Developers
ODP
They are Watching You
ODP
BASHing at the CLI - Midwest PHP 2018
PDF
You Were Lied To About Optimization
ODP
Docker for PHP Developers - php[world] 2017
ODP
Docker for PHP Developers - Madison PHP 2017
ODP
Docker for Developers - php[tek] 2017
ODP
Why Docker? Dayton PHP, April 2017
PPTX
Docker for Developers - Sunshine PHP
PPTX
How We Got Here: A Brief History of Open Source
PPTX
Docker for PHP Developers - ZendCon 2016
8 Rules for Better Applications - PHP Tek 2025
The Art of API Design - PHP Tek 2025, Chris Tankersley
Docker is Dead: Long Live Containers
Bend time to your will with git
Using PHP Functions! (Not those functions, Google Cloud Functions)
Dead Simple APIs with OpenAPI
Killer Docker Workflows for Development
You Got Async in my PHP!
Docker for Developers - PHP Detroit 2018
Docker for Developers
They are Watching You
BASHing at the CLI - Midwest PHP 2018
You Were Lied To About Optimization
Docker for PHP Developers - php[world] 2017
Docker for PHP Developers - Madison PHP 2017
Docker for Developers - php[tek] 2017
Why Docker? Dayton PHP, April 2017
Docker for Developers - Sunshine PHP
How We Got Here: A Brief History of Open Source
Docker for PHP Developers - ZendCon 2016

Recently uploaded (20)

PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Unlocking AI with Model Context Protocol (MCP)
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PPTX
Chapter 5: Probability Theory and Statistics
PPTX
Programs and apps: productivity, graphics, security and other tools
PPTX
1. Introduction to Computer Programming.pptx
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PDF
Transform Your ITIL® 4 & ITSM Strategy with AI in 2025.pdf
PPTX
A Presentation on Touch Screen Technology
PDF
Approach and Philosophy of On baking technology
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PPTX
Tartificialntelligence_presentation.pptx
PDF
Zenith AI: Advanced Artificial Intelligence
PPTX
A Presentation on Artificial Intelligence
PDF
Enhancing emotion recognition model for a student engagement use case through...
PDF
August Patch Tuesday
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
DASA ADMISSION 2024_FirstRound_FirstRank_LastRank.pdf
PDF
Hybrid model detection and classification of lung cancer
PDF
From MVP to Full-Scale Product A Startup’s Software Journey.pdf
Building Integrated photovoltaic BIPV_UPV.pdf
Unlocking AI with Model Context Protocol (MCP)
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Chapter 5: Probability Theory and Statistics
Programs and apps: productivity, graphics, security and other tools
1. Introduction to Computer Programming.pptx
Agricultural_Statistics_at_a_Glance_2022_0.pdf
Transform Your ITIL® 4 & ITSM Strategy with AI in 2025.pdf
A Presentation on Touch Screen Technology
Approach and Philosophy of On baking technology
MIND Revenue Release Quarter 2 2025 Press Release
Tartificialntelligence_presentation.pptx
Zenith AI: Advanced Artificial Intelligence
A Presentation on Artificial Intelligence
Enhancing emotion recognition model for a student engagement use case through...
August Patch Tuesday
Digital-Transformation-Roadmap-for-Companies.pptx
DASA ADMISSION 2024_FirstRound_FirstRank_LastRank.pdf
Hybrid model detection and classification of lung cancer
From MVP to Full-Scale Product A Startup’s Software Journey.pdf

OOP Is More Then Cars and Dogs - Midwest PHP 2017

  • 1. OOP is More Than Cars and Dogs Chris Tankersley Midwest PHP 2017 Midwest PHP 2017 1
  • 2. Quick Vocabulary Lesson • Class – Definition of code • Object – Instantiation of a Class • Member/Property – Variable belonging to a class • Method – Function belonging to a class There will be more as we go along Midwest PHP 2017 2
  • 3. Midwest PHP 2017 3 Class class Employee { protected $name; // This is a member protected $number; // This is a Method public function setData($data) { $this->name = $data['name']; $this->number = $data['number']; } public function viewData() { echo <<<ENDTEXT Name: {$this->name} Number: {$this->number} ENDTEXT; } }
  • 4. Object <?php $manager= new Manager(); // ^ // | // `--- This is the Object Midwest PHP 2017 4
  • 5. Why are we using OOP? Midwest PHP 2017 5
  • 6. Let’s count the reasons • Because we’re told to, procedural programming leads to spaghetti code • We deal with objects every day, so it shouldn’t be too hard • We want to allow for code re-use • We want to group like code together • We want to easily extend our code • We want to be able to easily test our code Midwest PHP 2017 6
  • 7. Getting OOP Right is Complicated Midwest PHP 2017 7
  • 14. Can a Dog have Wheels? Midwest PHP 2017 14
  • 16. What we’re all taught • Classes are “things” in the real world • We should construct class members based on Attributes • Number of wheels • Sound it makes • We should construct class methods based on “Actions” • Running • Speaking • Jumping Midwest PHP 2017 16
  • 17. New Vocabulary • Parent Class – Class that is extended • Child Class – Class that is extending another class In PHP, a class can be both a Child and a Parent at the same time Midwest PHP 2017 17
  • 18. Where I Learned It Midwest PHP 2017 18
  • 19. Our Structure Midwest PHP 2017 19 Employee Manager Scientist Laborer
  • 20. The Employee Class Midwest PHP 2017 20 abstract class Employee { protected $name; // Employee Name protected $number; // Employee Number public function setData($data) { $this->name = $data['name']; $this->number = $data['number']; } public function viewData() { echo <<<ENDTEXT Name: {$this->name} Number: {$this->number} ENDTEXT; } }
  • 21. The Manager Class Midwest PHP 2017 21 class Manager extends Employee { protected $title; // Employee Title protected $dues; // Golf Dues public function setData($data) { parent::setData($data); $this->title = $data['title']; $this->dues = $data['dues']; } public function viewData() { parent::viewData(); echo <<<ENDTEXT Title: {$this->title} Golf Dues: {$this->dues} ENDTEXT; } }
  • 22. The Scientist Class Midwest PHP 2017 22 class Scientist extends Employee { protected $pubs; // Number of Publications public function setData($data) { parent::setData($data); $this->pubs = $data['pubs']; } public function viewData() { parent::viewData(); echo <<<ENDTEXT Publications: {$this->pubs} ENDTEXT; } }
  • 23. The Laborer Class Midwest PHP 2017 23 class Laborer extends Employee { }
  • 24. What does this teach us? • Inheritance • Makes it easier to group code together and share it amongst classes • Allows us to extend code as needed • PHP allows Single inheritance Midwest PHP 2017 24
  • 25. We use it all the time namespace ApplicationController; use ZendMvcControllerAbstractActionController; use ZendViewModelViewModel; Class IndexController extends AbstractActionController { public function indexAction() { /** @var VendorVendorService $vendor */ $vendor = $this->serviceLocator->get('VendorVendorService'); $view = new ViewModel(); return $view; } } Midwest PHP 2017 25
  • 26. Why it Works (Most of the time, Kinda) • Allows us to extend things we didn’t necessarily create • Encourages code re-use • Allows developers to abstract away things Midwest PHP 2017 26
  • 27. How to use it • Understand the difference between Public, Protected, and Private • Public – Anyone can use this, even children • Protected – Anything internal can use this, even children • Private – This is mine, hands off • Abstract vs Concrete Classes • Abstract classes cannot be instantiated directly, they must be extended Midwest PHP 2017 27
  • 28. The Employee Class Midwest PHP 2017 28 abstract class Employee { protected $name; // Employee Name protected $number; // Employee Number public function setData($data) { $this->name = $data['name']; $this->number = $data['number']; } public function viewData() { echo <<<ENDTEXT Name: {$this->name} Number: {$this->number} ENDTEXT; } }
  • 29. The Manager Class Midwest PHP 2017 29 class Manager extends Employee { protected $title; // Employee Title protected $dues; // Golf Dues public function setData($data) { parent::setData($data); $this->title = $data['title']; $this->dues = $data['dues']; } public function viewData() { parent::viewData(); echo <<<ENDTEXT Title: {$this->title} Golf Dues: {$this->dues} ENDTEXT; } }
  • 30. An Example // Fatal error: Cannot instantiate abstract class Employee $employee = new Employee(); // We can do this though! $manager = new Manager(); // Fatal error: Cannot access protected property Manager::$name $manager->name = 'Bob McManager’; // setData is public, so we can use that $manager->setData(['name' => 'Bob McManager’,'number' => 1]); // We can also view the data, since it's public $manager->viewData(); Midwest PHP 2017 30
  • 31. Why can Inheritance Be Bad • PHP only allows Single Inheritance on an Class • You can have a series of Inheritance though, for example CEO extends Manager, Manager extends Employee • Long inheritance chains can be a code smell • Private members and methods cannot be used by Child classes • Single Inheritance can make it hard to ‘bolt on’ new functionality between disparate classes Midwest PHP 2017 31
  • 33. The General Idea • Classes contain other classes to do work and extend that way, instead of through Inheritance • Interfaces define “contracts” that objects will adhere to • Your classes implement interfaces to add needed functionality Midwest PHP 2017 33
  • 34. Interfaces interface EmployeeInterface { protected $name; protected $number; public function getName(); public function setName($name); public function getNumber(); public function setNumber($number); } interface ManagerInterface { protected $golfHandicap; public function getHandicap(); public function setHandicap($handicap); } Midwest PHP 2017 34
  • 35. Interface Implementation class Employee implements EmployeeInterface { public function getName() { return $this->name; } public function setName($name) { $this->name = $name; } } class Manager implements EmployeeInterface, ManagerInterface { // defines the employee getters/setters as well public function getHandicap() { return $this->handicap; } public function setHandicap($handicap) { $this->handicap = $handicap; } } Midwest PHP 2017 35
  • 36. This is Good and Bad • “HAS-A” is tends to be more flexible than “IS-A” • Somewhat easier to understand, since there isn’t a hierarchy you have to backtrack • Each class must provide their own Implementation, so can lead to code duplication Midwest PHP 2017 36
  • 37. Traits • Allows small blocks of code to be defined that can be used by many classes • Useful when abstract classes/inheritance would be cumbersome • My Posts and Pages classes shouldn’t need to extend a Slugger class just to generate slugs. Midwest PHP 2017 37
  • 38. Avoid Code-Duplication with Traits trait EmployeeTrait { public function getName() { return $this->name; } public function setName($name) { $this->name = $name; } } class Employee implements EmployeeInterface { use EmployeeTrait; } class Manager implements EmployeeInterface, ManagerInterface { use EmployeeTrait; use ManagerTrait; } Midwest PHP 2017 38
  • 39. Taking Advantage of OOP Midwest PHP 2017 39
  • 41. What is Coupling? • Coupling is how dependent your code is on another class • The more classes you are coupled to, the more changes affect your class Midwest PHP 2017 41
  • 42. namespace ApplicationController; use ZendMvcControllerAbstractActionController; use ZendViewModelViewModel; class MapController extends AbstractActionController { public function indexAction() { // Position is an array with a Latitude and Longitude object $position = $this->getServiceLocator()->get('MapService’) ->getLatLong('123 Main Street', 'Defiance', 'OH'); echo $position->latitude->getPoint(); } } Midwest PHP 2017 42
  • 43. Law of Demeter Midwest PHP 2017 43
  • 45. What is Dependency Injection? • Injecting dependencies into classes, instead of having the class create it • Allows for much easier testing • Allows for a much easier time swapping out code • Reduces the coupling that happens between classes Midwest PHP 2017 45
  • 46. Method Injection class MapService { public function getLatLong(GoogleMaps $map, $street, $city, $state) { return $map->getLatLong($street . ' ' . $city . ' ' . $state); } public function getAddress(GoogleMaps $map, $lat, $long) { return $map->getAddress($lat, $long); } } Midwest PHP 2017 46
  • 47. Constructor Injection class MapService { protected $map; public function __construct(GoogleMaps $map) { $this->map = $map; } public function getLatLong($street, $city, $state) { return $this ->map ->getLatLong($street . ' ' . $city . ' ' . $state); } } Midwest PHP 2017 47
  • 48. Setter Injection class MapService { protected $map; public function setMap(GoogleMaps $map) { $this->map = $map; } public function getMap() { return $this->map; } public function getLatLong($street, $city, $state) { return $this->getMap()->getLatLong($street . ' ' . $city . ' ' . $state); } } Midwest PHP 2017 48
  • 50. Single Responsibility Principle • Every class should have a single responsibility, and that responsibility should be encapsulated in that class Midwest PHP 2017 50
  • 51. What is a Responsibility? • Responsibility is a “Reason To Change” – Robert C. Martin • By having more than one “Reason to Change”, code is harder to maintain and becomes coupled • Since the class is coupled to multiple responsibilities, it becomes harder for the class to adapt to any one responsibility Midwest PHP 2017 51
  • 52. An Example /** * Create a new invoice instance. * * @param LaravelCashierContractsBillable $billable * @param object * @return void */ public function __construct(BillableContract $billable, $invoice) { $this->billable = $billable; $this->files = new Filesystem; $this->stripeInvoice = $invoice; } /** * Create an invoice download response. * * @param array $data * @param string $storagePath * @return SymfonyComponentHttpFoundationResponse */ public function download(array $data, $storagePath = null) { $filename = $this->getDownloadFilename($data['product']); $document = $this->writeInvoice($data, $storagePath); $response = new Response($this->files->get($document), 200, [ 'Content-Description' => 'File Transfer', 'Content-Disposition' => 'attachment; filename="'.$filename.'"', 'Content-Transfer-Encoding' => 'binary', 'Content-Type' => 'application/pdf', ]); $this->files->delete($document); return $response; } Midwest PHP 2017 52 https://github.com/laravel/cashier/blob/5.0/src/Laravel/Cashier/Invoice.php
  • 53. Why is this Bad? • This single class has the following responsibilities: • Generating totals for the invoice (including discounts/coupons) • Generating an HTML View of the invoice (Invoice::view()) • Generating a PDF download of the invoice(Invoice::download()) • This is coupled to a shell script as well • Two different displays handled by the class. Adding more means more responsibility • Coupled to a specific HTML template, the filesystem, the Laravel Views system, and PhantomJS via the shell script Midwest PHP 2017 53
  • 54. How to Improve • Change responsibility to just building the invoice data • Move the ‘output’ stuff to other classes Midwest PHP 2017 54
  • 56. Test Driven Development • Write your tests • Watch them fail • Write code to make the tests pass • Feel better! (and refactor) Midwest PHP 2017 56
  • 57. This is not a testing talk • Using Interfaces makes it easier to mock objects • Reducing coupling and following Demeter’s Law makes you have to mock less objects • Dependency Injection means you only mock what you need for that test • Single Responsibility means your test should be short and sweet • Easier testing leads to more testing Midwest PHP 2017 57
  • 59. We can make a dog with wheels! • Abstract class for Animal • Class for Dog that extends Animal • Trait for Wheels • With the correct methodology, we could even unit test this As in the real world, we can now represent a crippled dog Midwest PHP 2017 59
  • 60. Here’s a cute dog instead Midwest PHP 2017 60
  • 61. Additional Resources • Clean Code – Robert C. Martin • PHP Objects, Patterns, and Practice – Matt Zandstra Midwest PHP 2017 61
  • 62. Thank You! • Software Engineer for InQuest • Author of “Docker for Developers” • https://leanpub.com/dockerfordevs • Co-Host of “Jerks Talk Games” • http://jerkstalkgames • http://ctankersley.com • chris@ctankersley.com • @dragonmantank SunshinePHP 2017 62
  • 63. Photos • Slide 9 - http://bit.ly/1dkaoxS • Slide 10 - http://bit.ly/1c4Gc8z • Slide 11 - http://bit.ly/1R3isBp • Slide 12 - http://bit.ly/1ScEWRZ • Slide 13 - http://bit.ly/1Bc0qUv • Slide 14 - http://bit.ly/1ILhfNV • Slide 15 - http://bit.ly/1SeekA7 Midwest PHP 2017 63