229
Copyright © 2009 thePHP.cc, Germany Advanced OOP and Design Patterns Stefan Priebsch thePHP.cc CodeWorks 09

Advanced OOP and Design Patterns

Embed Size (px)

DESCRIPTION

Stefan Priebsch's slides from Codeworks 2009

Citation preview

Page 1: Advanced OOP and Design Patterns

Copyright © 2009 thePHP.cc, Germany

Advanced OOPand Design Patterns

Stefan PriebschthePHP.cc

CodeWorks 09

Page 2: Advanced OOP and Design Patterns

Premium PHP Consulting & Training. Worldwide.

ArneBlankerts

Sebastian Bergmann

StefanPriebsch

Page 3: Advanced OOP and Design Patterns

WhyWhy OOP?OOP?

Page 4: Advanced OOP and Design Patterns

<?php header('Content-Type: text/html; charset=' .$GLOBALS['charset']); ?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php echo $lang_iso_code; ?>" lang="<?php echo $lang_iso_code; ?>" dir="<?php echo $GLOBALS['text_dir']; ?>"><head><link rel="icon" href="./favicon.ico" type="image/x-icon" /><title>phpMyAdmin <?php echo PMA_VERSION; ?> -<?php echo htmlspecialchars($HTTP_HOST); ?></title><meta http-equiv="Content-Type" content="text/html; charset=<?php echo $GLOBALS['charset']; ?>" /><meta name="robots" content="noindex,nofollow" /><script type="text/javascript">window.onload = function() { if (onloadCnt == 0) { if (typeof(onLoadHandler) == "function") { onLoadHandler(); } };</script><script src="./js/common.js" type="text/javascript"></script></head><?php $query = "select `postId`,`filename`,`filesize`,`imgId` from `tiki_blog_posts_images` where `postId`=?";$result = $this->query($query,array((int) $postId));$ret = array();while ($res = $result->fetchRow()) { $imgId = $res['imgId']; $res['link'] = "<img src='tiki-view_blog_post_image.php?imgId=$imgId' border='0' alt='image' />"; $parts = parse_url($_SERVER['REQUEST_URI']); $path = str_replace('tiki-blog_post.php', 'tiki-view_blog_post_image.php', $parts['path']); $res['absolute'] = $tikilib->httpPrefix(). $path . "?imgId=$imgId"; $ret[] = $res;} return $ret; } ?><?php if ($GLOBALS['text_dir'] === 'ltr') { ?><frame frameborder="0" id="frame_navigation" src="navigation.php<?php echo $url_query; ?>" name="frame_navigation" /><?php } ?><frame frameborder="0" id="frame_content" src="<?php echo $main_target; ?>" name="frame_content" /><?php if ($GLOBALS['text_dir'] === 'rtl') { ?><frame frameborder="0" id="frame_navigation" src="navigation.php<?php echo $url_query; ?>" name="frame_navigation" /><?php } ?><noframes><body><p><?php echo $GLOBALS['strNoFrames']; ?></p></body></noframes></frameset></html>

PHPPHP

HTMLHTML

SQLSQL

Page 5: Advanced OOP and Design Patterns

<?php header('Content-Type: text/html; charset=' .$GLOBALS['charset']); ?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php echo $lang_iso_code; ?>" lang="<?php echo $lang_iso_code; ?>" dir="<?php echo $GLOBALS['text_dir']; ?>"><head><link rel="icon" href="./favicon.ico" type="image/x-icon" /><title>phpMyAdmin <?php echo PMA_VERSION; ?> -<?php echo htmlspecialchars($HTTP_HOST); ?></title><meta http-equiv="Content-Type" content="text/html; charset=<?php echo $GLOBALS['charset']; ?>" /><meta name="robots" content="noindex,nofollow" /><script type="text/javascript">window.onload = function() { if (onloadCnt == 0) { if (typeof(onLoadHandler) == "function") { onLoadHandler(); } };</script><script src="./js/common.js" type="text/javascript"></script></head><?php $query = "select `postId`,`filename`,`filesize`,`imgId` from `tiki_blog_posts_images` where `postId`=?";$result = $this->query($query,array((int) $postId));$ret = array();while ($res = $result->fetchRow()) { $imgId = $res['imgId']; $res['link'] = "<img src='tiki-view_blog_post_image.php?imgId=$imgId' border='0' alt='image' />"; $parts = parse_url($_SERVER['REQUEST_URI']); $path = str_replace('tiki-blog_post.php', 'tiki-view_blog_post_image.php', $parts['path']); $res['absolute'] = $tikilib->httpPrefix(). $path . "?imgId=$imgId"; $ret[] = $res;} return $ret; } ?><?php if ($GLOBALS['text_dir'] === 'ltr') { ?><frame frameborder="0" id="frame_navigation" src="navigation.php<?php echo $url_query; ?>" name="frame_navigation" /><?php } ?><frame frameborder="0" id="frame_content" src="<?php echo $main_target; ?>" name="frame_content" /><?php if ($GLOBALS['text_dir'] === 'rtl') { ?><frame frameborder="0" id="frame_navigation" src="navigation.php<?php echo $url_query; ?>" name="frame_navigation" /><?php } ?><noframes><body><p><?php echo $GLOBALS['strNoFrames']; ?></p></body></noframes></frameset></html>

