Architecting Your Models


Published on

Provides some approaches to the "M" in MVC -- Models -- and how to get away from tying models to your database, and instead adopt sane approaches that provide more flexibility and forward exapandibility in your code.

Published in: Technology
  • 'After being in relationship with Wilson for seven years,he broke up with me, I did everything possible to bring him back but all was in vain, I wanted him back so much because of the love I have for him, I begged him with everything, I made promises but he refused. I explained my problem to someone online and she suggested that I should contact a spell caster that could help me cast a spell to bring him back but I am the type that don't believed in spell, I had no choice than to try it, I meant a spell caster called Dr Zuma zuk and I email him, and he told me there was no problem that everything will be okay before three days, that my ex will return to me before three days, he cast the spell and surprisingly in the second day, it was around 4pm. My ex called me, I was so surprised, I answered the call and all he said was that he was so sorry for everything that happened, that he wanted me to return to him, that he loves me so much. I was so happy and went to him, that was how we started living together happily again. Since then, I have made promise that anybody I know that have a relationship problem, I would be of help to such person by referring him or her to the only real and powerful spell caster who helped me with my own problem and who is different from all the fake ones out there. Anybody could need the help of the spell caster, his email: or call him +2349055637784 you can email him if you need his assistance in your relationship or anything. CONTACT HIM NOW FOR SOLUTION TO ALL YOUR PROBLEMS'
    Are you sure you want to  Yes  No
    Your message goes here
  • nice :)
    Are you sure you want to  Yes  No
    Your message goes here
  • Hi,

    @gabreanuandrei, i'd like to add that what is so called 'domain logic' isn't limited to add behaviour inside your model classes representing the entities of the system. The business logic can live inside any class, and a service is not an exception. I think a 'well' (that's subjective) designed model layer can mix several approaches. If you take a look at Domain Driven Design for instance, you'll see that it introduces two different kind of services, one specific to the model, responsible of business operations, and being the glue between your models, and the second one dedicated to applicative code, but maybe that's the only aspect that you'll take from DDD, and you'll consolidate your approach being inspirated by other approaches radically different, and in the end, your model will be well organized, but also unique, unique for your project and unique for the business it is designed for, just like matthew pointed it out.

    I think that just opening a book and implementing your stuff exactly like it is 'right' is not necesseraly a good thing.

    At this time, i think that Matthew tried to have the best 'generic' approach he could have with the tools he had ;-)

    Today, it's not really a problem anymore since frameworks let your mind do the job !
    Are you sure you want to  Yes  No
    Your message goes here
  • @gabreanuandrei I want to point out a few things. First, this tutorial is almost 3 years old at this point. When I originally gave it, domain modelling in PHP was a fairly novel concept, and any information that moved developers away from having models directly extend objects that handled persistence (*ahem*ActiveRecord*ahem*) was a good step forward.

    Second: there are many, many valid ways to perform domain modelling. There is NOT a single correct way, however. Your choices will be informed by the project -- how big or small it is, how many developers you have, the complexity of the domain.

    Is the advice in the presentation _wrong_? I'd likely write a quite different presentation today -- but I wouldn't necessarily call the information in it inaccurate or bad. And yes, I've got a copy of Fowler's POEAA right next to me on my shelf, and have had my copy for many years. It's a guidebook, not a rulebook. ;-)
    Are you sure you want to  Yes  No
    Your message goes here
  • Isn't this tutorial actually bad? Based on Matin Fowler's article (and more on the web if you google) - basically the Service should NOT contain logic at all rather than just guide the client into using the Domain Model properly but also provide a public API of your application to clients (controllers, API's, cli scripts, etc.)

    What do you think?
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Architecting Your Models

  1. Architecting Your Models Matthew Weier O'Phinney Project Lead Zend Framework
  2. Goals
  3. <ul><li>Learn to recognize why old habits may be bad
  4. Learn several design patterns that can help you write testable, maintainable code
  5. Learn some techniques for altering existing behavior without rewriting existing code </li></ul>
  6. What We've Learned and What We Do
  7. Oooh! Let's create the schema!
  8. Write code that uses the DB
  9. <ul><li>Plain Old Mysql (POM)
  10. ActiveRecord
  11. Table/Row Data Gateway </li></ul>
  12. And then …
  13. <ul><li>We start lamenting about performance.
  14. We end up refactoring for every new feature (e.g. caching, logging).
  15. We need to go to a Service Oriented Architecture, and effectively refactor twice. </li></ul>
  17. Step One
  18. Models are just classes. Create classes.
  19. Models have metadata and behavior ; create properties and methods .
  20. class Person implements PersonInterface { // Metadata protected $_email ; protected $_password ; protected $_username ; // Cheat: use overloading to // provide setters/getters public function __get( $name ) { } public function __set( $name , $value ) { } // Behaviors public function authenticate() { } public function logout() { } public function ban() { } }
  21. Step Two
  22. Now start thinking about data persistence .
  23. <ul><li>Identify what data you need to persist
  24. Identify how you'll persist the data
  25. Write code for persisting data (Data Access Layer) </li></ul>
  26. CREATE TABLE person( username VARCHAR PRIMARY KEY , password VARCHAR , email VARCHAR , ); class PersonTable extends Zend_Db_Table_Abstract { protected $_name = 'person' ; protected $_primary = 'username' ; }
  27. Step Three
  28. Map your model to your data.
  29. Common approaches <ul><li>Transaction Script (can even use POM)
  30. Table Module (often with ActiveRecord or Table Data Gateway)
  31. Data Mapper / ORM </li></ul>
  32. class PersonMapper implements PersonMapperInterface { public function save(PersonInterface $person ) { $data = array ( 'username' => $person ->username, 'password' => $person ->password, 'email' => $person ->email, ); $this ->getTable()->save( $data ); } public function fetch( $username ); public function getTable(); public function setTable( $table ); }
  33. Some notes: <ul><li>Data !== Relational Database .
  34. Data could come from a document database, filesystem, cache, or web service.
  35. Choose an ORM that allows you to generate your schema from your entities; allows you to easily model first, and persistence comes for free. </li></ul>
  36. Step Four
  37. Move business and application logic to a Service Layer .
  38. Applications are like onions; they have layers. Photo © 2008, Mike Chaput-Branson
  39. The Service Layer provides application logic on top of your models
  40. Service Layer in perspective Data Access Objects and Data store(s) Data Mappers Domain Models Service Layer
  41. Benefits to a Service Layer <ul><li>Allows easy consumption of the application via your MVC layer
  42. Allows easy re-use of your application via services
  43. Write CLI scripts that consume the Service Layer </li></ul>
  44. What kind of application logic? <ul><li>Validation and filtering
  45. Authentication and Authorization
  46. Transactions and interactions between model entities </li></ul>
  47. class PersonService { public function create( array $data ) { $person = new Person(); if (! $data = $this ->getValidator() ->isValid( $data ) ) { throw new InvalidArgumentException(); } $person ->username = $data [ 'username' ]; $person ->password = $data [ 'password' ]; $person ->email = $data [ 'email' ]; $this ->getMapper()->save( $person ); return $person ; } }
  48. Decorating for fun and profit
  49. Decorators allow you to add or alter functionality of an existing class.
  50. Typical decorators … <ul><li>Implement the same interface(s) of the class being decorated
  51. Often use overloading to proxy to the decorated class
  52. Override specific behavior(s) you wish to modify or enhance
  53. Add new behaviors that use existing behaviors in the decorated class </li></ul>
  54. Refactor to add caching? No! Decorate!
  55. class CachingPersonMapper implements PersonMapperInterface { public function __construct( PersonMapperInterface $mapper ) { $this ->_mapper = $mapper ; } public function fetch( $username ) { $cache = $this ->getCache(); if (! $person = $cache ->load( $username )) { $person = $this ->_mapper ->fetch( $username ); $cache ->save( $person , $username ); } return $person ; } }
  56. Refactor to provide alternate return formats? (e.g., JSON, XML, etc.) No! Decorate!
  57. class JsonPerson implements PersonInterface { public function __construct( PersonInterface $person ) { $this ->_person = $person ; } public function __toString() { $data = array ( 'username' => $this ->_person->username, 'email' => $this ->_person->email, ); return json_encode( $data ); } }
  58. Nicely Formed Objects
  59. <ul><li>Rebuilding and refactoring is costly and painful
  60. Good OOP and encapsulation CAN make your life easier
  61. Testing is easier than debugging
  62. Choose a good ORM to expedite development. (Doctrine, Object Freezer, Zend_Entity, etc.) </li></ul>
  63. Think beyond the DB!
  64. Thank you! <ul><li>Feedback:
  65. Twitter: @weierophinney
  66. Blog: </li></ul>