3

I'm not sure if the title is the best way to describe this question.

This book - http://apress.com/book/view/9781590599099 - illustrates an implementation of the Unit of Work pattern. It goes a little something like this.

class UoW(){
   private array $dirty;
   private array $clean;
   private array $new;
   private array $delete;

   public static function markClean(Entity_Class $Object){
   //remove the class from any of the other arrays, add it to the clean array
   }

   public static function markDirty(Entity_Class $Object){
   //remove the class from any of the other arrays, add it to the dirty array
   }

   public static function markNew(Entity_Class $Object){
   //add blank entity classes to the new array
   }

   public static function markDelete(Entity_Class $Object){
   //remove the class reference from other arrays, mark for deletion
   }

   public function commit(){
   //perform all queued operations, move all objects into new array, remove any deleted objects
   }
}

class MyMapper(){
  public function setName($value){
     $this->name = $value;
     UoW::markDirty($this);//here's where the problem is
   }
} 

(Ignoring issues of static calls and dependencies for a moment)

The author notes that this implementation requires the coder to insert the relevant UoW marking methods, and that this elective honouring of the pattern can lead to errors. Now, taking on board the pros and cons of concrete accessors, you could perhaps automate the UoW invocation like this:

public function __set($key,$value){
   //check to see if this is valid property for this class
   //assuming the class has an array defining allowed properties 
   if(property_exists($this,$key)){
       $this->$key = $value;
       UoW::markDirty($this);

       /*
       * or alternatively use an observer relationship 
       * i.e. $this->notify();
       * assuming the UoW has been attached prior to this operation
       */
      }
   } 

So, my question is, how would you go about guaranteeing the appropriate UoW method was called when setting properties on a Domain Object?

Lizard
  • 43,732
  • 39
  • 106
  • 167
sunwukung
  • 2,815
  • 3
  • 41
  • 56
  • The *Unit of Work* and other patterns are described in detail in [*Patterns of Enterprise Application Architecture* by Martin Fowler](http://martinfowler.com/eaaCatalog/index.html). [You can read excerpts of it (including the relevant UoW pages) in Google Books.](http://books.google.de/books?id=FyWZt5DdvFkC&lpg=PT213&ots=eEDx-vWx6E&dq=%22with%20object%20registration%20(Figure%2011.2)%22&pg=PT211#v=onepage&q=%22with%20object%20registration%20(Figure%2011.2)%22&f=false) Fowler mentions *Object Registration*, *Caller Registration* and *UoWController* as possible approaches. – Gordon Jul 05 '10 at 10:01
  • I've got the book right here on my desk - but none of the methods "automate" registration or notification. Object and caller registration omits the need to mark data changes in the object, but require that all changes to the model be performed by the UoW itself in a commit(). – sunwukung Jul 05 '10 at 10:58
  • well, he mentions AOP, but that is admittedly barely feasible for PHP yet. Observer patterns sounds good to me though. – Gordon Jul 05 '10 at 11:35
  • Observer pattern is great if UoW is the sole means of persistence, but if the implementing code attempts persistence via the data mapper - it becomes ineffective. The problem is the reliance on referencing the UoW->notify()/UoW::markStatus method in the accessors. If accessors are replaced with magic methods, it would automate the notification without in the base class. Thanks for your comments though. – sunwukung Jul 05 '10 at 13:57
  • Unfortunately I don't think that the __set method is going to work. __set only gets called if there isn't a accessible property of a name. – Orangepill May 31 '13 at 06:42

1 Answers1

0

The best approach I've found is to declare the properties "protected" and then use PHPDoc comments to "expose" them as public properties. Something like:

/**
 * @property string $prop
 */
class Foo extends UoW {
    protected $prop = "foo";

    public function __set($name, $value) {
        if (property_exists($this, $name)) {
            $this->$name = $value;
            $this->markDirty();
        }
    }
}

This will cause your IDE and most tools to pick up that Foo->prop is a property, while ensuring the dirty mark gets set.

rich remer
  • 3,407
  • 2
  • 34
  • 47