PHPPHP

HTMLHTML

SQLSQL

Page 6: Advanced OOP and Design Patterns

<?php header('Content-Type: text/html; charset=' .$GLOBALS['charset']); ?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php echo $lang_iso_code; ?>" lang="<?php echo $lang_iso_code; ?>" dir="<?php echo $GLOBALS['text_dir']; ?>"><head><link rel="icon" href="./favicon.ico" type="image/x-icon" /><title>phpMyAdmin <?php echo PMA_VERSION; ?> -<?php echo htmlspecialchars($HTTP_HOST); ?></title><meta http-equiv="Content-Type" content="text/html; charset=<?php echo $GLOBALS['charset']; ?>" /><meta name="robots" content="noindex,nofollow" /><script type="text/javascript">window.onload = function() { if (onloadCnt == 0) { if (typeof(onLoadHandler) == "function") { onLoadHandler(); } };</script><script src="./js/common.js" type="text/javascript"></script></head><?php $query = "select `postId`,`filename`,`filesize`,`imgId` from `tiki_blog_posts_images` where `postId`=?";$result = $this->query($query,array((int) $postId));$ret = array();while ($res = $result->fetchRow()) { $imgId = $res['imgId']; $res['link'] = "<img src='tiki-view_blog_post_image.php?imgId=$imgId' border='0' alt='image' />"; $parts = parse_url($_SERVER['REQUEST_URI']); $path = str_replace('tiki-blog_post.php', 'tiki-view_blog_post_image.php', $parts['path']); $res['absolute'] = $tikilib->httpPrefix(). $path . "?imgId=$imgId"; $ret[] = $res;} return $ret; } ?><?php if ($GLOBALS['text_dir'] === 'ltr') { ?><frame frameborder="0" id="frame_navigation" src="navigation.php<?php echo $url_query; ?>" name="frame_navigation" /><?php } ?><frame frameborder="0" id="frame_content" src="<?php echo $main_target; ?>" name="frame_content" /><?php if ($GLOBALS['text_dir'] === 'rtl') { ?><frame frameborder="0" id="frame_navigation" src="navigation.php<?php echo $url_query; ?>" name="frame_navigation" /><?php } ?><noframes><body><p><?php echo $GLOBALS['strNoFrames']; ?></p></body></noframes></frameset></html>

PHPPHP

HTMLHTML

SQLSQL

Page 7: Advanced OOP and Design Patterns

PHPPHP

HTMLHTML

SQLSQL

Page 8: Advanced OOP and Design Patterns

PresentationPresentation

LogicLogic

Data AccessData Access

Page 9: Advanced OOP and Design Patterns

Separation ofSeparation ofConcernsConcerns

Page 10: Advanced OOP and Design Patterns

Good OOP starts Good OOP starts before classesbefore classescome into playcome into play

Page 11: Advanced OOP and Design Patterns

Do weDo weneed OOP?need OOP?

Page 12: Advanced OOP and Design Patterns

IF-GOTO programsIF-GOTO programs

Page 13: Advanced OOP and Design Patterns

LOOP programsLOOP programs

Page 14: Advanced OOP and Design Patterns

WHILE programsWHILE programs

Page 15: Advanced OOP and Design Patterns

IF-GOTO andIF-GOTO andWHILE programsWHILE programsare equally powerful.are equally powerful.

Page 16: Advanced OOP and Design Patterns

Every WHILE programEvery WHILE programcan be simulated by acan be simulated by aWHILE program withWHILE program withonly one while loop.only one while loop.

Page 17: Advanced OOP and Design Patterns

OOP isOOP issyntactical sugarsyntactical sugar

Page 18: Advanced OOP and Design Patterns

Then Why OOP?Then Why OOP?

Page 19: Advanced OOP and Design Patterns

ReadabilityReadability

Page 20: Advanced OOP and Design Patterns

class BlogPosting{ public function addComment(Comment $comment)}

Page 21: Advanced OOP and Design Patterns

class BlogPosting{ public function addComment(Comment $comment) { $this->comments[] = $comment; }}

Page 22: Advanced OOP and Design Patterns

class BlogPosting{ public function addComment(Comment $comment) { $this->comments[] = $comment;

if ($comment->getAuthor()->isRegistered()) { $comment->setApproved(true); } }}

Page 23: Advanced OOP and Design Patterns

EncapsulationEncapsulation

Page 24: Advanced OOP and Design Patterns

Keeping SecretsKeeping Secrets

Page 25: Advanced OOP and Design Patterns

InterfaceInterfaceand and

ImplementationImplementation

Page 26: Advanced OOP and Design Patterns

$email->send();$email->send();

$pdf->generate();$pdf->generate();

Page 27: Advanced OOP and Design Patterns

MaintainabilityMaintainability

Page 28: Advanced OOP and Design Patterns

Source: Barry Boehm: „EQUITY Keynote Address“, March 19th, 2007Source: Barry Boehm: „EQUITY Keynote Address“, March 19th, 2007

DesignDesign CodeCodeReqReq DevTDevT OpsOps

Rela

tive C

ost

of

a B

ug

fix

Rela

tive C

ost

of

a B

ug

fix

1x1x 5x5x10x10x

20x20x

50x50x

AccTAccT

>150x>150x

Page 29: Advanced OOP and Design Patterns

ExtensibilityExtensibility

Page 30: Advanced OOP and Design Patterns

class Customer{ protected $discount = 0;

public function getDiscount() { return $this->discount; }}

Page 31: Advanced OOP and Design Patterns

class PremiumCustomer extends Customer{ protected $discount = 5;}

Page 32: Advanced OOP and Design Patterns

class PremiumCustomer extends Customer{ protected $discount = 5;

public function getDiscount() { if ($this->signupYear < 2003) { return 10; }

if ($this->getTotalRevenue() > 100000) { return 10; }

return parent::getDiscount(); }}

Page 33: Advanced OOP and Design Patterns

class PremiumCustomer extends Customer{ protected $discount = 5;

public function getDiscount() { if ($this->fulfilsYearCriterion() || $this->fulfilsRevenueCriterion()) {

return 10; }

return parent::getDiscount(); }

...}

Page 34: Advanced OOP and Design Patterns

class PremiumCustomer extends Customer{ ...

protected function fulfilsYearCriterion() { return $this->signupYear < 2003; }

protected function fulfilsRevenueCriterion() { return $this->getTotalRevenue() > 100000; }

...}

Page 35: Advanced OOP and Design Patterns

class PremiumCustomer extends Customer{ protected $specialDiscount= 10;

public function getDiscount() { if ($this->fulfilsYearCriterion() || $this->fulfilsRevenueCriterion()) {

return $this->specialDiscount; }

return parent::getDiscount(); }}

Page 36: Advanced OOP and Design Patterns

class MostValuedCustomer extends PremiumCustomer{ protected $discount = 10; protected $specialDiscount= 20;}

Page 37: Advanced OOP and Design Patterns

ReusabilityReusability

Page 38: Advanced OOP and Design Patterns

Only isolated andOnly isolated andloosely coupledloosely coupled

classes are reusable.classes are reusable.

Page 39: Advanced OOP and Design Patterns

MaintainabilityMaintainability

Page 40: Advanced OOP and Design Patterns

Is OOP slow?Is OOP slow?

Page 41: Advanced OOP and Design Patterns

Benchmark results are different on every system.Benchmark results are different on every system.

foo() foo() 3.09 µsec3.09 µsec

Test::foo() 3.26 µsec

$test->foo() 3.12 µsec

$test = new Test();$test->foo() 4.03 µsec

Page 42: Advanced OOP and Design Patterns

25% slower!25% slower!

Page 43: Advanced OOP and Design Patterns

1 µsec1 µsec

Page 44: Advanced OOP and Design Patterns

Benchmark results are different on every system.Benchmark results are different on every system.

print ~ 10 µsec

file_get_contents() ~ 30 µsec

mysql_connect() ~ 100 µsec

HTTP GET Request ~ 35,000 µsec

Page 45: Advanced OOP and Design Patterns

I/O is whereI/O is wherethe action is.the action is.

Page 46: Advanced OOP and Design Patterns

OOP is fast OOP is fast enough.enough.

Page 47: Advanced OOP and Design Patterns

Dealing with Dealing with DependenciesDependencies

Page 48: Advanced OOP and Design Patterns

DecouplingDecoupling

Page 49: Advanced OOP and Design Patterns

DependenciesDependencieson Constantson Constants

Page 50: Advanced OOP and Design Patterns

define('BASEPATH', '/some/absolute/path');...

class Something{ public function loadData() { $this->data = file_get_contents(BASEPATH . '/file.ext'); }}

...$something = new Something();$something->loadData();

Page 51: Advanced OOP and Design Patterns

class Something{ protected $basePath = BASEPATH; public function loadData() { $this->data = file_get_contents($this->basePath . '/file.ext'); }}

Page 52: Advanced OOP and Design Patterns

class Something{ protected $basePath = BASEPATH; public function setBasePath($basePath) { $this->basePath = $basePath; }

public function loadData() { $this->data = file_get_contents($this->basePath . '/file.ext'); }}

Page 53: Advanced OOP and Design Patterns

$something = new Something();$something->setBasePath(BASEPATH);$something->loadData();

Page 54: Advanced OOP and Design Patterns

class Something{ protected $basePath; public function setBasePath($basePath) { $this->basePath = $basePath; }

public function loadData() { $this->data = file_get_contents($this->basePath . '/file.ext'); }}

Page 55: Advanced OOP and Design Patterns

class Something{ protected $basePath; public function setBasePath($basePath) { $this->basePath = $basePath; }

public function loadData() { if (is_null($this->basePath)) { throw new RuntimeException('No basepath set'); }

$this->data = file_get_contents($this->basePath . '/file.ext'); }}

Page 56: Advanced OOP and Design Patterns

class Something{ protected $basePath; public function __construct($basePath) { $this->basePath = $basePath; }

public function loadData() { if (is_null($this->basePath)) { throw new RuntimeException('No basepath set'); }

$this->data = file_get_contents($this->basePath . '/file.ext'); }}

Page 57: Advanced OOP and Design Patterns

Files are also a Files are also a dependencydependency

Page 58: Advanced OOP and Design Patterns

class Something{ public function __construct($data) { $this->data = $data; }}

Page 59: Advanced OOP and Design Patterns

