SitePoint Sponsor

User Tag List

Page 2 of 3 FirstFirst 123 LastLast
Results 26 to 50 of 59
  1. #26
    SitePoint Guru OfficeOfTheLaw's Avatar
    Join Date
    Apr 2004
    Location
    Quincy
    Posts
    636
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by lastcraft

    As for memory, one of the worst offenders seems to be PHP hashes. I have seen factor of six increases in the data size once loaded into a hash. You just cannot predict these things, you have to measure .
    hashes? I expected objects to create more overhead, but now you got me worried. Hashes are nice and simple to use, and I tend to use them quite often. Should I be worried?

  2. #27
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Probably not. Xdebug will reveal all.

  3. #28
    SitePoint Wizard DougBTX's Avatar
    Join Date
    Nov 2001
    Location
    Bath, UK
    Posts
    2,498
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by hantu
    That exactly what I don't want to have. The business objects should be oblivious how and if they are persisted. I don't want persistence layer specific code inside them.
    What records changes made to these objects then? Or would you just run an Update based on all the data taken out of the database, assuming that anthing put in could have changed?

    I was just trying to demonstrate that the code needed to record changes in data doesn't need to be complicated. Here are two examples, one uses GetSetter, the other doesn't.

    PHP Code:
    class Biz {

       protected 
    $something;

       function 
    doSomething($stuff) {
          
    $this->something $stuff 100;
       }

    and with GetSetter:

    PHP Code:
    class Biz extends GetSetter {

       function 
    doSomething($stuff) {
          
    $this->something $stuff 100;
       }

    The change is quite transparent imo.

    Douglas
    Hello World

  4. #29
    SitePoint Zealot sleepeasy's Avatar
    Join Date
    Sep 2003
    Location
    Bristol, UK
    Posts
    145
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by DougBTX
    What records changes made to these objects then? Or would you just run an Update based on all the data taken out of the database, assuming that anthing put in could have changed?
    The code you posted (although I admit was just very small example) wouldn't be able to record changes either, unless the Biz class flags that one of it's properties has been updated. But this will require changes to the Biz class, or at the very least starts to place an extra burden on it (that of having to record changes to itself).

    Yes, you could do something within a __set() method of the GetterSetter class, but this would only work if the property being changed hasn't been defined in the Biz class. The problem here is that the Biz class probably will define all it's properties - I'm basing this on the fact that I belive most people define properties when they code their classes.

    I have to agree with hantu
    Quote Originally Posted by hantu
    The business objects should be oblivious how and if they are persisted
    I think that the code working with the business object should be responsible for calling an update. It doesn't need any datastore specific details, it should simply realise that if it updates an object that it has previously retrieved from a datastore then it must store it again.

    PHP Code:
    interface DataStore_IStore {
        public function 
    getById($id);
        public function 
    nativeQuery($query);
        public function 
    store($object);
        
    // public function getBy...
        // DataStore implementors will define additional
        // methods to simplify retrieval

    When working with persistent objects you have to retrieve them from somewhere, whatever pattern you're using - ActiveRecord, DataMapper or whatever. Requiring client code to have the small intelligence required to know that they must specifically pass any modified objects for storage is not a major inconvenience IMHO.




    What I have been complementing is a kindof reversed approach to what you posted. Instead of having the Biz class extend the GetterSetter, you have the GetterSetter extend the Biz class. Now you may (quite rightly) be thinking that this is rather foolish. However, the way I'm thinking is that this is not for instantiation by client code, but would be used by the datastore to wrap an instance of Biz...

    PHP Code:
    class Biz { }
    class 
    Biz_Persistent extends Biz { }

    class 
    Biz_DataStore {
        
    // ...
        
    public function getById($id) {
            
    // get the requested Biz object as $biz
            
    return (new Biz_Persistent($biz))
        } 
    // getById()


    Now the Biz_Persistent object acts as a wrapper (I was going to call it a decorator but I don't think that it is) for the Biz object, but because it extends Biz itself it will be accepted by all methods that use typehinting

    PHP Code:
    public function extractBiz(Biz $biz); 
    The Biz_Persistent object could record any changes to the Biz object it is wrapping, the Biz object itself would be none the wiser and would not require any modification. Client code would be oblivious aswell, Biz_Persistent would simply pass any calls it doesn't want to handle on to the object it is wrapping.

    The obvious downside is that Biz_Persistent will have to ovverride all methods it inherits and pass the call on to it's subject.

    Note I haven't written one line of code to implement this idea. I've only been thinking about it, and arguing with myself whether it could work even though it is a rather horrid use of inheritance, or I'm just nuts.

    One obvious thing that could break this very easily is adding a method to Biz. Biz_Persistent would have to be updated to override that method and pass it on to the Biz object it is wrapping.

    After writing about this I seem to be leaning further away from it, but I will leave it in the post just to see what other people think of it, and for something to look back on in a few years when I need proof of my craziness.

    Your opinion(s) would be appreciated
    Always open to question or ridicule

  5. #30
    SitePoint Wizard DougBTX's Avatar
    Join Date
    Nov 2001
    Location
    Bath, UK
    Posts
    2,498
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by sleepeasy
    The obvious downside is that Biz_Persistent will have to ovverride all methods it inherits and pass the call on to it's subject.
    With code generation and reflection, that shouldn't be too big an issue.

    A bigger question for me: how does Biz_Persistent know which methods it wants to watch? And how/what does it watch? (Edit: If this did work on with generated code, how would the generator know what to watch? Then you've got to build the Biz class to a spec that the generator understands, and you are back to aquare one again... because if you don't generate things it is a bunch of extra code ou have to write...)

    I'd be happier with something along the lines of the Memento pattern, though again that is the buisness object knowing that it wants to send a memento at some point.

    Douglas
    Hello World

  6. #31
    SitePoint Enthusiast hantu's Avatar
    Join Date
    Oct 2004
    Location
    Berlin
    Posts
    54
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by DougBTX
    What records changes made to these objects then? Or would you just run an Update based on all the data taken out of the database, assuming that anthing put in could have changed?
    This is a problem I haven't really solved yet.

    One of my first Ideas was to put a decorator around loaded objects that tracks the changes a bit like sleepeasy suggested. It could magically catch all method calls via _call, pass them to the decorated class and record changes done by set* calls.

    The problem is if you do an instanceof check on the retrieved object, then you will get the classname of the decorator not the classname of the wrapped object. This could be very confusing and maybe you would have to change your business logic which is want I strictly want to avoid.

    Holding copies of loaded objects is not an option either as it surely eats up to much memory and the comparison would take too long.

    Any ideas on this?

  7. #32
    SitePoint Wizard DougBTX's Avatar
    Join Date
    Nov 2001
    Location
    Bath, UK
    Posts
    2,498
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by hantu
    The problem is if you do an instanceof check on the retrieved object, then you will get the classname of the decorator not the classname of the wrapped object. This could be very confusing...
    Only if the person working with the code doesn't understand inheritance and interfaces, but I would like to assume they do. If you had each of your Biz objects support an IBiz interface (it could be a different interface for each Biz object) and then did typecasting/instanceof against that, then you wouldn't need to worry about whether a certain piece of code relies on Biz or Biz_Persistent, as they could both support the IBiz interface.

    Douglas
    Hello World

  8. #33
    SitePoint Zealot sike's Avatar
    Join Date
    Oct 2002
    Posts
    174
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    the UnitOfWork would be a possible solution :

    Code:
     $uow = new UnitOfWork();
     //create object of class Foo
     $foo = $uow->create('Foo');
     //work with foo
     $foo->name = 'Bar';
     $uow->commit();
    the idea behind is that the UnitOfWork holds a copy of the object and checks on commit if any changes happened.
    for a good example see lastcrafts post "a different slant on persistence". the only problem i see is that you should avoid using only one UnitOfWork for all your updates because of the memory problems. treat it more like a sql transaction.. this are only some rough thoughts.

    cheers
    Sike

  9. #34
    SitePoint Zealot sleepeasy's Avatar
    Join Date
    Sep 2003
    Location
    Bristol, UK
    Posts
    145
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by DougBTX
    With code generation and reflection, that shouldn't be too big an issue.

    A bigger question for me: how does Biz_Persistent know which methods it wants to watch? And how/what does it watch? (Edit: If this did work on with generated code, how would the generator know what to watch? Then you've got to build the Biz class to a spec that the generator understands, and you are back to aquare one again... because if you don't generate things it is a bunch of extra code ou have to write...)
    Yes, I should've mentioned that I envisioned using the reflection API to generate the code for Biz_Persistent. The generated class would have to override all methods and the body would simply consist of passing the call on to it's subject.

    Some intervention from the developer would be required to tell the generator which methods are getter/setter methods so that it can flag any calls to those methods before passing the call on to the subject.

    I just realised that this already cumbersome idea will well and truly be broken if Biz has publicly accessible properties - however rare they are in my own code, the possibility remains that someone will want to code their business object with public properties.

    Quote Originally Posted by DougBTX
    Only if the person working with the code doesn't understand inheritance and interfaces, but I would like to assume they do. If you had each of your Biz objects support an IBiz interface (it could be a different interface for each Biz object) and then did typecasting/instanceof against that, then you wouldn't need to worry about whether a certain piece of code relies on Biz or Biz_Persistent, as they could both support the IBiz interface.
    This would be great, however, I believe interfaces should be used to define an interface for a service provider, and/or service subjects.. e.g. IPublisher, and IPublishable. Having an interface for each business object seems a bit strange to me. I will need to think about it a bit more, so I'm not saying I think it's wrong, just that it's a different use of interfaces to how I've used them.

    It certainly would solve the problem though.
    Always open to question or ridicule

  10. #35
    SitePoint Enthusiast hantu's Avatar
    Join Date
    Oct 2004
    Location
    Berlin
    Posts
    54
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If I would force my business objects to implement a certain interface or inherit from a certain class for persistence functionality than this would break my initial approach: make the business objects oblivious how and if they are persisted.

    If this was necessary I'd rather say use propel cause it will generate all the code and is already available.

    I already have coded a decorator that is able to track the changes, but like said before, the problem is the classname checks of decorated objects.

    Heres how the decorator would look like:
    PHP Code:

    class ModificationTrackingDecorator {

      private 
    $modifiedAttributes;
      private 
    $attributes;
      private 
    $originalObject;
      
      function 
    __construct($original$attributesToWatch) {
        
    $this->originalObject $originalObject;
        
    $this->attributes $attributesToWatch;
        
    $this->modifiedAttributes = array();
      }
        
      function 
    __call($method$params) {  

        if (
    substr($method03) == 'set') {
          
    $attribute strtolower(substr($method3strlen($method)));
          
          if (
    in_array($attribute$this->attributesToWatch)) {
            
    $this->modifiedAttributes[] = $attribute;
          }
        }
            
        return 
    $this->originalObject->$method($params);
      }
      
      function 
    getModifiedAttributes() {
        return 
    array_unique($this->modifiedAttributes);
      }


  11. #36
    SitePoint Wizard DougBTX's Avatar
    Join Date
    Nov 2001
    Location
    Bath, UK
    Posts
    2,498
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by hantu
    make the business objects oblivious how and if they are persisted.

    ...

    I already have coded a decorator that is able to track the changes, but like said before, the problem is the classname checks of decorated objects.
    Using your setup, how would a buisness object store its "last modified" date in the database? The Biz object would calculate this value itself, using time().

    Douglas
    Hello World

  12. #37
    SitePoint Enthusiast hantu's Avatar
    Join Date
    Oct 2004
    Location
    Berlin
    Posts
    54
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by DougBTX
    Using your setup, how would a buisness object store its "last modified" date in the database? The Biz object would calculate this value itself, using time().
    Douglas
    I would give my object a function getLastModified() which returns time() and map it to the database like all other attributes.

  13. #38
    SitePoint Wizard DougBTX's Avatar
    Join Date
    Nov 2001
    Location
    Bath, UK
    Posts
    2,498
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by hantu
    I would give my object a function getLastModified() which returns time() and map it to the database like all other attributes.
    Then how is it tracked with ModificationTrackingDecorator?

    Still trying to understand your setup,
    Douglas
    Hello World

  14. #39
    ********* Victim lastcraft's Avatar
    Join Date
    Apr 2003
    Location
    London
    Posts
    2,423
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Hi...

    Myself and Jeff have been carrying on an e-mail correspondence that mirrors this discussion. That is, how to get the mappers completely invisible to the DomainObjects. Here are some thoughts so far...

    The DynamicProxy solution (that reflective Decorator thingy) does not work properly. If the methods are called internally they will bypass the intercept...
    PHP Code:
    class Thing {
        public 
    $first;
        public 
    $surname;

        function 
    setName($first$surname) {
            
    $this->setFirstName($first);
            
    $this->setSurname($surname);
        }

    This problem doesn't affect the generated subclass solution.

    There is a split now depending on whether you persist via. member variable, or only through accessors.

    The subclass solution has the problem of not being able to hide the public members in the same way a Proxy would do, but does give you the option of making them protected. The trouble is that any direct change to the members will bypass the dirty flag that tracks whether you need to save it. You could avoid this problem by not keeping a dirty flag at all.

    Despite my initial horror of keeping two copies of data lying around for comparison I am now thinking that this isn't such a bad thing after all. The business objects that get updated are pretty important objects. if you are iterating through a large set of objects updating everyone, then if you want to send the updates as one query you have to keep at least one copy of the data anyway. Once this the data set is too large, you have to switch to sending the query straight away on update anyway. All having too copies of the data lyng around does, is force you to halve the threshold where this switch in update strategy happens. It doesn't fundamentally affect the issue of in memory data references at all.

    If you use accessors then your subclass type proxy thingy can keep track of the dirty status. This other approach of accessors forces the domain object to use the accessors internally as well ot it loses the plot. You could argue that this is good practice anyway, but it allows the possibility of error.

    Anyway, I can see three options: keep two copies of the data mapping off of the members (public members), keep two copies of the data mapping off accessors (lots of accessors) or dirty flag restricting the option to accessors (must use accesors internally).

    Another problem with mappers is collections. What if you have a collection and you want to add an item to it...?
    PHP Code:
    class Parent {

        function 
    happyDay() {
            
    $this->children[] = new Child();
        }

    You have now lost any proxies. Also if you just load arrays then when you construct the object you will have to load any children as well. That could result in a large part of the DB being loaded. The escape route is not to load a simple array, but some kind of lazy collection. That means that the collection will have to know how to add and delete objects and it means that the domain objects will have to understand collections...
    PHP Code:
    class Parent {

        function 
    happyDay() {
            
    $this->children->add(new Child());
        }

    This isn't too much of a restriction though.

    Mapping is an interesting one. Using XML will complicate the build process for the site and requires a second file. That means that you have to edit two files when a domain object changes. One option is to put the mapping information into the domain object file as some form of comment...
    PHP Code:
    class Person {
        public 
    $name;    ## @column name

    Here I am using a distinctive comment to make the parsing easier.

    For PHP the UnitOfWork seems a no brainer. Here is a sample without UnitOfWork in the fewest number of lines I can think of...
    PHP Code:
    $query = new Query('Person');
    $query->addCriteria(new Equality('name''Jill'));
    $jill $query->fetch();
    $jill->setSignature('Hi from J');
    $jill->commit(); 
    Usually you end up with all sorts of mappers/peers/brokers as well. Now with UnitOfWork...
    PHP Code:
    $transaction = new Transaction();
    $query $transaction->createQuery('Person');
    $query->addCriteria(new Equality('name''Jill'));
    $jill $query->fetch();
    $jill->setSignature('Hi from J');
    $transaction->commit(); 
    Almost the same number of lines of code (probably fewer in practice), but here you have transaction support, identity can be tracked, you don't have to remember to commit all the object individually. It's also easier to test as the only intercept point to replace it all with stubs/mocks is the Transaction object. This is the Changes structure of course with different names. The fact that it would be implemented with mappers underneath is a implementation detail.

    This is key to a PHP solution, because of the need to craete everything on every request you want construction at least as neat as usage.

    yours, Marcus
    Marcus Baker
    Testing: SimpleTest, Cgreen, Fakemail
    Other: Phemto dependency injector
    Books: PHP in Action, 97 things

  15. #40
    SitePoint Enthusiast hantu's Avatar
    Join Date
    Oct 2004
    Location
    Berlin
    Posts
    54
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by DougBTX
    Then how is it tracked with ModificationTrackingDecorator?

    Still trying to understand your setup,
    Douglas
    I wouldn't track it with that decorator.

    The approach of my setup is the following: Imagine you put up your business logic using a Domain Model (which basically means you model everything as objects).

    I would now like to be able to persist any of these objects without having to change their code (like apache OJB does).

    I'll give an example of what I imagine.

    PHP Code:

    class Product {

      private 
    $id;
      private 
    $name;
      private 
    $price;

      private 
    $category;
      private 
    $buyers = array();

      
    // + setters/getters ...
    }

    class 
    Category {

      private 
    $id;
      private 
    $name;

      private 
    $products = array();
      
    // + setters/getters ...
    }

    class 
    Buyer {
      private 
    $id;
      private 
    $email;

      private 
    $products = array();
      
    // + setters/getters ...

    Say thats the Domain Model. (operations omitted, I would place them in other classes).

    The structure is now: a Product has one category and many buyers. A buyer can have bought many products and a category has many products.

    Now the mapping is defined in an XML-File like in Propel and you create appropriate database tables.

    According to OJB, I would now like to have a PersistenceBroker that will handle object persistence transparently for you.

    That's how it would be used:


    PHP Code:
    $broker = new PersistenceBroker();

    // add a Product of category with id 12

    $p = new Product();
    $p->setName('Gameboy');
    $p->setPrice(99.90);

    $c = new Category();
    $c->setId(12);

    $p->setCategory($c);

    try {
      
    $broker->beginTransaction();
      
    $broker->store($p);  
      
    $broker->commitTransaction();
    }
    catch (
    PersistenceBrokerException $pbex) {
      
    $broker->abortTransaction();
      
    // more error handling
    }

    // some time later: load the first 100 buyers of this product that have a german email address

    $criteria = new Criteria();

    $criteria->addEqualsTo('product.name''GameBoy');
    $criteria->addLike('email''%.de');

    $query = new QueryByCriteria('Buyer'$criteria);
    $query->setRows(100);

    $buyers $broker->getCollectionByQuery($query); 

  16. #41
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Regarding two copies :
    Alternatively the business-objects could hold a hash of the data - probably $hash = md5(serialize($this)); would do. It will trade memory-usage for CPU-cycles, but you would spend CPU on the comparison anyway. My feeling is that's a sane tradeoff.

  17. #42
    ********* Victim lastcraft's Avatar
    Join Date
    Apr 2003
    Location
    London
    Posts
    2,423
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Hi...

    Quote Originally Posted by kyberfabrikken
    Regarding two copies :
    Alternatively the business-objects could hold a hash of the data - probably $hash = md5(serialize($this)); would do. It will trade memory-usage for CPU-cycles, but you would spend CPU on the comparison anyway. My feeling is that's a sane tradeoff.
    Good thinking. You only need to detect a change, not know what has changed as optimising the query fields is probably going to be small fry compared with other optimisation issues.

    yours, Marcus
    Marcus Baker
    Testing: SimpleTest, Cgreen, Fakemail
    Other: Phemto dependency injector
    Books: PHP in Action, 97 things

  18. #43
    SitePoint Enthusiast hantu's Avatar
    Join Date
    Oct 2004
    Location
    Berlin
    Posts
    54
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Wouldn't it be possible to combine the PersistenceBroker & Unit of Work concepts ?

    Between $broker->beginTransaction() and $broker->commitTransaction() you could put up a Unit of Work to keep track of everything thats happening.

    Just some rough thought.

  19. #44
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Actually I realized after posting that in theory using a hash is unsafe, since two distinct sources could have the same hash. Thus hash(a) == hash(b) is not allways equal to a == b. In theory mind you, since I would say the risk is like one in a thousand years. I could live with that risk.

  20. #45
    SitePoint Enthusiast hantu's Avatar
    Join Date
    Oct 2004
    Location
    Berlin
    Posts
    54
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    kyberfabrikken's hashing idea may get my Decorator/DynamicProxy finding the modified attributes properly:

    PHP Code:
    class ModificationTrackingDecorator {

      private 
    $attributesToWatch;
      private 
    $initialValues;
      private 
    $originalObject;

      function 
    __construct($originalObject$attributesToWatch) {
        
        
    $this->attributesToWatch $attributesToWatch;
        
    $this->originalObject $originalObject;
        
    $this->initialValues hashAttributes($originalObject$attributesToWatch);
      
      }

      function 
    __call($method$params) {    
        return 
    $this->originalObject->$method($params);
      } 


      private function 
    hashAttributes($object$attributes) {

        
    $hashes = array();

        foreach (
    $attributes as $attribute) {
          
    $method 'get'.ucfirst($attribute);
          
    $value $object->$method();

           if (
    is_object($value)) {
             
    $value serialize($value);
           }
       
           
    $hashes[] = md5($value);
        }
        return 
    $hashes;
      }


      function 
    getModifiedAttributes() {
     
        
    $modifiedAttributes = array();
        
    $currentValues hashAttributes($this->originalObject$this->attributesToWatch);

        for(
    $n=0;$max=sizeof($this->attributesToWatch);$n<$max;$n++) {

          if (
    $currentValues[$n] != $this->initialValues[$n]) {
             
    $modifiedAttributes[] = $$this->attributesToWatch[$n];
          }
        }

        return 
    $modifiedAttributes;
      }


    Imagine the broker gets an object to store now, it can easily get its state:

    it is not decorated -> created by the user
    decorated & no modifiedAttributes -> clean
    decorated & modifiedAttributes -> dirty, update could be done easily


    Question is: Is this the right way and place to keep track of the changes?
    Last edited by hantu; Dec 9, 2004 at 06:46. Reason: typo in code ;)

  21. #46
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Question is: Is this the right way and place to keep track of the changes?
    I don't like the Decorator-solution - It seems too much of a hack to me. Since the UnitOfWork would need a IdentityMap of all instantiated BusinessObjects anyway, why not let it maintain the hashes in the same place ? This will leave the BusinessObjects completely ignorant of being observed by the UnitOfWork.

    It may be a bad code smell though to have one object being so concerned with another objects data, but that's UnitOfWork in a nutshell methinks.

  22. #47
    SitePoint Enthusiast hantu's Avatar
    Join Date
    Oct 2004
    Location
    Berlin
    Posts
    54
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    I don't like the Decorator-solution - It seems too much of a hack to me. Since the UnitOfWork would need a IdentityMap of all instantiated BusinessObjects anyway, why not let it maintain the hashes in the same place ? This will leave the BusinessObjects completely ignorant of being observed by the UnitOfWork.
    Ok, agree with you. Just wanted to show that it would be possible with that decorator, but internal handling with a Unit of Work would of course be a better solution.

  23. #48
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I can't figure out if it's a good idea to keep a hash of each attribute for the BusinessObject, or just one hash per object. If we are dealing with an object with a lot of small (memorywise) attributes ... like integers ... the hash actually takes more space than the original value. This could be circumvented somehow by something like :
    PHP Code:
        foreach ($attributes as $attribute) { 
          
    $method 'get'.$attribute
          
    $value $object->$method(); 
           if (
    is_object($value)) { 
             
    $hashes[] = array(HASH_MODE_MD5md5(serialize($value))); 
           } else if (
    count($value) < 32) {
             
    $hashes[] = array(HASH_MODE_SCALAR$value); 
           } else {
             
    $hashes[] = array(HASH_MODE_MD5md5($value)); 
           }
        } 
    However, the more logic we put into the hash-construction, the more CPU-cycles we waste. At some point it will outweight the gained amount of memory.
    Last edited by kyberfabrikken; Dec 9, 2004 at 08:02. Reason: PHP is caseinsensitive -- No need for ucfirst()

  24. #49
    SitePoint Wizard DougBTX's Avatar
    Join Date
    Nov 2001
    Location
    Bath, UK
    Posts
    2,498
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    or just one hash per object.
    One per object, comparing the hashs of two properties is probably more expensive than just comparing the properties. Hopefuly comparing the hashes of two objects will be less expensive than comparing each attribute on each object.

    Douglas
    Hello World

  25. #50
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hopefuly comparing the hashes of two objects will be less expensive than comparing each attribute on each object.
    It surely will, but having a hash per attribute gives the added benifit of knowing witch attributes to update, thus making it possible to finetune the queries to only update those.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •