Transparent Object Persistence with FLOW3

3,621 views
3,511 views

Published on

Presentation on object persistence held during the T3CON09 in Irving, Texas on 2009-04-17

Published in: Technology
3 Comments
3 Likes
Statistics
Notes
No Downloads
Views
Total views
3,621
On SlideShare
0
From Embeds
0
Number of Embeds
163
Actions
Shares
0
Downloads
50
Comments
3
Likes
3
Embeds 0
No embeds

No notes for slide

Transparent Object Persistence with FLOW3

  1. 1. Transparent Object Persistence (with FLOW3) Karsten Dambekalns <karsten@typo3.org> Inspiring people to share
  2. 2. Old school persistence DDD persistence FLOW3 persistence Inspiring people to share
  3. 3. An example to use... Let’s use a Blog A Blog project has • a Blog • some Posts, • Comments and • Tags Easy enough, eh? Inspiring people to share
  4. 4. Setting the stage A blog is requested We want to show posts We have data somewhere We use MVC and have a view waiting We only need to hand over the posts Inspiring people to share
  5. 5. Blog tables^Wrelations blogs uid name 1 FLOW3 posts uid blog_id title author text date 1 1 FLOW3 R. Lemke Mēs esam vissforšākie, tāpēc ka... 2008-10-07 comments uid post_id author text 1 1 Kasper Skårhøj Nice writeup, but... posts_tags tags post_id tag_id uid name 1 1 1 PHP 1 3 2 DDD 3 FLOW3
  6. 6. Straight DB usage $row = mysql_fetch_assoc( mysql_query('SELECT uid FROM blogs WHERE name = '' . mysql_real_escape_string($blog) . ''') ); $blogId = $row['uid']; $posts = array(); $res = mysql_query('SELECT * FROM posts WHERE blog_id = ' . $blogId); while (($row = mysql_fetch_assoc($res)) !== FALSE) { $posts[] = $row; } $view->setPosts($posts); Inspiring people to share
  7. 7. Straight DB usage $row = mysql_fetch_assoc( mysql_query('SELECT uid FROM blogs WHERE name = '' . mysql_real_escape_string($blog) . ''') ); $blogId = $row['uid']; $posts = array(); SQL injection! • $res = mysql_query('SELECT * FROM posts WHERE blog_id = ' . $blogId); while (($row = mysql_fetch_assoc($res)) !== FALSE) { •clumsy code $posts[] = $row; } •other RDBMS $view->setPosts($posts); •field changes? Inspiring people to share
  8. 8. Straight DB usage $row = mysql_fetch_assoc( mysql_query('SELECT uid FROM blogs WHERE name = '' . mysql_real_escape_string($blog) . ''') ); $blogId = $row['uid']; $posts = array(); SQL injection! • $res = mysql_query('SELECT * FROM posts WHERE blog_id = ' . $blogId); while (($row = mysql_fetch_assoc($res)) !== FALSE) { •clumsy code $posts[] = $row; } •other RDBMS $view->setPosts($posts); •field changes? Inspiring people to share
  9. 9. DBAL in TYPO3v4 $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid', 'blogs', 'name = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($blog, 'blogs')); $blogId = $rows[0]['uid']; $posts = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', 'posts', 'blog_id = ' . $blogId); $view->setPosts($posts); Inspiring people to share
  10. 10. DBAL in TYPO3v4 $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid', 'blogs', 'name = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($blog, 'blogs')); $blogId = $rows[0]['uid']; $posts = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', 'posts', 'blog_id = ' . $blogId); $view->setPosts($posts); SQL injection! • •still clumsy... •field changes? Inspiring people to share
  11. 11. DBAL in TYPO3v4 $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid', 'blogs', 'name = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($blog, 'blogs')); $blogId = $rows[0]['uid']; $posts = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', 'posts', 'blog_id = ' . $blogId); $view->setPosts($posts); SQL injection! • •still clumsy... •field changes? Inspiring people to share
  12. 12. ORM tools ORM means Object-Relational Mapping Objects represent a database row Most tools are rather ROM – still focus on relational thinking Implementations differ • ORM base classes need to be extended • Schema is used to generate code Inspiring people to share
  13. 13. Active Record $blog = new Blog($blog); $posts = $blog->getPosts(); $view->setPosts($posts); Inspiring people to share
  14. 14. Active Record $blog = new Blog($blog); $posts = $blog->getPosts(); $view->setPosts($posts); very nice • •dependency on ORM tool? •save()/delete( ) Inspiring people to share
  15. 15. Active Record $blog = new Blog($blog); $posts = $blog->getPosts(); $view->setPosts($posts); very nice • •dependency on $post->save(); ORM tool? $post->delete(); •save()/delete( ) Inspiring people to share
  16. 16. “DDD persistence” Domain Models encapsulate behavior and data Concerned about the problem – only Infrastructure is of no relevance Inspiring people to share
  17. 17. Entities Identity is important Are not defined by their attributes Examples could be... • People • Blog posts Inspiring people to share
  18. 18. Value objects Have no indentity Their value is of importance Are interchangeable Examples could be... • Colors • Numbers • Tags in a blog Inspiring people to share
  19. 19. 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: • Book Inspiring people to share
  20. 20. 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
  21. 21. A Domain Model Blog Repository Blog Post Comment Tag Inspiring people to share
  22. 22. A Domain Model Blog Repository it Blog Repos Post Comment Tag Inspiring people to share
  23. 23. A Domain Model Blog Repository it Blog Repos Post Comment Tag Inspiring people to share
  24. 24. A Domain Model Blog Repository it Blog Repos Post Comment Tag Inspiring people to share
  25. 25. A Domain Model Blog Repository it Blog Repos Post Aggre- gates Comment Tag Inspiring people to share
  26. 26. A Domain Model Post Comment Tag Inspiring people to share
  27. 27. A Domain Model Post Comment Tag Inspiring people to share
  28. 28. A Domain Model Post Entity Comment Tag Inspiring people to share
  29. 29. A Domain Model Post Entity Comment Tag Entity Inspiring people to share
  30. 30. A Domain Model Post Entity Val ue Comment Tag Entity Inspiring people to share
  31. 31. Implementing this... Inspiring people to share
  32. 32. Implementing this... must be a lot of work! Inspiring people to share
  33. 33. Using FLOW3? Inspiring people to share
  34. 34. Using FLOW3? Inspiring people to share
  35. 35. 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 Inspiring people to share
  36. 36. The Blog class class Blog { /** * @var string */ protected $name; /** * @var SplObjectStorage */ protected $posts; /** * Constructs this blog * * @param string $name Name of this blog */ public function __construct($name) { $this->name = $name; } Inspiring people to share
  37. 37. The Blog class /** * Adds a post to this blog * * @param F3BlogDomainModelPost $post * @return void * @author Karsten Dambekalns <karsten@typo3.org> */ public function addPost(F3BlogDomainModelPost $post) { $this->posts->attach($post); } /** * Returns all posts in this blog * * @return SplObjectStorage containing F3BlogDomainModelPost * @author Karsten Dambekalns <karsten@typo3.org> */ public function getPosts() { return clone $this->posts; } Inspiring people to share
  38. 38. The Post class class Post { /** * @var string * @identity */ protected $title; /** * @var SplObjectStorage */ protected $comments; /** * Adds a comment to this post * * @param F3BlogDomainModelComment $comment * @return void * @author Robert Lemke <robert@typo3.org> */ public function addComment(F3BlogDomainModelComment $comment) { $this->comments->attach($comment); } Inspiring people to share
  39. 39. The Tag class class Tag { /** * @var string */ protected $name; /** * Setter for name * * @param string $name * @author Karsten Dambekalns <karsten@typo3.org> */ public function __construct($name) { $this->name = $name; } Inspiring people to share
  40. 40. The BlogRepository Now this really must be a complex piece of code, no? Inspiring people to share
  41. 41. The BlogRepository Now this really must be a complex piece of code, no? One word: No Inspiring people to share
  42. 42. The BlogRepository Now this really must be a complex piece of code, no? One word: No class BlogRepository extends F3FLOW3PersistenceRepository { /** * Returns one or more Blogs with a matching name if found. * * @param string $name The name to match against * @return array */ public function findByName($name) { $query = $this->createQuery(); $blogs = $query->matching($query->equals('name', $name))->execute(); return $blogs; } } Inspiring people to share
  43. 43. The BlogRepository Now this really must be a complex piece of code, no? One word: No class BlogRepository extends F3FLOW3PersistenceRepository { /** * Returns one or more Blogs with a matching name if found. * * @param string $name The name to match against * @return array */ public function findByName($name) { $query = $this->createQuery(); $blogs = $query->matching($query->equals('name', $name))->execute(); return $blogs; } } Inspiring people to share
  44. 44. @nnotations used Inspiring people to share
  45. 45. @nnotations used @entity Inspiring people to share
  46. 46. @nnotations used @entity @valueobject Inspiring people to share
  47. 47. @nnotations used @entity @valueobject @var Inspiring people to share
  48. 48. @nnotations used @entity @valueobject @var @transient Inspiring people to share
  49. 49. @nnotations used @entity @valueobject @var @transient @uuid Inspiring people to share
  50. 50. @nnotations used @entity @valueobject @var @transient @uuid @identity Inspiring people to share
  51. 51. @nnotations used @entity @valueobject @var @transient @uuid @identity @lazy Inspiring people to share
  52. 52. 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
  53. 53. Simplified stack SQLite PgSQL MySQL ... Inspiring people to share
  54. 54. Simplified stack PDO ... SQLite PgSQL MySQL ... Inspiring people to share
  55. 55. Simplified stack TYPO3 Content Repository PDO ... SQLite PgSQL MySQL ... Inspiring people to share
  56. 56. Simplified stack FLOW3 Persistence TYPO3 Content Repository PDO ... SQLite PgSQL MySQL ... Inspiring people to share
  57. 57. Simplified stack Application Application FLOW3 Persistence TYPO3 Content Repository PDO ... SQLite PgSQL MySQL ... Inspiring people to share
  58. 58. Simplified stack Inspiring people to share
  59. 59. Simplified stack TYPO3 Content Repository Inspiring people to share
  60. 60. Simplified stack FLOW3 Persistence TYPO3 Content Repository Inspiring people to share
  61. 61. 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
  62. 62. JSR-283 Repository Defines a uniform API for accessing content repositories A Content Repository • is an object database for storage, search and retrieval of hierarchical data • provides methods for versioning, transactions and monitoring TYPO3CR is the first PHP implementation of JSR-283 Karsten Dambekalns is member of the JSR-283 expert group Inspiring people to share
  63. 63. Legacy databases Often you... • still need to access some existing RDBMS • need to put data somewhere for other systems to access The Content Repository will allow “mounting” of RDBMS tables Through this you can use the same persistence flow Inspiring people to share
  64. 64. Legacy databases Often you... future • still need to access some existing RDBMS fun! • need to put data somewhere for other systems to access The Content Repository will allow “mounting” of RDBMS tables Through this you can use the same persistence flow Inspiring people to share
  65. 65. 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
  66. 66. 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
  67. 67. Client code ignores Repository implementation; Developers do not! Eric Evans Inspiring people to share
  68. 68. Inspiring people to share
  69. 69. Inspiring people to share
  70. 70. Usability Repositories extending FLOW3’s base Repository • have basic methods already • only need to implement custom find methods • already have a query object set up for “their” class No tables, no schema, no XML, no hassle No save calls, no fiddling with hierarchies Ready-to-use objects returned Inspiring people to share
  71. 71. Questions! Inspiring people to share
  72. 72. Inspiring people to share
  73. 73. 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
  74. 74. Literature Inspiring people to share
  75. 75. Literature Domain-Driven Design Eric Evans, Addison-Wesley Inspiring people to share
  76. 76. Literature Domain-Driven Design Eric Evans, Addison-Wesley Applying Domain-Driven Design and Patterns Jimmy Nilsson, Addison-Wesley Inspiring people to share
  77. 77. Literature Domain-Driven Design Eric Evans, Addison-Wesley Applying Domain-Driven Design and Patterns Jimmy Nilsson, Addison-Wesley Patterns of Enterprise Application Architecture Martin Fowler, Addison-Wesley Inspiring people to share
  78. 78. Flickr photo credits: megapixel13 (barcode), rmrayner (ring), Ducatirider (grapes), Here’s Kate (book shelf) Pumpkin pictures: http://ptnoticias.com/pumpkinway/ Inspiring people to share

×