decoupling objects with standard interfaces

53
IPC Spring 2013 IPC Spring 2013 Decoupling Objects With Standard Interfaces

Upload: thomas-weinert

Post on 25-May-2015

308 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: Decoupling Objects With Standard Interfaces

IPC Spring 2013IPC Spring 2013

Decoupling Objects WithStandard Interfaces

Page 2: Decoupling Objects With Standard Interfaces

About MeAbout Me● Thomas Weinert

● papaya Software GmbH● papaya CMS

● Twitter: @ThomasWeinert● Web: http://www.a-basketful-of-papayas.net

Page 3: Decoupling Objects With Standard Interfaces

InterfacesInterfaces● By Declaration● By Convention

● Magic Methods

Page 4: Decoupling Objects With Standard Interfaces

ReasonsReasons● Encapsulation● Reuse● S.O.L.I.D.

Page 5: Decoupling Objects With Standard Interfaces

ImplementImplement

class Foo implements Countable, IteratorAggregate { }

Page 6: Decoupling Objects With Standard Interfaces

ExtendExtend

interface Foo extends IteratorAggregate { }

Page 7: Decoupling Objects With Standard Interfaces

ValidateValidate

if ($foo instanceOf Traversable) { }

Page 8: Decoupling Objects With Standard Interfaces

Type HintsType Hints

function bar(Traversable $foo) { }

Page 9: Decoupling Objects With Standard Interfaces

InterfacesInterfaces

By Convention

Page 10: Decoupling Objects With Standard Interfaces

Object InitializationObject Initialization● Magic Methods

● __construct()● __destruct()● __clone()● __sleep()/__wakeup() → Serializeable● __set_state()

Page 11: Decoupling Objects With Standard Interfaces

__toString__toString● Cast an object to string

/** * Casting the object to string will *return the last value * @return string */public function __toString() { return (string)end($this->_values);}

Page 12: Decoupling Objects With Standard Interfaces

Dynamic PropertiesDynamic Properties● $object->value = 123● $value = $object->value;● $object->setValue(123);● $value = $object->getValue();

Page 13: Decoupling Objects With Standard Interfaces

Dynamic PropertiesDynamic Properties● __isset()● __get()● __set()● __unset()

Page 14: Decoupling Objects With Standard Interfaces

__isset()__isset() /** * @param string $name * @return boolean */ public function __isset($name) { switch ($name) { case 'name' : case 'value' : case 'values' : return TRUE; } return FALSE; }

Page 15: Decoupling Objects With Standard Interfaces

__get()__get()/** * @param string $name * @throws InvalidArgumentException * @return mixed */public function __get($name) { switch ($name) { case 'name' : return $this->_name; case 'value' : return end($this->_values); case 'values' : return $this->_values; } throw new \LogicException( sprintf( 'Can not read non existing property: %s::$%s', __CLASS__, $name ) );}

Page 16: Decoupling Objects With Standard Interfaces

__set()__set()/** * @param string $name * @param string|array|Traversable $value * @throws \LogicException */public function __set($name, $value) { switch ($name) { case 'name' : $this->setName($value); return; case 'value' : $this->setData((string)$value); return; case 'values' : $this->setData($value); return; } throw new \LogicException( sprintf('Can not write non existing property: %s::$%s', __CLASS__, $name ...

Page 17: Decoupling Objects With Standard Interfaces

__call/__callStatic__call/__callStatic

Dynamic Methods/Functions

Page 18: Decoupling Objects With Standard Interfaces

Generic CallbacksGeneric Callbacksclass MyEvents extends Events {

public function __construct() { parent::__construct(['example' => 21]); }}

$my = new MyEvents();echo $my->onExample(), "\n"; //21

$my->onExample = function () { return 42;};echo $my->onExample(), "\n"; //42

$my->onExample = 23;echo $my->onExample(), "\n"; //23

Page 19: Decoupling Objects With Standard Interfaces

PHP DocumentorPHP Documentor/* * … * * @property Callable $onExample * @method mixed onExample() */class MyEvents extends Events {

public function __construct() { parent::__construct(['example' => 21]); }}

Page 20: Decoupling Objects With Standard Interfaces

CallableCallable● 'function'● array($object, 'method')● function() {}● class {}

Page 21: Decoupling Objects With Standard Interfaces

__invoke__invoke● Functors

● Callable

Page 22: Decoupling Objects With Standard Interfaces

Callback ListsCallback Lists...$queries = Io\Deferred::When( $mysqlOne("SELECT 'Query 1', SLEEP(5)") ->done( function($result) use ($time) { var_dump(iterator_to_array($result)); var_dump(microtime(TRUE) - $time); } ), $mysqlTwo("SELECT 'Query 2', SLEEP(1)") ->done( function($result) use ($time) { var_dump(iterator_to_array($result)); var_dump(microtime(TRUE) - $time); } ));

Page 23: Decoupling Objects With Standard Interfaces

Functor ExampleFunctor Example

class DatabaseResultDebugger {

private $_startTime = 0;

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

public function __invoke($result) { var_dump(iterator_to_array($result)); var_dump(microtime(TRUE) - $this->_startTime); }}

Page 24: Decoupling Objects With Standard Interfaces

Callback HandlersCallback Handlers$queries = Io\Deferred::When( $mysqlOne("SELECT 'Query 1', SLEEP(5)") ->done( new DatabaseResultDebugger($time) ), $mysqlTwo("SELECT 'Query 2', SLEEP(1)") ->done( new DatabaseResultDebugger($time) ));

Page 25: Decoupling Objects With Standard Interfaces

More Callback HandlersMore Callback Handlers$queries = Io\Deferred::When( $mysqlOne("SELECT 'Query 1', SLEEP(5)") ->done( new ConcreteDatabaseResultHandler() ) ->done( new DatabaseResultDebugger($time) ), $mysqlTwo("SELECT 'Query 2', SLEEP(1)") ->done( new DatabaseResultDebugger($time) ));

Page 26: Decoupling Objects With Standard Interfaces

Predeclared Interfaces

Page 27: Decoupling Objects With Standard Interfaces

SerializeableSerializeable● Usage

● serialize($object)● unserialize($string);

● Methods● $object->serialize()● $object->unserialize($string);

Page 28: Decoupling Objects With Standard Interfaces

JsonSerializableJsonSerializable● Usage

● json_encode()

● Method● $object->jsonSerialize()

Page 29: Decoupling Objects With Standard Interfaces

ArrayAccessArrayAccess● [] -Syntax● Validation● Conversion● Lazy Initialization

Page 30: Decoupling Objects With Standard Interfaces

ArrayAccess MethodsArrayAccess Methods● offsetExists()● offsetGet()● offsetSet()● offsetUnset()

Page 31: Decoupling Objects With Standard Interfaces

OffsetExists()OffsetExists()

/** * @param integer $offset * @return boolean */ public function offsetExists($offset) { return array_key_exists($offset, $this->_values); }

Page 32: Decoupling Objects With Standard Interfaces

OffsetGet()OffsetGet()

/** * @param integer $offset */ public function offsetGet($offset) { return $this->_values[$offset]; }

Page 33: Decoupling Objects With Standard Interfaces

OffsetSet()OffsetSet()

/** * @param integer $offset * @param string $value */ public function offsetSet($offset, $value) { if (NULL === $offset) { $this->_values[] = $value; } else { $this->_values[$offset] = $value; } }

Page 34: Decoupling Objects With Standard Interfaces

OffsetUnset()OffsetUnset()

/** * @param integer $offset */ public function offsetUnset($offset) { unset($this->_values[$offset]); }

Page 35: Decoupling Objects With Standard Interfaces

Array DereferencingArray Dereferencing

echo $object->foo()[0];

Page 36: Decoupling Objects With Standard Interfaces

CountableCountable● count($foo)

class DatabaseResult implements Countable { ... public function count() { return $this->_count; } ...}

Page 37: Decoupling Objects With Standard Interfaces

TraversableTraversable● foreach● Iterator● IteratorAggregate

Page 38: Decoupling Objects With Standard Interfaces

Iterator InterfacesIterator Interfaces

Traversable

Iterator

OuterIterator

IteratorAggregate

RecursiveIteratorSeekableIterator

SPL

Page 39: Decoupling Objects With Standard Interfaces

Iterator functionsIterator functions● foreach() ● iterator_to_array()● iterator_count()● iterator_apply()

Page 40: Decoupling Objects With Standard Interfaces

IteratorIterator● rewind()● next()● valid()● current()● key()

Page 41: Decoupling Objects With Standard Interfaces

IteratorAggregateIteratorAggregate● getIterator()

class Foo implements IteratorAggregate { private $_items = array(); public function __construct(array $items) { $this->_items = $items; } public function getIterator() { return new ArrayIterator($this->_items); }}

Page 42: Decoupling Objects With Standard Interfaces

Predefined IteratorsPredefined Iterators● ArrayIterator● EmptyIterator● RegexIterator● …

Page 43: Decoupling Objects With Standard Interfaces

Nest IteratorsNest Iterators● IteratorIterator

● AppendIterator● CallbackFilterIterator● ...

Page 44: Decoupling Objects With Standard Interfaces

RecursiveIteratorRecursiveIterator● List with Children

$items = [ 1 => '1', 2 => '1.1', 3 => '2'];

$structure = [ 0 => [1, 3], 1 => [2]];

Page 45: Decoupling Objects With Standard Interfaces

Inherit from IteratorIteratorInherit from IteratorIteratorclass Bar extends IteratorIterator implements RecursiveIterator {

private $_items = []; private $_structure = [];

public function __construct($items, $structure, $parent = 0) { $siblings = []; if (!empty($structure[$parent])) { foreach ($structure[$parent] as $id) { if (isset($items[$id])) { $siblings[$id] = $items[$id]; } } } parent::__construct(new ArrayIterator($siblings)); $this->_items = $items; $this->_structure = $structure; }...

Page 46: Decoupling Objects With Standard Interfaces

hasChildren()hasChildren()

public function hasChildren() { return $this->valid() && isset($this->_structure[$this->key()]); }

Page 47: Decoupling Objects With Standard Interfaces

getChildren()getChildren()

public function getChildren() { if ($this->hasChildren()) { return new $this( $this->_items, $this->_structure, $this->key() ); } else { return new $this([], []); } }

Page 48: Decoupling Objects With Standard Interfaces

RecursiveIteratorIteratorRecursiveIteratorIterator● Iterator for RecursiveIterator$iterator = new RecursiveIteratorIterator( new Bar($items, $structure), RecursiveIteratorIterator::SELF_FIRST);

foreach ($iterator as $element) { echo str_repeat('*', $iterator->getDepth() + 1); echo $element; echo "\n";}

Page 49: Decoupling Objects With Standard Interfaces

ResultResult* 1

** 1.1

* 2

● No recursive function call● Works with Traversable/ArrayAccess● Allows for Lazy Initalization

Page 50: Decoupling Objects With Standard Interfaces

ObserverObserver

Subject

Observer 2 Observer 2Observer 2

Page 51: Decoupling Objects With Standard Interfaces

ObserverObserver

CMS Page published

Log Action Announce ToWebservice

Invalidate Cache

Page 52: Decoupling Objects With Standard Interfaces

ObserverObserver● SplObserver

● update()

● SplSubject● attach()● detach()● notify()

Page 53: Decoupling Objects With Standard Interfaces

Thank YouThank You

● Twitter: @ThomasWeinert

● https://joind.in/8807