Dependencies on Dependencies on Global VariablesGlobal Variables

Page 60: Advanced OOP and Design Patterns

class Something{ public function loadData() { global $dsn;

… load data from database ... }}

Page 61: Advanced OOP and Design Patterns

class Something{ public function loadData($dsn) { … load data from database ... }}

Page 62: Advanced OOP and Design Patterns

class Something{ protected $dsn;

public function __construct($dsn) { $this->dsn = $dsn; }

public function loadData() { … load data from database ... }}

Page 63: Advanced OOP and Design Patterns

class Something{ protected $dbAdapter;

public function __construct(DatabaseAdapter $dbAdapter) { $this->dbAdapter = $dbAdapter; }}

Page 64: Advanced OOP and Design Patterns

Dependency Dependency InjectionInjection

Page 65: Advanced OOP and Design Patterns

class Something{ protected $dbAdapter;

public function __construct(DatabaseAdapter $dbAdapter) { $this->dbAdapter = $dbAdapter; }

public function loadData() { … ask somebody else to load data from database ... }}

Page 66: Advanced OOP and Design Patterns

DelegationDelegation

Page 67: Advanced OOP and Design Patterns

Let othersLet othersdo the work.do the work.

Page 68: Advanced OOP and Design Patterns

class DatabaseAdapter{ protected $dsn;

public function __construct($dsn) { $this->dsn = $dsn; }}

Page 69: Advanced OOP and Design Patterns

$dbAdapter = new DatabaseAdapter();

$something = new Something($dbAdapter);$something->doWork();

Page 70: Advanced OOP and Design Patterns

class DummyDatabaseAdapter extends DatabaseAdapter{}

$dbAdapter = new DummyDatabaseAdapter();

$something = new Something($dbAdapter);$something->doWork();

Page 71: Advanced OOP and Design Patterns

class Something{ protected $dbAdapter;

public function __construct(DatabaseAdapter $dbAdapter = null) { if (is_null($dbAdapter)) { $dbAdapter = new DefaultDatabaseAdapter(); }

$this->dbAdapter = $dbAdapter; }

public function loadData() { … load data from database ... }}

Page 72: Advanced OOP and Design Patterns

DependenciesDependencieson Functionson Functions

Page 73: Advanced OOP and Design Patterns

class Something{ public function doWork() { ... global_function(...); ... }}

Page 74: Advanced OOP and Design Patterns

require_once 'global_function.php';

$something = new Something();$something->doWork();

Page 75: Advanced OOP and Design Patterns

require_once 'mock_global_function.php';

$something = new Something();$something->doWork();

Page 76: Advanced OOP and Design Patterns

DependenciesDependencieson Static Callson Static Calls

Page 77: Advanced OOP and Design Patterns

class Something{ public function loadData() { $dsn = Configuration::getDsn();

… load data from database ... }}

Page 78: Advanced OOP and Design Patterns

class Something{ protected $configurationClass = 'Configuration';

public function setConfigurationClass($classname) { $this->configurationClass = $classname }

public function loadData() { $classname = $this->configurationClass; $db = $classname::getDsn();

… load data from database ... }}

Page 79: Advanced OOP and Design Patterns

??

Page 80: Advanced OOP and Design Patterns

class Something{ protected $configurationClass = 'Configuration';

public function setConfigurationClass($classname) { $this->configurationClass = $classname }

public function loadData() { $classname = $this->configurationClass; $db = $classname::getDsn();

… load data from database ... }}

Page 81: Advanced OOP and Design Patterns

Will $classnameWill $classnameactually be a class?actually be a class?

Page 82: Advanced OOP and Design Patterns

class Something{ protected $configurationClass = 'Configuration';

public function setConfigurationClass($classname) { $this->configurationClass = $classname }

public function loadData() { $classname = $this->configurationClass; $db = $classname::getDsn();

… load data from database ... }}

Page 83: Advanced OOP and Design Patterns

Will the class haveWill the class havea getDsn() method?a getDsn() method?

Page 84: Advanced OOP and Design Patterns

Better let PHP Better let PHP enforce this.enforce this.

Page 85: Advanced OOP and Design Patterns

DependenciesDependencieson Objectson Objects

Page 86: Advanced OOP and Design Patterns

class Something{ public function doWork() { ... $this->log('…'); ... }}

Page 87: Advanced OOP and Design Patterns

class Something{ protected function log($message) { file_put_contents(LOGFILE, $message, FILE_APPEND); }

public function doWork() { ... $this->log('…'); ... }}

Page 88: Advanced OOP and Design Patterns

class Logger{ public function log($message) { file_put_contents(LOGFILE, $message, FILE_APPEND); }}

Page 89: Advanced OOP and Design Patterns

class Something{ protected $logger;

public function __construct() { $this->logger = new Logger(); }

...}

Page 90: Advanced OOP and Design Patterns

class Something{ protected $logger;

public function __construct() { $this->logger = new Logger(); }

public function doWork() { … $this->logger->log(...); ... }}

Page 91: Advanced OOP and Design Patterns

class Something{ protected $logger;

public function __construct(Logger $logger) { $this->logger = $logger; }

public function doWork() { … $this->logger->log(...); ... }}

Page 92: Advanced OOP and Design Patterns

