Transparent Object Persistence (within FLOW3)

3,201 views

Published on

An overview and some details about how object persistence in FLOW3 works internally.

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,201
On SlideShare
0
From Embeds
0
Number of Embeds
1,458
Actions
Shares
0
Downloads
41
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Transparent Object Persistence (within FLOW3)

  1. 1. Transparent Object Persistence (within FLOW3) Karsten Dambekalns <karsten@typo3.org> Inspiring people to share Samstag, 16. Mai 2009
  2. 2. “DDD persistence” Domain Models encapsulate behavior and data Concerned about the problem – only Infrastructure is of no relevance Unfortunately you need to be aware of the infrastructure at some point – at least a little Inspiring people to share Samstag, 16. Mai 2009
  3. 3. Entities Identity is important Are not defined by their attributes Examples could be... • Projects • Developers Inspiring people to share Samstag, 16. Mai 2009
  4. 4. Value objects Have no indentity Their value is of importance Are interchangeable Examples could be... • Colors • Numbers • Tags in Forge Inspiring people to share Samstag, 16. Mai 2009
  5. 5. Aggregates Cluster associated objects Have a boundary and a root The root is a specific entity References from outside point to the root An example for an aggregate: • Project Inspiring people to share Samstag, 16. Mai 2009
  6. 6. Repositories Provide access to entities (and aggregates) Allow to find a starting point for traversal Persisted objects can be searched for Queries can be built in various ways Handle storage of additions and updates Inspiring people to share Samstag, 16. Mai 2009
  7. 7. A Domain Model Project Repository Project Developer SVN twitter Account Account Inspiring people to share Samstag, 16. Mai 2009
  8. 8. A Domain Model Project Repository it Project Repos Developer SVN twitter Account Account Inspiring people to share Samstag, 16. Mai 2009
  9. 9. A Domain Model Project Repository it Project Repos Developer SVN twitter Account Account Inspiring people to share Samstag, 16. Mai 2009
  10. 10. A Domain Model Project Repository it Project Repos Developer SVN twitter Account Account Inspiring people to share Samstag, 16. Mai 2009
  11. 11. A Domain Model Project Repository it Project Repos Developer Aggre- gates SVN twitter Account Account Inspiring people to share Samstag, 16. Mai 2009
  12. 12. A Domain Model Developer SVN twitter Account Account Inspiring people to share Samstag, 16. Mai 2009
  13. 13. Using FLOW3... You just implement the model No need to care about persisting your model FLOW3 handles this for you – transparently Even a Repository only needs little work Define relevant metadata in the source file using annotations Inspiring people to share Samstag, 16. Mai 2009
  14. 14. @nnotations used Inspiring people to share Samstag, 16. Mai 2009
  15. 15. @nnotations used @entity Inspiring people to share Samstag, 16. Mai 2009
  16. 16. @nnotations used @entity @valueobject Inspiring people to share Samstag, 16. Mai 2009
  17. 17. @nnotations used @entity @valueobject @var Inspiring people to share Samstag, 16. Mai 2009
  18. 18. @nnotations used @entity @valueobject @var @transient Inspiring people to share Samstag, 16. Mai 2009
  19. 19. @nnotations used @entity @valueobject @var @transient @uuid Inspiring people to share Samstag, 16. Mai 2009
  20. 20. @nnotations used @entity @valueobject @var @transient @uuid @identity Inspiring people to share Samstag, 16. Mai 2009
  21. 21. @nnotations used @entity @valueobject @var @transient @uuid @identity @lazy Inspiring people to share Samstag, 16. Mai 2009
  22. 22. Persistence Manager Mostly invisible to developers Manages additions of and updates to objects Concerned only about objects in repositories Collects objects and hands over to backend Allows for objects being persisted at any time Automatically called to persist at end of script run Inspiring people to share Samstag, 16. Mai 2009
  23. 23. Simplified stack SQLite PgSQL MySQL ... Inspiring people to share Samstag, 16. Mai 2009
  24. 24. Simplified stack PDO ... SQLite PgSQL MySQL ... Inspiring people to share Samstag, 16. Mai 2009
  25. 25. Simplified stack TYPO3 Content Repository PDO ... SQLite PgSQL MySQL ... Inspiring people to share Samstag, 16. Mai 2009
  26. 26. Simplified stack FLOW3 Persistence TYPO3 Content Repository PDO ... SQLite PgSQL MySQL ... Inspiring people to share Samstag, 16. Mai 2009
  27. 27. Simplified stack Application Application FLOW3 Persistence TYPO3 Content Repository PDO ... SQLite PgSQL MySQL ... Inspiring people to share Samstag, 16. Mai 2009
  28. 28. Simplified stack FLOW3 Persistence Persistence TYPO3 CR Backend Inspiring people to share Samstag, 16. Mai 2009
  29. 29. TYPO3 CR FLOW3 Inspiring people to share Samstag, 16. Mai 2009
  30. 30. Transparent persistence Explicit support for Domain-Driven Design Class Schemata are defined by the Domain Model class • No need to write an XML or YAML schema definition • No need to define the database model and object model multiple times at different places Automatic persistence in the JSR-283 based Content Repository Legacy data sources can be mounted Inspiring people to share Samstag, 16. Mai 2009
  31. 31. Query Factory Creates a query for you Decouples persistence layer from backend Must be implemented by backend API with one method: • public function create($className); Inspiring people to share Samstag, 16. Mai 2009
  32. 32. Query objects Represent a query for an object type Allow criteria to be attached Must be implemented by backend Simple API • execute() • matching() • equals(), lessThan(), ... • ... Inspiring people to share Samstag, 16. Mai 2009
  33. 33. Object reconstitution When fetching objects the content repository looks for matching nodes The nodes are mapped to objects by a data mapper Reconstitution • does not call __construct() • restores all non-transient properties • reinjects dependencies (skips constructor arguments) Inspiring people to share Samstag, 16. Mai 2009
  34. 34. Object reconstitution public function map(F3PHPCRNodeIteratorInterface $nodes) { $objects = array(); foreach ($nodes as $node) { $object = $this->mapSingleNode($node); $this->persistenceManager->getSession()->registerReconstitutedObject($object); $objects[] = $object; } return $objects; } F3TYPO3CRFLOW3PersistenceDataMapper Inspiring people to share Samstag, 16. Mai 2009
  35. 35. Object reconstitution $explodedNodeTypeName = explode(':', $node->getPrimaryNodeType()->getName(), 2); $className = str_replace('_', '', $explodedNodeTypeName[1]); $classSchema = $this->persistenceManager->getClassSchema($className); $objectConfiguration = $this->objectManager->getObjectConfiguration($className); $object = $this->objectBuilder->createEmptyObject($className, $objectConfiguration); $this->identityMap->registerObject($object, $node->getIdentifier()); $this->objectBuilder->reinjectDependencies($object, $objectConfiguration); $this->thawProperties($object, $node, $classSchema); $object->FLOW3_Persistence_memorizeCleanState(); F3TYPO3CRFLOW3PersistenceDataMapper Inspiring people to share Samstag, 16. Mai 2009
  36. 36. Object reconstitution public function createEmptyObject($objectName, F3FLOW3ObjectConfiguration $objectConfiguration) { $className = $objectConfiguration->getClassName(); if (!in_array('F3FLOW3AOPProxyInterface', class_implements($className))) { throw new F3FLOW3ObjectExceptionCannotReconstituteObject('Cannot create empty instance of the class quot;' . $className . 'quot; because it does not implement the AOP Proxy Interface.', 1234386924); } $object = unserialize('O:' . strlen($className) . ':quot;' . $className . 'quot;:0:{};'); $object->FLOW3_AOP_Proxy_setProperty('objectFactory', $this->objectFactory); $object->FLOW3_AOP_Proxy_setProperty('objectManager', $this->objectManager); $object->FLOW3_AOP_Proxy_declareMethodsAndAdvices(); return $object; } F3FLOW3ObjectBuilder Inspiring people to share Samstag, 16. Mai 2009
  37. 37. Lazy Loading Loading a full object tree makes sense – or not It does most of the time If your domain model has small aggregates eager loading makes sense If you have expensive to create objects or a lot of smaller ones you don’t always need, lazy loading helps Example: displaying a list of projects doesn’t need the projects details, just the names Inspiring people to share Samstag, 16. Mai 2009
  38. 38. Lazy Loading Ideally you would not think about lazy loading beyond the addition of the @lazy annotation In practice you need to be aware of some technical issues In place of the real object you get a proxy, so • you can’t use it at type hinted places • pass it around without some thinking Using it otherwise works as expected After first use the proxy will be completely gone Inspiring people to share Samstag, 16. Mai 2009
  39. 39. The LazyLoadingProxy public function _loadRealInstance() { $realInstance = $this ->F3_FLOW3_Persistence_LazyLoadingProxy_population ->__invoke(); $this ->F3_FLOW3_Persistence_LazyLoadingProxy_parent ->FLOW3_AOP_Proxy_setProperty( $this->F3_FLOW3_Persistence_LazyLoadingProxy_propertyName, $realInstance ); return $realInstance; } F3FLOW3PersistenceLazyLoadingProxy Inspiring people to share Samstag, 16. Mai 2009
  40. 40. $dataMapper = $this; // make available to closure... $objectStorage = new F3FLOW3PersistenceLazyLoadingProxy( $parent, $propertyName, function() use ($proxyNode, $dataMapper) { $objectStorage = new SplObjectStorage(); $itemNodes = $proxyNode->getNodes(); foreach ($itemNodes as $itemNode) { $objectNode = $itemNode->getNode('flow3:object'); if ($objectNode->getPrimaryNodeType()->getName() === F3TYPO3CRFLOW3PersistenceBackend::NODETYPE_OBJECTPROXY) { $object = $dataMapper->mapObjectProxyNode($objectNode); } else { $object = $dataMapper->mapSingleNode($objectNode); } $objectStorage->attach($object); } return $objectStorage; } ); F3TYPO3CRFLOW3PersistenceDataMapper Inspiring people to share Samstag, 16. Mai 2009
  41. 41. Node structure PHP has more data structures than a content repository, e.g. • JSR-283 defines multi-valued properties without keys and without stable ordering • Arrays in PHP have keys and order that are stable and might be important for your code Thus we do some more mapping to node structures Inspiring people to share Samstag, 16. Mai 2009
  42. 42. Inspiring people to share Samstag, 16. Mai 2009
  43. 43. Inspiring people to share Samstag, 16. Mai 2009
  44. 44. Inspiring people to share Samstag, 16. Mai 2009
  45. 45. Inspiring people to share Samstag, 16. Mai 2009
  46. 46. Inspiring people to share Samstag, 16. Mai 2009
  47. 47. Questions! Inspiring people to share Samstag, 16. Mai 2009
  48. 48. Inspiring people to share Samstag, 16. Mai 2009
  49. 49. Links FLOW3 http://flow3.typo3.org/ TYPO3CR http://forge.typo3.org/projects/show/package-typo3cr JSR-283 http://jcp.org/en/jsr/detail?id=283 Inspiring people to share Samstag, 16. Mai 2009
  50. 50. Samstag, 16. Mai 2009
  51. 51. Flickr photo credits: megapixel13 (barcode), rmrayner (ring), Ducatirider (grapes), Here’s Kate (book shelf) Pumpkin pictures: http://ptnoticias.com/pumpkinway/ Inspiring people to share Samstag, 16. Mai 2009

×