Play-Doh: Modelling Your Objects
Upcoming SlideShare
Loading in...5

Play-Doh: Modelling Your Objects



Updated version of my tek09 uncon talk, covering the pitfalls of standard database-driven development and ways to apply design patterns to make your code more maintainable, extensible, and flexible.

Updated version of my tek09 uncon talk, covering the pitfalls of standard database-driven development and ways to apply design patterns to make your code more maintainable, extensible, and flexible.



Total Views
Views on SlideShare
Embed Views



26 Embeds 975 481 149 70 39 37 35 29
http://www.webcreator.kiev 24 22 20 16 15 6 6 5 5 4 3
http://localhost 2 1 1 1 1 1 1 1


Upload Details

Uploaded via as OpenOffice

Usage Rights

CC Attribution-NonCommercial-ShareAlike LicenseCC Attribution-NonCommercial-ShareAlike LicenseCC Attribution-NonCommercial-ShareAlike License

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
  • @Matthew Thank you for the quick response. In the slides presented, I am trying to figure out which was implied (duck typing or interface). The constructor of the decorators used type hinting of the decorated class, but that type hint was the actual class type. In that case, if I were to write another decorator for the same object, I would not be able to decorate a decorated object.

    Also would the idea with the slide example be that there's a __call() implementation that sends any unrecognized calls into the decorated object?

    Thanks again,
    Are you sure you want to
    Your message goes here
  • @David: There are two approaches: duck typing and interfaces. Interfaces are the more classic approach, and in such an approach, the decorator would implement the interface, and in most instances simply proxy calls back to the mapper being decorated (except when modifying functionality). This approach enforces contracts -- but makes the actual implementation more verbose (no more relying on __cal()).

    In duck typing, the idea is that we wouldn't type hint for the object, but instead let the language enforce the interface. In other words, if we call a method not available on the object, PHP barfs. This approach offers more flexibility and is typically more concise, but can lead to difficulties in debugging and maintenance.
    Are you sure you want to
    Your message goes here
  • In the decorator examples, you're using type hinting to ensure you get a PersonMapper or Person class passed into the constructor. However the decorating classes themselves don't meet that same type hint. How would you be able to do something like give the mapper the ability to log information as well as cache the database call?

    It seems like the decorators would either need to extend the base class (probably wrong), or the PersonMapper and the CachingPersonMapper would need to both implement some interface and that interface would need to be the type hint for the constructor of the decorator?

    Any insight you can provide would be very appreciated. I've been showing this to lots of coworkers but we have all been tripped up by the decorator example.

    Are you sure you want to
    Your message goes here
  • Nice lesson about 'Modelling Your Objects'
    Are you sure you want to
    Your message goes here
Post Comment
Edit your comment

Play-Doh: Modelling Your Objects Play-Doh: Modelling Your Objects Presentation Transcript

  • Play-Doh: Modelling your Objects Matthew Weier O'Phinney Project Lead Zend Framework CodeWorks 2009 Webinar Series 24 July 2009
  • Goals
    • Learn to recognize why old habits may be bad View slide
    • Learn several design patterns that can help you write testable, maintainable code View slide
    • Learn some techniques for altering existing behavior without rewriting existing code
  • What we've learned and what we do
  • Oooh! Let's create the schema!
  • Write code that uses the DB
    • Plain Old Mysql (POM)
    • ActiveRecord
    • Table/Row Data Gateway
  • And then …
    • we start lamenting about performance
    • we end up refactoring for every new feature (e.g. caching, logging)
    • we need to go to a Service Oriented Architecture, and effectively refactor twice
  • Step One
  • Models are just classes. Create classes.
  • Models have metadata and behavior; create properties and methods .
  • class Person { // 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 () { } }
  • Step Two
  • Now start thinking about data persistence .
    • Identify what data you need to persist
    • Identify how you'll persist the data
    • Write code for persisting data (Data Access Layer)
  • CREATE TABLE person ( username VARCHAR PRIMARY KEY , password VARCHAR , email VARCHAR , ); class PersonTable extends Zend_Db_Table_Abstract { protected $_name = 'person' ; protected $_primary = 'username' ; }
  • Step Three
  • Map your model to your data.
    • Common approaches:
      • Transaction Script (can even use POM)
      • Table Module (often with ActiveRecord or Table Data Gateway)
      • Data Mapper / ORM
  • class PersonMapper { public function save ( Person $person ) { $data = array ( 'username' => $person -> username , 'password' => $person -> password , 'email' => $person -> email , ); $this -> getTable ()-> save ( $data ); } public function fetch ( $username = null ); public function getTable (); public function setTable ( $table ); }
    • Some notes:
      • Data !== Relational Database. Data could come from a document database, filesystem, cache, or web service.
      • Choose an ORM that allows you to generate your schema from your entities; allows you to easily model first, and persistence comes for free.
  • Step Four
  • Move business and application logic to a Service Layer .
  • Applications are like onions; they have layers. Photo © 2008, Mike Chaput-Branson
  • The Service Layer provides application logic on top of your models
  • Service layer in perspective Data Access Objects and Data store(s) Data Mappers Domain Models Service Layer
    • Benefits to a Service Layer:
      • Allows easy consumption of the application via your MVC layer
      • Allows easy re-use of your application via services
      • Write CLI scripts that consume the Service Layer
    • What kind of application logic?
      • Validation and filtering
      • Authentication and Authorization
      • Transactions and interactions between model entities
  • 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 ; } }
  • Decorating for Fun and Profit
  • Decorators allow you to add or alter functionality of an existing class.
    • Typical decorator:
      • Implements same interface(s) of class being decorated
      • Uses overloading to proxy to decorated class
      • Override specific behavior you wish to modify or enhance
      • Add new behavior that uses existing behavior in the decorated class
  • Refactor to add caching? No! Decorate!
  • class CachingPersonMapper { protected $_mapper ; public function __construct ( PersonMapper $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 ; } }
  • Refactor to provide alternate return formats? (e.g., JSON vs XML vs ...) No! Decorate!
  • class JsonPerson { protected $_person ; public function __construct ( Person $person ) { $this -> _person = $person ; } public function __toString () { $data = array ( 'username' => $this -> _person -> username , 'email' => $this -> _person -> email , ); return json_encode ( $data ); } }
  • Nicely formed objects
    • Rebuilding and refactoring is costly and painful
    • Good OOP and encapsulation CAN make your life easier
    • Testing is easier than debugging
    • Choose a good ORM to expedite development. (Doctrine is an excellent choice)
  • Think beyond the DB!
  • Thank you.