class Logger{ public function log($message) { file_put_contents(LOGFILE, $message, FILE_APPEND); }}

Page 93: Advanced OOP and Design Patterns

class Logger{ protected $file;

public function __construct($file) { $this->file = $file; }

public function log($message) { ... file_put_contents($this->file, $message, FILE_APPEND); ... }}

Page 94: Advanced OOP and Design Patterns

class DatabaseLogger extends Logger{ protected $dsn;

public function __construct($dsn) { $this->dsn = $dsn; }

public function log($message) { … log $message to database $dsn ... }}

Page 95: Advanced OOP and Design Patterns

class DbGateway{ protected $dsn;

public function __construct($dsn) { $this->dsn = $dsn; }

...}

Page 96: Advanced OOP and Design Patterns

class DbGateway{ protected $isConnected = false;

...

protected function connect() { … connect to $dsn ... }

public function query($query) { if (!$this->isConnected) { $this->connect(); }

… run $query ... }

...}

Page 97: Advanced OOP and Design Patterns

class DatabaseLogger extends Logger extends DbGateway{ ...}

Page 98: Advanced OOP and Design Patterns

Multiple Inheritance

Page 99: Advanced OOP and Design Patterns

??

Page 100: Advanced OOP and Design Patterns

class Something{ public function __construct(Logger $logger) { $this->logger = $logger; }

public function doWork() { ... $this->logger->log(...); ... }}

Page 101: Advanced OOP and Design Patterns

Do we really need to Do we really need to extend Logger?extend Logger?

Page 102: Advanced OOP and Design Patterns

class FileLogger{ protected $file;

public function __construct($file) { $this->file = $file; }

public function log($message) { ... file_put_contents($this->file, $message, FILE_APPEND); ... }}

Page 103: Advanced OOP and Design Patterns

class DatabaseLogger extends DbGateway{ public function log($message) { ... … write $message to database using $this->query() … ... }}

Page 104: Advanced OOP and Design Patterns

class Something{ public function __construct(Logger $logger) { $this->logger = $logger; }

public function doWork() { ... $this->logger->log(...); ... }}

Page 105: Advanced OOP and Design Patterns

How do we makeHow do we makethe type hint work?the type hint work?

Page 106: Advanced OOP and Design Patterns

InterfacesInterfaces

Page 107: Advanced OOP and Design Patterns

interface Loggable{ public function log($message);}

Page 108: Advanced OOP and Design Patterns

class FileLogger implements Loggable{ protected $file;

public function __construct($file) { $this->file = $file; }

public function log($message) { ... file_put_contents($this->file, $message, FILE_APPEND); ... }}

Page 109: Advanced OOP and Design Patterns

class DatabaseLogger extends DbGateway implements Loggable{ public function log($message) { ... … write $message to database using $this->query() … ... }}

Page 110: Advanced OOP and Design Patterns

class Something{ public function __construct(Loggable $logger) { $this->logger = $logger; }

protected function doWork() { ... $this->logger->log(...); ... }}

Page 111: Advanced OOP and Design Patterns

$logger = new FileLogger('/path/to/logfile');

$something = new Something($logger);$something->doWork();

Page 112: Advanced OOP and Design Patterns

$logger = new DatabaseLogger($dsn);

$something = new Something($logger);$something->doWork();

Page 113: Advanced OOP and Design Patterns

$logger = new DummyLogger();

$something = new Something($logger);$something->doWork();

Page 114: Advanced OOP and Design Patterns

class DummyLogger implements Loggable{ public function log($message) { }}

Page 115: Advanced OOP and Design Patterns

Interfaces makeInterfaces makegood type hints.good type hints.

Page 116: Advanced OOP and Design Patterns

Abstract Classes Abstract Classes and Methodsand Methods

Page 117: Advanced OOP and Design Patterns

