SitePoint Sponsor

User Tag List

Results 1 to 6 of 6
  1. #1
    SitePoint Addict
    Join Date
    Mar 2003
    Location
    Germany
    Posts
    216
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Post Object composition: Pass as arg or include?

    I have a question about object composition. I think I understand that's good if you let objects collaborate, i.e. if one objects uses other objects to complete its task (when necessary). Lately I have been in this situation several times and I wondered what's the 'proper' way to handle this: should the 'used' objects be passed as parameters or should I just include those classes in the calling class'es file and the using class just instantiates them? I mean, in the second approach, does the 'using' class have the right to just 'know' of other objects it can use? SOmehow this seems not right to me.

    For example, I wanted to write an Archiver class that reads stuff from some db tables and archives it in another db table. I thought this class would use some Data Access Objects to read and write data and also a Logger object to log errors.

    Now, should I design it like this (simplified):

    PHP Code:
    class Archiver 
    {
      function 
    Archiver (&$SDAO, &$TDAO, &$Logger)
      {
        
    $this->SourceDAO $SDAO;
        
    $this->SourceDAO->getArchiveCandidates();
     
    ... 
    or should I do it like that (in the file for the Archiver class):

    PHP Code:
     
    require_once ('EventDAO.class.php');
    require_once (
    'ArchiveDAO.class.php');
    require_once (
    'Logger.class.php');
     
    class 
    Archiver 
    {
       function 
    Archiver ()
      {
        
    $this->SourceDAO =& new EventDAO();
        
    $this->TargetDAO =& new ArchiveDAO();
        
    $this->Logger =& new Logger();
     
        
    $this->SourceDAO->getArchiveCandidates()
     
    ... 
    AH, sorry, just while writing this it occured to me that I can answer the qestion myself concerning this example... Approach B would not be flexible enough, because I need to pass on different kinds of SourceDAOs.

    Uhm, maybe another example could illustrate my problem better, but I can't think of one right now. But anyway, is there a 'standard approach' for object composition or are both approaches perfectly possible, depending on the situation at hand?

  2. #2
    SitePoint Zealot
    Join Date
    Mar 2004
    Location
    Netherlands
    Posts
    138
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    But anyway, is there a 'standard approach' for object composition
    This is called 'dependency injection' or 'Inversion of Control'. Read more about it at http://www.martinfowler.com/articles/injection.html .

    The IoC type you are using is 'Constructor Injection'. I think this the best way to implement depedency injection. You can read about the pros and cons in the article.

    Picocontainer http://docs.codehaus.org/display/PICO
    Picocontainer is a framework that can manage dependencies in a structured manner. Picocontainer is based on constructor injection. Originally it was developed for Java, but a PHP5 port is on the way.

    Note that it isn't nescessary to use a framework for dependeny injection. You can just as well do it by hand. (I do)

  3. #3
    SitePoint Zealot
    Join Date
    Jan 2004
    Location
    vta,ca,usa
    Posts
    180
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Your first example uses a method generally known as 'aggregation' - an object is instantiated, then passed to another object that uses it internally, as well as allowing the aggregated object to be used elsewhere in the application. The second example is 'composition' - the object 'composes' the second object and uses it internally, but there isn't necessarily any external access to the composed object.

    In reference to your comment about composition not being flexible enough, wouldn't that suggest the use of the Factory Method, whereby the 'factory' designates which object is composed?

  4. #4
    SitePoint Addict
    Join Date
    Mar 2003
    Location
    Germany
    Posts
    216
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thank you both for your answers. I will certainly read the article.

    Quote Originally Posted by bdl
    Your first example uses a method generally known as 'aggregation' - an object is instantiated, then passed to another object that uses it internally, as well as allowing the aggregated object to be used elsewhere in the application. The second example is 'composition' - the object 'composes' the second object and uses it internally, but there isn't necessarily any external access to the composed object.
    Ah, this really clears things up a bit. I know the basic concepts of aggregation and composition, but I have never knowingly implemented them before. So I think it is more a question of wether I intend to use these objects elsewhere on their own as well, right?

    Quote Originally Posted by bdl
    In reference to your comment about composition not being flexible enough, wouldn't that suggest the use of the Factory Method, whereby the 'factory' designates which object is composed?
    Sounds interesting, too. In this case I would not include a particular DAO, for instance, but a DAOFactory, right? And then I would pass an argument stating which DAO must be instantiated?

  5. #5
    SitePoint Addict
    Join Date
    Mar 2003
    Location
    Germany
    Posts
    216
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Btw, in his Book "Design Patterns Explained", Alan Shalloway says this:

    When there are associations between two classes
    • - One class "contains" another class: the has-a relationship
    • - One class "uses" another class
    There are variations on these themes. For example, to say something contains something else can mean that

    • The contained item is a part of the containing item (like an engine in a car).
    • I have a collection of things that can exist on their own (like airplanes at an airport).
    The first example is called composition while the second is called aggregation.
    So far, so good. But in practice, I'm not quite sure right now. Let's consider those DAOs. I think the Archiver class uses them, so it's aggregation, right? In which case I should use my first method and pass those DAOs as arguments, right? Or does the Archiver class have some DAOs? I mean, the DAOs are somewhat self-contained and I use them everywhere, but normally always as part of something bigger, to get a subtask done (data access). So, I'm still somewhat confused... I think that both appraches would be possible (implementation-wise), I just want to understand the 'right' way to do it (theory-wise).

  6. #6
    SitePoint Zealot
    Join Date
    Mar 2004
    Location
    Netherlands
    Posts
    138
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    In your second approach, the archiver chooses the objects by itself (by creating a new instance of a certain class for each).

    In your first approach, the creator of the archiver object can choose which objects the archiver object will act on. This approach is by far the most flexible.
    This difference is called the 'inversion of control'.

    because I need to pass on different kinds of SourceDAOs.
    You may also want to pass different kinds of targetdao's.
    Or maybe, you decide at some time you want to use an other logging class. As long as the interface of the new logging class is compatible with the old one, you can just pass it to the archiver.
    This can't be done in the second example, because you've hardcoded the classname in the constructor.


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
  •