SitePoint Sponsor

User Tag List

Results 1 to 14 of 14

Thread: Object values

  1. #1
    SitePoint Zealot
    Join Date
    Mar 2004
    Location
    netherlands
    Posts
    104
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Object values

    Back with a new question; How to fill an objects values?

    There are numbers of ways to do this, you can find the values outside the object, and then push it into the new one by using setters, you can pass a row from the database in array format to the constructor of the object, or you can even let the object find its own values by sending the constructor an unique parameter which equals the objects identity (like an id), and then use the constructor to find the values through a finder.

    Maybe a little weird question, because i see everyone using setters, but i feel like the finder way would be more reusable, because this way the object gets its own data.

    What would be the pro's and cons of these methods? Am I overseeing another good method? Any comments and/or tips?

    Thanks in advance

  2. #2
    SitePoint Addict silent's Avatar
    Join Date
    Jun 2004
    Location
    Roaming North America
    Posts
    220
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Everyone seems to have their own opinion on this one... Generally, I have "Model" type objects (kinda like C structs) that I can then pass to either a "Reader" or a "Writer" object which actually performs the action using the model's data.

    The getter/setter approach is, I think, a different issue, and one I try to stay away from since the "purists" seem to think that member variables shouldn't be accessed directly and the "realists" don't really care. I don't really care about the fashion that member variables are get/setted, as long as the style is consistent throughout the object model...

    Example:

    PHP Code:
    class Model {

        var 
    $MemberVariable1 '';
        var 
    $MemberVariable2 '';
        
        function 
    Model(){}
    }

    class 
    ModelReader() {

        var 
    $_Model null;
        
        function 
    ModelReader( &Model ) {
            
    $this->_Model =& new Model();
        }
        
        
    /**
         * @access    public
         */
        
    function &GetModel$Id ) {
            
    // Populate last minute...when actually needed
            
    $this->_LoadModel($Id);
            return 
    $this->_Model;
        }
        
        
    /**
         * @access    private
         */
        
    function _LoadModel() {
            
    // Code to populate Model from Db or other storage here...
        
    }
        
    }

    class 
    ModelWriter() {

        var 
    $_Model null;
        
        function 
    ModelWriter( &Model ) {
            
    $this->_Model =& $Model;
        }
        
        
    /**
         * @access    public
         * @return     bool
         */
        
    function WriteModel() {
            
    // Save Model to Db or other storage and return success of storage
        
    }
        

    Usually before the Model is passed to the Writer, I will set the publicly available properties directly, as in:

    PHP Code:
    $oModel =& new Model();
    $oModel->MemberVariable1 'a string';
    $oModel->MemberVariable2 12
    then pass to the Writer:

    PHP Code:
    $oWriter =& new ModelWriter($oModel);
    if (!
    $oWriter->WriteModel()) {
      
    // Log Errors...

    Likewise, I will access properties of a Model (delivered from a Reader) directly:

    PHP Code:
    $oReader =& new ModelReader();
    $oModel =& $oReader->GetModel(14); // Assume 14 is the ID...
    // Do some other stuff...
    echo $oModel->MemberVariable1
    Just one option, and of course, as many have pointed out, the strategy really does depend on the developer's (or team's) consistency and discipline to only access publicly available properties (until PHP5 of course!)

    Cheers,

    jay
    Last edited by silent; Jun 30, 2004 at 02:36.

  3. #3
    SitePoint Zealot
    Join Date
    Mar 2004
    Location
    netherlands
    Posts
    104
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    So if i understand you correctly, you are using the loader and writer to store and load the objects values? So that would equal the mapper approach, where it is maybe different on the way you are setting the new objects internal values (directly or setters).
    Now if you think the other way around, wouldn't it be an option to let the object know how to construct itself (so the object sets its own values)?

    So that would make:
    PHP Code:
    $course = new Course(2004);
    $student = new Student('name');
    $course->addStudent($student); 
    That seems more logical then accessing a mapper/finder directly to get the right object, as in:
    PHP Code:
    $finder = new CourseFinder;
    $course $finder->findByYear(2004);
    $finder = new StudentFinder;
    $course->addStudent($finder->findByName('name')); 
    Or in your case:
    PHP Code:
    $reader = new ModelReader(); 
    $course $reader->GetModel(2004);
    //etc 
    .. i think.

  4. #4
    SitePoint Addict silent's Avatar
    Join Date
    Jun 2004
    Location
    Roaming North America
    Posts
    220
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Manor,

    Some very good points. However, I have tried the approach you show above, and the problem I ran in to was that the constructor doesn't return a value other than the object being created; therefore if something went wrong with the loading of the object, I can't do this (at least, I don't think I can!):

    PHP Code:
    $course = new Course(2004);
    if (!
    $course) {exit;}
    $student = new Student('name');
    $course->addStudent($student); 
    whereas with the second example, I can return a boolean false from the finder/getter method and act upon it:

    PHP Code:
    $finder = new CourseFinder;
    $course $finder->findByYear(2004);
    if (
    $course) {
      
    $finder = new StudentFinder;
      
    $course->addStudent($finder->findByName('name'));
    } else {exit;} 
    Just a different style I guess. I suppose much of it comes down to how much complexity you're willing to put up with over the lifetime (maintenance included) of the application...

    cheers, and well said!

    jay

  5. #5
    SitePoint Zealot
    Join Date
    Mar 2004
    Location
    netherlands
    Posts
    104
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Well, I dont think that is the worst problem. You can catch an exception for that in PHP5, or you can do something like:

    PHP Code:
    $course = new Course(2004);
    if(!
    $course->isValid())
    {
          
    //etc

    The problem Im worried about in this case is making multiple objects. So if you want to select the last10 courses from the last time (so that would mean 1994 till 2004), you would have to make a loop and let each Course object run a select query to fill in its own values. That would mean 10 select query's, where a mapper can do it in 1.

    So what Im thinking is, you can make the unique construct parameter optional, and if its given, let it fill its own values. But if the parameter is empty, leave everything as it is, and use setters or something to ensure that the mapper way would work as well.

  6. #6
    Non-Member
    Join Date
    Jan 2004
    Location
    Planet Earth
    Posts
    1,764
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The Mapper approach does have it's uses, though this

    PHP Code:
    ...
    $course = new Course(2004); 
    if(!
    $course->isValid()) 

          
    //etc 
    }
    ... 
    Does show the benifits of this method clearly

    Btw, good example Manor

  7. #7
    SitePoint Addict silent's Avatar
    Join Date
    Jun 2004
    Location
    Roaming North America
    Posts
    220
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Manor
    So what Im thinking is, you can make the unique construct parameter optional, and if its given, let it fill its own values. But if the parameter is empty, leave everything as it is, and use setters or something to ensure that the mapper way would work as well.
    Funny, that's exactly what I've done in the past (IsValid() code included... ). I will say, however, that I do not use my Reader/Writer methods for collections of objects. I have rarely encountered situations where I needed to write multiple similar objects to storage on a single call, and in those situations, I have written specialized classes ("ModelCollectionWriters" if you will) that handle those situations. When reading multiple similar objects, I use a Finder-type object that returns, generally, a collection of the needed Models (only the structs, not anything else).

    This all means that I'm not passing around objects that have methods (like IsValid()) I'm only passing the structs. My ModelWriter would have the function IsValid(), and would understand how to validate the passed Model. I guess my thinking has evolved into "well, the ModelWriter is the one doing the writing of the model, so shouldn't the Writer validate whether what is is writing is valid or not?" Of course, one might further abstract the process into the ModelWriter using another Validator class (strategy pattern?) to do the validating, but I've rarely found a need for this complexity in my projects...

    Make sense? Don't know if I've explained myself well...and I apologize if I'm not using correct GoF terminology all the time! You code long enough in your own world, and it's tough to break out of your own semantics!

    jay

  8. #8
    SitePoint Addict silent's Avatar
    Join Date
    Jun 2004
    Location
    Roaming North America
    Posts
    220
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    BTW, I don't want you to think I use these types of complex objects when simply displaying data or lists; I use highly streamlined classes that know nothing about the data they are displaying...

    I only use this type of pattern when manipulating an object or collections of objects.

    cheers,

    jay

  9. #9
    SitePoint Zealot
    Join Date
    Mar 2004
    Location
    netherlands
    Posts
    104
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yes i understand. What you said about the structs off the object; That is basicly what mappers/finders do. They fill an array with constructed objects to return to the asker. This is extremely usefull when selecting multiple objects, but I dont feel like accessing a mapper or some sort directly, it just doesn't feel right. This is probably a personal disliking, but I am trying to find other methods to construct (multiple) objects without accessing a datamapper directly.

  10. #10
    SitePoint Addict silent's Avatar
    Join Date
    Jun 2004
    Location
    Roaming North America
    Posts
    220
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I hear you. What's your opinion on where to put the IsValid() type functon? I'm interested to hear your viewpoints

    cheers,

    jay

    (It's always neat to hear everyone's approach to common patterns and problems!)

  11. #11
    SitePoint Zealot sleepeasy's Avatar
    Join Date
    Sep 2003
    Location
    Bristol, UK
    Posts
    145
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm of the opinion that model objects shouldn't know anything about how or where they're stored.

    Giving your model objects the ability to populate themselves by retrieveing it's values from the data source is mixing behaviour and increases the complexity of your model.

    Although there are advantages to doing this (less typing):
    PHP Code:
    $car = new Car(4000); 
    When the id you give in the constructor doesn't identify a valid Car then that's when the advantage of the above method starts to break down.

    I find the following easier to understand because I know that the finder is going to try and find me the Car object with id 4000.

    PHP Code:
    try {
        
    $car Car_Finder::instance()->getById(4000));
    } catch (
    Exception $e) {
        exit();

    I'm wondering how your method would deal with queries that are more complex. What if you want to retrieve all cars that are green, or that are yellow, have more than 10,000 miles on the clock and are made by Ford?
    Always open to question or ridicule

  12. #12
    SitePoint Addict silent's Avatar
    Join Date
    Jun 2004
    Location
    Roaming North America
    Posts
    220
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    sleepeasy: I agree with you, and I think we've covered the advantages and disadvantages of this pattern above.

    But in the case of writing the model to storage, what's your opinion of where the IsValid() function should reside? ModelWriter? Model itself? ModelValidator separate class?

    interested,

    jay

  13. #13
    SitePoint Zealot
    Join Date
    Mar 2004
    Location
    netherlands
    Posts
    104
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    sleepeasy, im aware of the problems this method has.
    As for the fact that you believe that the object shouldn't be aware how to access the data layer, is not such a big problem in my opinion.
    The constructor of the object access a mapper/finder to find its values, so it does not really know how the finder finds it, the same as the finder does not know what the object is all about when you request an object through the 'mapper' method.

    And about the complex queries; as the constructor uses a finder anyway, the whole idea doesn't really change. But I think it would be cleaner to talk to the domain objects only, so you would have a sole domain object environment, and not ask a finder for an object first. Or you would have such good nameconventions, that it would be 'unclear' that you are talking about finder, so it would flow into your model of domain objects.

  14. #14
    SitePoint Zealot
    Join Date
    Mar 2004
    Location
    netherlands
    Posts
    104
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    And jay, because I am trying to keep mappers out of direct reach, I think any isValid() method would then be placed in the objects itself, else it wouldn't have any use after all.


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
  •