class Something{ public function run() { // initialize …

// perform calculations …

// write log entry …

// sort output ... }}

Page 118: Advanced OOP and Design Patterns

class Something{ public function run() { $this->initialize(); $this->calculateStuff(); $this->doLogging(); $this->sortOutput(); }}

Page 119: Advanced OOP and Design Patterns

Template MethodTemplate Method

Page 120: Advanced OOP and Design Patterns

class Something{ abstract protected function initialize(); abstract protected function calculateStuff(); abstract protected function doLogging(); abstract protected function sortOutput();

public function run() { $this->initialize(); $this->calculateStuff(); $this->doLogging(); $this->sortOutput(); }}

Page 121: Advanced OOP and Design Patterns

abstract class Something{ abstract protected function initialize(); abstract protected function calculateStuff(); abstract protected function doLogging(); abstract protected function sortOutput();

public function run() { $this->initialize(); $this->calculateStuff(); $this->doLogging(); $this->sortOutput(); }}

Page 122: Advanced OOP and Design Patterns

abstract class Something{ abstract protected function initialize(); abstract protected function calculateStuff(); abstract protected function doLogging(); abstract protected function sortOutput();

final public function run() { $this->initialize(); $this->calculateStuff(); $this->doLogging(); $this->sortOutput(); }}

Page 123: Advanced OOP and Design Patterns

class ConcreteSomething extends Something{ protected function initialize() { }

protected function calculateStuff() { }

protected function doLogging() { }

protected function sortOutput() { }}

Page 124: Advanced OOP and Design Patterns

Abstract classes Abstract classes cannot be instantiated.cannot be instantiated.

Page 125: Advanced OOP and Design Patterns
Page 126: Advanced OOP and Design Patterns
Page 127: Advanced OOP and Design Patterns
Page 128: Advanced OOP and Design Patterns

„„Every pattern describes a problemEvery pattern describes a problemwhich occurs over and over again inwhich occurs over and over again in

our environment, and then describes our environment, and then describesthe core of the solution to that problem,the core of the solution to that problem,

in such a way that you can use thisin such a way that you can use thissolution a million times over, withoutsolution a million times over, withoutever doing it the same way twice.“ever doing it the same way twice.“

-- Christopher Alexander -- Christopher Alexander

Page 129: Advanced OOP and Design Patterns

A design patternA design patternis a general reusableis a general reusable

solution to a commonly solution to a commonly occurring problem.occurring problem.

Page 130: Advanced OOP and Design Patterns

A design pattern is not a A design pattern is not a finished design that can be finished design that can be

transformed directly into code.transformed directly into code.

Page 131: Advanced OOP and Design Patterns

ArchitecturalArchitecturalPatternsPatterns

DesignDesignPatternsPatterns

IdiomsIdioms

Page 132: Advanced OOP and Design Patterns

Problem: displayProblem: displaya progress bara progress bar

Page 133: Advanced OOP and Design Patterns

class Something{ protected function performCalculation() { ... foreach ($items as $item) { … process the item … print '.'; } ... }}

Page 134: Advanced OOP and Design Patterns

Subject/ObserverSubject/Observer

Page 135: Advanced OOP and Design Patterns

The subject maintains a list of The subject maintains a list of observers and notifies them on observers and notifies them on

status changes.status changes.

Page 136: Advanced OOP and Design Patterns

interface SplSubject{ public function attach(SplObserver $observer); public function detach(SplObserver $observer);

public function notify();}

Page 137: Advanced OOP and Design Patterns

interface SplObserver{ public function update(SplSubject $subject);}

Page 138: Advanced OOP and Design Patterns

class Subject implements SplSubject{ protected $observers;

public function __construct() { $this->observers = new SplObjectStorage(); }

...}

Page 139: Advanced OOP and Design Patterns

class Subject implements SplSubject{ …

public function attach(SplObserver $observer) { $observers->attach($observer); } public function detach(SplObserver $observer) { $observers->detach($observer); }

...}

Page 140: Advanced OOP and Design Patterns

class Subject implements SplSubject{ ...

public function notify() { foreach ($this->observers as $observer) { $observer->update($this); } }}

Page 141: Advanced OOP and Design Patterns

class Something extends Subject implements SplSubject{ public function doWork() { … foreach ($items as $item) { … $this->notify(); } ... }}

Page 142: Advanced OOP and Design Patterns

class ProgressBar implements SplObserver{ public function update(SplSubject $subject) { print '. '; }}

Page 143: Advanced OOP and Design Patterns

class Something extends Subject implements SplSubject{ public function doWork() { … foreach ($items as $item) { $this->currentItem = $item; … $this->notify(); } ... }

public function getCurrentItem() { return $this->currentItem() }}

Page 144: Advanced OOP and Design Patterns

class ProgressBar implements SplObserver{ public function update(SplSubject $subject) { $item = $subject->getCurrentItem(); … }}

Page 145: Advanced OOP and Design Patterns

class ProgressBar implements SplObserver{ public function update(SplSubject $subject) { $item = $subject->getCurrentItem();

if ($item->isDir()) { print '[' . $item->getPathname() . '] '; }

if ($item->isFile()) { print '.'; } }}

Page 146: Advanced OOP and Design Patterns

$progressBar = new ProgressBar();

$something = new Something();$something->attach($progressBar);

$something->doWork();

Page 147: Advanced OOP and Design Patterns

FactoryFactory

Page 148: Advanced OOP and Design Patterns

Defines an interface for creatingDefines an interface for creatinga family of objects. The concretea family of objects. The concrete

classes that are to be instantiated classes that are to be instantiated are not clearly defined.are not clearly defined.

Page 149: Advanced OOP and Design Patterns

Creates objects for you.Creates objects for you.

Page 150: Advanced OOP and Design Patterns

abstract class Plane{ static public function getInstance($type) { return new $type; }}

Page 151: Advanced OOP and Design Patterns

class Boeing extends Plane{}

class Airbus extends Plane{}

class Boeing777 extends Boeing{}

class AirbusA340 extends Airbus{}

Page 152: Advanced OOP and Design Patterns

$a = Plane::getInstance('Boeing777');

$b = Plane::getInstance('AirbusA340');

Page 153: Advanced OOP and Design Patterns

abstract class Plane{ static public function getInstance($type) { switch ($type) { case 'Boeing777': return new Boeing777(); … default:

throw new RuntimeException('...'); } }}

Page 154: Advanced OOP and Design Patterns

abstract class Plane{ static public function getInstance($type) { if (!in_array($type, array('Boeing777', 'AirbusA340', …))) { throw new RuntimeException('...'); }

return new $type; }}

Page 155: Advanced OOP and Design Patterns

abstract class Plane{ static public function getInstance($type) { if (!class_exists($type)) { throw new RuntimeException('...'); }

return new $type; }}

Page 156: Advanced OOP and Design Patterns

abstract class Plane{ protected $classMap = array( '777' => 'Boeing777', ... );

static public function getInstance($type) { if (!isset($this->classMap[$type])) { throw new RuntimeException('...'); }

$classname = $this->classMap[$type]; return new $classname; }}

Page 157: Advanced OOP and Design Patterns

SingletonSingleton

Page 158: Advanced OOP and Design Patterns

Limits number of instancesLimits number of instancesof a class to one object.of a class to one object.

Page 159: Advanced OOP and Design Patterns

Limits number of instancesLimits number of instancesof a class to one object.of a class to one object.

Page 160: Advanced OOP and Design Patterns

class Singleton{ static protected $instance;

static public function getInstance() { if (is_null(self::$instance)) { self::$instance = new Singleton(); }

return self::$instance; }}

Page 161: Advanced OOP and Design Patterns

class Singleton{ static protected $instance;

private function __construct() {} private function __clone() {}

static public function getInstance() { if (is_null(self::$instance)) { self::$instance = new Singleton(); }

return self::$instance; }}

Page 162: Advanced OOP and Design Patterns

class Something{ public function doWork() { $singleton = Singleton::getInstance(); $singleton->... ... }}

Page 163: Advanced OOP and Design Patterns

class Something{ public function doWork($reference) { $reference->... ... }}

Page 164: Advanced OOP and Design Patterns
Page 165: Advanced OOP and Design Patterns

RegistryRegistry

Page 166: Advanced OOP and Design Patterns

A well-known object usedA well-known object usedby others to find sharedby others to find shared

objects and services.objects and services.

Page 167: Advanced OOP and Design Patterns

…$db = StaticRegistry::getDbAdapter();...

Page 168: Advanced OOP and Design Patterns

class StaticRegistry{ static protected $dbAdapter;

static public function getDbAdapter() { if (is_null(self::$dbAdapter)) { self::$dbAdapter = new DbAdapter(); }

return self::$dbAdapter; }}

Page 169: Advanced OOP and Design Patterns

…$db = Registry::getInstance()->getDbAdapter();...

Page 170: Advanced OOP and Design Patterns

class SingletonRegistry{ static protected $instance;

protected $dbAdapter;

static public function getInstance() { … }

public function getDbAdapter() { if (is_null($this->dbAdapter)) { $this->dbAdapter = new DbAdapter(); }

return $this->dbAdapter; }}

Page 171: Advanced OOP and Design Patterns

class Registry{ …

protected $dbAdapterClass = 'DbAdapter'; protected $dbAdapter;

public function setDbAdapterClass($class) { $this->dbAdapterClass = $class; }

public function getDbAdapter() { if (is_null($this->dbAdapter)) { $classname = $this->dbAdapterClass; $this->dbAdapter = new $classname; }

return $this->dbAdapter; }}

Page 172: Advanced OOP and Design Patterns

MVCMVC

Page 173: Advanced OOP and Design Patterns

ClassicalClassical

MVCMVC

Page 174: Advanced OOP and Design Patterns

ModelModel

Page 175: Advanced OOP and Design Patterns

RepresentsRepresentsdomain-specific datadomain-specific data

Page 176: Advanced OOP and Design Patterns

View View

Page 177: Advanced OOP and Design Patterns

RendersRendersmodel datamodel data

Page 178: Advanced OOP and Design Patterns

ControllerController

Page 179: Advanced OOP and Design Patterns

Handles eventsHandles eventsand modifies modeland modifies model

Page 180: Advanced OOP and Design Patterns

PresentationPresentation

LogicLogic

Data AccessData Access MM

VV

CC

Page 181: Advanced OOP and Design Patterns

Model != Data AccessModel != Data Access

Page 182: Advanced OOP and Design Patterns

Model != Data AccessModel != Data Access

Page 183: Advanced OOP and Design Patterns
Page 184: Advanced OOP and Design Patterns

ControllerController

ModelModelViewView

Page 185: Advanced OOP and Design Patterns

ControllerController

ModelModelViewView

Controller observes ViewController observes View

Page 186: Advanced OOP and Design Patterns

ControllerController

ModelModelViewView

Controller fetches data from ViewController fetches data from View

Page 187: Advanced OOP and Design Patterns

ControllerController

ModelModelViewView

Controller modifies ModelController modifies Model

Page 188: Advanced OOP and Design Patterns

ControllerController

ModelModelViewView

View observes ModelView observes Model

Page 189: Advanced OOP and Design Patterns

ControllerController

ModelModelViewView

View fetches data from ModelView fetches data from Model

Page 190: Advanced OOP and Design Patterns

MVCMVCon the Webon the Web

Page 191: Advanced OOP and Design Patterns

ServerServer

ClientClient

HTTP RequestHTTP Request HTTP ResponseHTTP Response

VV

CC MM

Page 192: Advanced OOP and Design Patterns

View is View is remoteremote

Page 193: Advanced OOP and Design Patterns

ControllerController

ModelModelViewView

Page 194: Advanced OOP and Design Patterns

ControllerController

ModelModelViewView

Controller can't observe ViewController can't observe View

Page 195: Advanced OOP and Design Patterns

ControllerController

ModelModelViewView

View can't observe ModelView can't observe Model

Page 196: Advanced OOP and Design Patterns

ControllerController

ModelModelViewView

FrontFrontControllerController

View doesn't talk to ControllerView doesn't talk to Controller

Page 197: Advanced OOP and Design Patterns

ControllerController

ModelModelViewView

FrontFrontControllerController

HTTPHTTPRequestRequest

Page 198: Advanced OOP and Design Patterns

ControllerController

ModelModelViewView

FrontFrontControllerController

HTTPHTTPRequestRequest

execute()execute()

Page 199: Advanced OOP and Design Patterns

ControllerController

ModelModelViewView

FrontFrontControllerController

HTTPHTTPRequestRequest

execute()execute()

getData()getData()

Page 200: Advanced OOP and Design Patterns

ControllerController

ModelModelViewView

FrontFrontControllerController

HTTPHTTPRequestRequest

execute()execute()

getData()getData()

setData()

setData()

Page 201: Advanced OOP and Design Patterns

ControllerControllerselects Viewselects View

Page 202: Advanced OOP and Design Patterns

View generatesView generatesfull HTML pagefull HTML page

Page 203: Advanced OOP and Design Patterns

Workflows by Workflows by Controller chainingController chaining

Page 204: Advanced OOP and Design Patterns

Lean Controller, Lean Controller, Fat ModelFat Model

Page 205: Advanced OOP and Design Patterns
Page 206: Advanced OOP and Design Patterns

No data accessNo data accessin Controller or Modelin Controller or Model

Page 207: Advanced OOP and Design Patterns

No presentationNo presentationin Controller or Modelin Controller or Model

Page 208: Advanced OOP and Design Patterns

Separation ofSeparation ofConcernsConcerns

Page 209: Advanced OOP and Design Patterns

Golden Golden RulesRules

Page 210: Advanced OOP and Design Patterns

„„Hang the rules. Hang the rules. They're more like They're more like guidelines anyway.“guidelines anyway.“

--Elizabeth Swann,--Elizabeth Swann,Pirates of the CaribbeanPirates of the Caribbean

Page 211: Advanced OOP and Design Patterns

Make Make dependencies dependencies

explicit.explicit.

Page 212: Advanced OOP and Design Patterns

„„Life can only beLife can only beunderstoodunderstood backwardsbackwards,,but it must be but it must be livedlivedforwardsforwards.“.“

-- Soren Kierkegaard-- Soren Kierkegaard

Page 213: Advanced OOP and Design Patterns

Solve your Solve your problem.problem.

Page 214: Advanced OOP and Design Patterns

Do one thingDo one thingat a time.at a time.

Page 215: Advanced OOP and Design Patterns

Let othersLet othersdo the work.do the work.

Page 216: Advanced OOP and Design Patterns

Do not care Do not care about others.about others.

Page 217: Advanced OOP and Design Patterns

Keep itKeep itsimple.simple.

Page 218: Advanced OOP and Design Patterns

„„Debugging is twice as hardDebugging is twice as hardas writing the code in theas writing the code in thefirst place. Therefore, if youfirst place. Therefore, if youwrite the code as cleverly as write the code as cleverly as possible, you are, by definition, possible, you are, by definition, not smart enoughnot smart enoughto debug it.“to debug it.“

-- Brian W. Kernighan-- Brian W. Kernighan

Page 219: Advanced OOP and Design Patterns

Do notDo notcomment.comment.

Page 220: Advanced OOP and Design Patterns

Do notDo notcomment.comment.**

** Some restrictions apply. Some restrictions apply.

Page 221: Advanced OOP and Design Patterns

””The most important The most important single aspect of software single aspect of software development ...development ...

… is to be … is to be clearclear about about what you are trying to what you are trying to build.”build.”

-- Bjarne Stroustrup-- Bjarne Stroustrup

Page 222: Advanced OOP and Design Patterns

Name the thing.Name the thing.

Page 223: Advanced OOP and Design Patterns

„„There's no sense beingThere's no sense beingexact about somethingexact about somethingif you don't even knowif you don't even know

what you're talking about.“what you're talking about.“-- John von Neumann-- John von Neumann

Page 224: Advanced OOP and Design Patterns

It has to fitIt has to fiton one page.on one page.

Page 225: Advanced OOP and Design Patterns

””Measuring programming Measuring programming progress by lines of codeprogress by lines of codeis like measuring aircraft is like measuring aircraft building progress by building progress by weightweight.”.”

-- Bill Gates-- Bill Gates

Page 226: Advanced OOP and Design Patterns

Accept Change.Accept Change.

Page 227: Advanced OOP and Design Patterns

””I may not have gone I may not have gone where I intended to go, where I intended to go, but I think I have ended but I think I have ended up where I needed to be.“up where I needed to be.“

-- Douglas Adams-- Douglas Adams

Page 228: Advanced OOP and Design Patterns

Thank you.Thank you.

Please rate me:Please rate me:http://joind.inhttp://joind.in

Page 229: Advanced OOP and Design Patterns

Copyright © 2009 thePHP.cc, Germany

Contact■ http://thePHP.cc■ http://www.priebsch.de■ http://www.slideshare.net/spriebsch■ http://twitter.com/spriebsch■ [email protected], IRC: spriebsch