Cool Objects Sleep on the Couch

Loading...

Flash Player 9 (or above) is needed to view presentations.
We have detected that you do not have it on your computer. To install it, go here.

1 comments

Comments 1 - 1 of 1 previous next Post a comment

Post a comment
Embed Video
Edit your comment Cancel

12 Favorites, 1 Group & 1 Event

Cool Objects Sleep on the Couch - Presentation Transcript

  1. Cool Objects Sleep on the Couch Sebastian Bergmann May 27th 2009
  2. Who I Am  Sebastian Bergmann  Involved in the PHP project since 2000  Creator of PHPUnit  Co-Founder and Principal Consultant with thePHP.cc
  3. How can we map data between objects and a database?
  4. Data Mapping The Problem class User { protected $name; protected $address; } class Address { protected $city; protected $zip; protected $state; protected $country; }
  5. Data Mapping The Problem Relational databases only store scalar values (organized in tuples and relations)  Objects are not scalar values  Object graph has to be broken down into single objects, then into scalar values
  6. Data Mapping The Problem class User { Table: users protected $name; +------+---------+ protected $address; | name | address | } +------+---------+ class Address { Table: addresses protected $city; +------+-----+-------+---------+ protected $zip; | city | zip | state | country | protected $state; +------+-----+-------+---------+ protected $country; }
  7. Data Mapping The Problem class User { Table: users protected $name; +------+-----+ protected $addresses = array(); | name | ??? | } +------+-----+ class Address { Table: addresses protected $city; +------+-----+-------+---------+ protected $zip; | city | zip | state | country | protected $state; +------+-----+-------+---------+ protected $country; }
  8. Data Mapping Hand-Coded SQL in the Domain Class class User { protected $name; public function __construct($name) { $this->setName($name); } public function setName($name) { $this->name = $name; if (/* new user */) { DB::getInstance()->query('INSERT INTO users …'); } else { DB::getInstance()->query('UPDATE users SET …'); } } }
  9. Data Mapping Hand-Coded SQL in the Domain Class Domain logic and persistence layer are tangled  No locality of change  No separation of concerns  Domain logic cannot be used – tested, for instance – without the persistence layer
  10. Essential Data Mapping Patterns  Active Record  Object-Relational Mapping (ORM)  Unit of Work  Identity Map  Lazy Load
  11. Data Source Architectural Patterns Active Record An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data. This slide contains material by Martin Fowler
  12. Data Source Architectural Patterns Active Record Active Record may be used to implement an Object-Relational Mapper (ORM), but it should never be used as one. This slide contains material by Kore Nordmann
  13. Object-Relational Mapping (ORM) Programming technique for converting data between incompatible type systems in relational databases and object- oriented programming languages [that] creates a ”virtual object database”. This slide contains material from Wikipedia
  14. Object-Relational Behavioral Patterns Unit of Work Maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems. This slide contains material by Martin Fowler
  15. Object-Relational Behavioral Patterns Identity Map Ensures that each object gets loaded only once by keeping every loaded object in a map. Looks up objects using the map when referring to them. This slide contains material by Martin Fowler
  16. Object-Relational Behavioral Patterns Lazy Load An object that does not contain all of the data you need but knows how to get it. This slide contains material by Martin Fowler
  17. ORM Solutions for PHP  Doctrine  Propel
  18. ORM Solutions for PHP Propel <database name=\"example\" defaultIdMethod=\"native\"> <table name=\"user\"> <column name=\"id\" type=\"integer\" required=\"true\" primaryKey=\"true\" autoIncrement=\"true\"/> <column name=\"name\" type=\"varchar\" size=\"255\" required=\"true\" /> <column name=\"address\" type=\"integer\" required=\"true\"/> <foreign-key foreignTable=\"address\"> <reference local=\"address\" foreign=\"id\"/> </foreign-key> </table> <table name=\"address\"> <column name=\"id\" type=\"integer\" required=\"true\" primaryKey=\"true\" autoIncrement=\"true\"/> <column name=\"city\" type=\"varchar\" size=\"128\" required=\"true\"/> <column name=\"zip\" type=\"varchar\" size=\"128\" required=\"true\"/> <column name=\"state\" type=\"varchar\" size=\"128\" required=\"true\"/> <column name=\"country\" type=\"varchar\" size=\"128\" required=\"true\"/> </table> </database>
  19. ORM Solutions for PHP Propel sb@thinkpad example % propel-gen . . . . sb@thinkpad example % tree build build |-- classes | `-- example | |-- Address.php | |-- AddressPeer.php | |-- User.php | |-- UserPeer.php | |-- map | | |-- AddressMapBuilder.php | | `-- UserMapBuilder.php | `-- om | |-- BaseAddress.php | |-- BaseAddressPeer.php | |-- BaseUser.php | `-- BaseUserPeer.php |-- conf | |-- example-classmap.php | `-- example-conf.php `-- sql |-- schema.sql `-- sqldb.map 6 directories, 14 files
  20. ORM Solutions for PHP Propel sb@thinkpad example % propel-gen . . . . sb@thinkpad example % phploc build phploc 1.1.0 by Sebastian Bergmann. Directories: 3 Files: 12 Lines of Code (LOC): 3469 Executable Lines of Code (ELOC): 1279 Comment Lines of Code (CLOC): 1743 Non-Comment Lines of Code (NCLOC): 1726 Interfaces: 0 Classes: 10 Non-Static Methods: 69 Static Methods: 54 Functions: 0
  21. Object-Relational Mapping (ORM) The Vietnam of Computer Science Law of Diminishing Returns Early successes yield a commitment to use ORM in places where success becomes more elusive, and over time, isn't a success at all due to the overhead of time and energy required to support it through all possible use-cases. This slide contains material from Ted Neward
  22. Redefining ORM  Not Object-Relational Mapping  Instead: Object-Repository Mapping  Map POPO*s to a schema-free database using the Object_Freezer library * Plain Old PHP Object
  23. Object_Freezer Library that provides the low-level functionality required to  store (\"freeze\") PHP objects to and  retrieve (\"thaw\") PHP objects from an object repository
  24. Object_Freezer Freezing an object class SomeClass { private $foo = 'bar'; } require_once 'Object/Freezer.php'; $freezer = new Object_Freezer; $frozenObject = $freezer->freeze(new SomeClass);
  25. Object_Freezer A frozen object array( 'root' => '087998e3-5305-4837-bd50-79564e720777', 'objects' => array( '087998e3-5305-4837-bd50-79564e720777' => array( 'className' => 'SomeClass', 'isDirty' => TRUE, 'state' => array( 'foo' => 'bar', '__php_object_freezer_hash' => 'a8e3be85ce27a1e44ec5bb83407b53f25bbf9a95', ) ) ) )
  26. Object_Freezer Thawing a frozen object $object = $freezer->thaw( array( 'root' => '087998e3-5305-4837-bd50-79564e720777', 'objects' => array( '087998e3-5305-4837-bd50-79564e720777' => array( 'className' => 'SomeClass', 'isDirty' => TRUE, 'state' => array( 'foo' => 'bar', '__php_object_freezer_hash' => 'a8e3be85ce27a1e44ec5bb83407b53f25bbf9a95', ) ) ) ) );
  27. Object_Freezer: Internals Reading non-public object state $reflector = new ReflectionObject($object); $state = array(); foreach ($reflector->getProperties() as $attribute) { $attribute->setAccessible(TRUE); $state[$attribute->getName()] = $attribute->getValue($object); }
  28. Object_Freezer: Internals Reading non-public object state $reflector = new ReflectionObject($object); $state = array(); foreach ($reflector->getProperties() as $attribute) { $attribute->setAccessible(TRUE); $state[$attribute->getName()] = $attribute->getValue($object); } New in PHP 5.3
  29. Object_Freezer: Internals Creating an object without invoking a constructor $object = unserialize( sprintf( 'O:%d:\"%s\":0:{}', strlen($className), $className ) ); Caveat If the class declares a __wakeup() method, it will be invoked.
  30. Object_Freezer: Internals Setting non-public object state $object = unserialize( sprintf( 'O:%d:\"%s\":0:{}', strlen($className), $className ) ); $reflector = new ReflectionObject($object); foreach ($state as $name => $value) { $attribute = $reflector->getProperty($name); $attribute->setAccessible(TRUE); $attribute->setValue($object, $value); }
  31. Object_Freezer_Storage  Abstract base class for object storage implementations  Unit of Work  Identity Map  Lazy Load  Available implementations  Apache CouchDB
  32. Apache CouchDB  Distributed  Fault-Tolerant  Schema-Free  Document-Oriented  RESTful JSON API
  33. Apache CouchDB RESTful JSON API sb@thinkpad ~ % curl -X GET http://127.0.0.1:5984/ {\"couchdb\":\"Welcome\",\"version\":\"0.9.0\"} sb@thinkpad ~ % curl -X GET http://127.0.0.1:5984/_all_dbs [] sb@thinkpad ~ % curl -X PUT http://127.0.0.1:5984/test {\"ok\":true} sb@thinkpad ~ % curl -X GET http://127.0.0.1:5984/_all_dbs [\"test\"] sb@thinkpad ~ % curl -X DELETE http://127.0.0.1:5984/test {\"ok\":true}
  34. Object_Freezer_Storage_CouchDB Storing an object in Apache CouchDB class SomeClass { private $foo = 'bar'; } require_once 'Object/Freezer/Storage/CouchDB.php'; $storage = new Object_Freezer_Storage_CouchDB( 'test', new Object_Freezer, TRUE, 'localhost', 5984 ); $id = $storage->store(new SomeClass);
  35. Object_Freezer_Storage_CouchDB Fetching an object from Apache CouchDB var_dump($storage->fetch($id)); object(SomeClass)#5 (3) { [\"foo\":\"SomeClass\":private]=> string(3) \"bar\" [\"__php_object_freezer_uuid\"]=> string(36) \"29ea0bf5-e3f8-4694-8278-7a58a40f9d1a\" [\"__php_object_freezer_hash\"]=> string(40) \"b4eb9c1b85b392b06e778ded6fe3136859d7e7e3\" }
  36. Object_Freezer_Storage_CouchDB Implementation: PHP Code protected function doStore(array $frozenObject) { $payload = array('docs' => array()); foreach ($frozenObject['objects'] as $_id => $_object) { if ($_object['isDirty'] !== FALSE) { $payload['docs'][] = array( '_id' => $_id, 'class' => $_object['className'], 'state' => $_object['state'] ); } } if (!empty($payload['docs'])) { $this->send( 'POST', '/' . $this->database . '/_bulk_docs', json_encode($payload) ); } }
  37. Object_Freezer_Storage_CouchDB Implementation: JSON Message POST /test/_bulk_docs { \"docs\": [ { \"_id\": \"8314aba0-fe30-494f-b836-edc9e7366366\", \"class\": \"SomeClass\", \"state\": { \"__php_object_freezer_hash\": \"9bb7d790...\", \"foo\": \"bar\" } } ] }
  38. Object_Freezer_Storage_CouchDB Implementation: PHP Code protected function doFetch($id, array &$objects = array()) { $isRoot = empty($objects); if (!isset($objects[$id])) { $response = $this->send('GET', '/' . $this->database . '/' . $id); if (strpos($response['headers'], 'HTTP/1.0 200 OK') === 0) { $object = json_decode($response['body'], TRUE); } else { throw new RuntimeException( sprintf('Object with id \"%s\" could not be fetched.', $id) ); } $objects[$id] = array( 'className' => $object['class'], 'isDirty' => FALSE, 'state' => $object['state'] ); if (!$this->lazyLoad) { $this->fetchArray($object['state'], $objects); } } if ($isRoot) { return array('root' => $id, 'objects' => $objects); } }
  39. Object_Freezer_Storage_CouchDB Implementation: JSON Message GET /test/8314aba0-fe30-494f-b836-edc9e7366366 { \"_id\": \"8314aba0-fe30-494f-b836-edc9e7366366\", \"_rev\": \"2289472561\", \"class\": \"SomeClass\", \"state\": { \"__php_object_freezer_hash\": \"9bb7d790...\", \"foo\": \"bar\" } }
  40. Object_Freezer Less than 400 lines of executable code sb@thinkpad object-freezer % phploc Object phploc 1.1.0 by Sebastian Bergmann. Directories: 4 Files: 9 Lines of Code (LOC): 1559 Executable Lines of Code (ELOC): 398 Comment Lines of Code (CLOC): 973 Non-Comment Lines of Code (NCLOC): 586 Interfaces: 2 Classes: 7 Non-Static Methods: 36 Static Methods: 2 Functions: 0
  41. The End Thank you for your interest! These slides will be linked soon from http://sebastian-bergmann.de/
  42. References  http://martinfowler.com/eaaCatalog/activeRecord.html  http://kore-nordmann.de/blog/why_active_record_sucks.html  http://en.wikipedia.org/wiki/Object-relational_mapping  http://blogs.tedneward.com/2006/06/26/The+Vietnam+Of+Computer+Science.aspx  http://martinfowler.com/eaaCatalog/unitOfWork.htm  http://martinfowler.com/eaaCatalog/identityMap.htm  http://martinfowler.com/eaaCatalog/lazyLoad.htm
  43. License   This presentation material is published under the Attribution-Share Alike 3.0 Unported license.   You are free: ✔ to Share – to copy, distribute and transmit the work. ✔ to Remix – to adapt the work.   Under the following conditions: ● Attribution. You must attribute the work in the manner specified by the author or licensor (but not in any way that suggests that they endorse you or your use of the work). ● Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under the same, similar or a compatible license.   For any reuse or distribution, you must make clear to others the license terms of this work.   Any of the above conditions can be waived if you get permission from the copyright holder.   Nothing in this license impairs or restricts the author's moral rights.

+ Sebastian BergmannSebastian Bergmann, 6 months ago

custom

4029 views, 12 favs, 13 embeds more stats

The PHP Object Freezer provides the low-level funct more

More info about this document

CC Attribution-ShareAlike LicenseCC Attribution-ShareAlike License

Go to text version

  • Total Views 4029
    • 3276 on SlideShare
    • 753 from embeds
  • Comments 1
  • Favorites 12
  • Downloads 153
Most viewed embeds
  • 562 views on http://sebastian-bergmann.de
  • 101 views on http://www.planet-php.net
  • 41 views on http://www.3wstudio.com.ar
  • 19 views on http://www.planet-php.org
  • 17 views on http://planet-php.org

more

All embeds
  • 562 views on http://sebastian-bergmann.de
  • 101 views on http://www.planet-php.net
  • 41 views on http://www.3wstudio.com.ar
  • 19 views on http://www.planet-php.org
  • 17 views on http://planet-php.org
  • 4 views on http://www.slideshare.net
  • 2 views on http://xss.yandex.net
  • 2 views on http://planet-php.net
  • 1 views on http://www.phpro.org
  • 1 views on http://feed.bmaron.net
  • 1 views on http://127.0.0.1:8795
  • 1 views on http://www.birds.cornell.edu
  • 1 views on http://favit.dev

less

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate. If needed, use the feedback form to let us know more details.

Cancel
File a copyright complaint
Having problems? Go to our helpdesk?

Categories