Upgrade to Pro — share decks privately, control downloads, hide ads and more …

IPC 2013: Decoupling Objects With Standard Interfaces

IPC 2013: Decoupling Objects With Standard Interfaces

3f2fb8bbcd44609346e1cc0c06d0a39b?s=128

Thomas Weinert

October 30, 2013
Tweet

More Decks by Thomas Weinert

Other Decks in Programming

Transcript

  1. IPC 2013 IPC 2013 Decoupling Objects With Standard Interfaces

  2. About Me About Me • Thomas Weinert • @ThomasWeinert •

    dimensional GmbH • papaya CMS • PHP, Javascript, XSLT • XML Fanatic (JSON is BAD)
  3. Interfaces Interfaces • By Declaration • By Convention • Magic

    Methods
  4. Reasons Reasons • Encapsulation • Reuse • S.O.L.I.D.

  5. Implement Implement class Foo implements Countable, IteratorAggregate { }

  6. Extend Extend interface Foo extends IteratorAggregate { }

  7. Extend Extend interface Foo extends IteratorAggregate, ArrayAccess { }

  8. Validate Validate if ($foo instanceOf Traversable) { }

  9. Type Hints Type Hints function bar(Traversable $foo) { }

  10. Interfaces Interfaces By Convention

  11. Object Initialization Object Initialization • Magic Methods • __construct() •

    __destruct() • __clone() • __sleep()/__wakeup() → Serializeable • __set_state()
  12. __toString __toString /** * Casting the object to string will

    * return the last value * @return string */ public function __toString() { return (string)end($this->_values); }
  13. Dynamic Properties Dynamic Properties $object->value = 123 $value = $object->value;

    $object->setValue(123); $value = $object->getValue();
  14. Dynamic Properties Dynamic Properties • __isset() • __get() • __set()

    • __unset()
  15. __isset() __isset() /** * @param string $name * @return boolean

    */ public function __isset($name) { switch ($name) { case name : case value : case values : return TRUE; } return FALSE; }
  16. __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 ) ); }
  17. __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 ...
  18. __call/__callStatic __call/__callStatic • Dynamic Methods/Functions

  19. Generic Callbacks Generic Callbacks class 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
  20. PHP Documentor PHP Documentor /** * … * @property Callable

    $onExample * @method mixed onExample() */ class MyEvents extends Events { public function __construct() { parent::__construct(['example' => 21]); } }
  21. Callable Callable • function • array($object, method) • function() {}

    • class { public function __invoke() {} }
  22. Callback Lists Callback 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); } ) );
  23. Functor Example Functor 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 ); } }
  24. Callback Handlers Callback 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) ) );
  25. More Callback Handlers More 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) ) );
  26. Predeclared Interfaces Predeclared Interfaces • Serializeable • Usage • serialize($object)

    • unserialize($string); • Methods • $object->serialize() • $object->unserialize($string);
  27. JsonSerializable JsonSerializable • Usage • json_encode() • Method • $object->jsonSerialize()

  28. ArrayAccess ArrayAccess • [] -Syntax • Validation • Conversion •

    Lazy Initialization
  29. ArrayAccess Methods ArrayAccess Methods • offsetExists() • offsetGet() • offsetSet()

    • offsetUnset()
  30. OffsetExists() OffsetExists() /** * @param integer $offset * @return boolean

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

    offsetGet($offset) { return $this->_values[$offset]; }
  32. OffsetSet() OffsetSet() /** * @param integer $offset * @param string

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

    offsetUnset($offset) { unset($this->_values[$offset]); }
  34. Array Dereferencing Array Dereferencing echo $object->foo()[0];

  35. Countable Countable • Usage • count($foo) • Method • count()

  36. Countable Example Countable Example class DatabaseResult implements Countable { ...

    public function count() { return $this->_count; } ... }
  37. Traversable Traversable • Usage • foreach($traversable as $key=>$value) • Implementations

    • Iterator • IteratorAggregate
  38. Iterator Interfaces Iterator Interfaces Traversable IteratorAggregate Iterator SeekableIterator RecursiveIterator OuterIterator

    SPL
  39. Iterator functions - Usage Iterator functions - Usage • foreach()

    • iterator_to_array() • iterator_count() • iterator_apply()
  40. Iterator Implementation Iterator Implementation • rewind() • next() • valid()

    • current() • key()
  41. IteratorAggregate IteratorAggregate • getIterator() class MyDatabaseResult implements IteratorAggregate { private

    $_items = array(); public function getIterator() { return new ArrayIterator( $this->_items ); } }
  42. Predefined Iterators Predefined Iterators • ArrayIterator • EmptyIterator • RegexIterator

    • …
  43. Nest Iterators Nest Iterators • IteratorIterator • AppendIterator • CallbackFilterIterator

    • ...
  44. RecursiveIterator RecursiveIterator • List with Children $items = [ 1

    => '1', 2 => '1.1', 3 => '2' ]; $structure = [ 0 => [1, 3], 1 => [2] ];
  45. Inherit from IteratorIterator Inherit from IteratorIterator class Bar extends IteratorIterator

    implements RecursiveIterator { private $_items = []; private $_structure = []; public function __construct( $items, $structure, $parent = 0 ) { → next slide } …
  46. Inherit from IteratorIterator Inherit from IteratorIterator … $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; …
  47. hasChildren() hasChildren() public function hasChildren() { return $this->valid() && isset(

    $this->_structure[$this->key()] ); }
  48. getChildren() getChildren() public function getChildren() { if ($this->hasChildren()) { return

    new $this( $this->_items, $this->_structure, $this->key() ); } else { return new $this([], []); } }
  49. RecursiveIteratorIterator RecursiveIteratorIterator • 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"; }
  50. Result Result * 1 ** 1.1 * 2 • No

    recursive function call • Works with Traversable/ArrayAccess • Allows for Lazy Initalization
  51. Thank You Thank You • Questions? • Twitter: @ThomasWeinert •

    Blog: http://a-basketful-of-papayas.net