rootcho has asked for the wisdom of the Perl Monks concerning the following question:

hi,
I have a rather abstract question. I was doing some experiments and now I'm stuck to decide which method to use : object or class "composition" (if I can use that word, OO gurus will tell).
For the sake of experiment let's say I want to build a Server which we want to be able to handle tcp/ip,streams etc.. (look at this just as simplified example, but don't forget the subject of the message :), this is my real question) . One of the things it will do is as you may expect is to send and recieve messages, so let's do it like this (in pseudo language):
class SendRecv { send{} recv{} } class Server { use base qw(SendRecv) .... }
As you see from this code I'm composing the Server with something like interface..now if i make many different SendRecv-classes I can compose different servers that will handle all types of data.Not only that i can also send/recv data differently i.e. I may also do compression, encryption ..etc..w/o modifyng the Server-class
Now the other approach that many will use probably look like this :
class SendRecv { send{} recv{} new{} } class Server { use SendRecv; new { my $sr = SendRecv->new(); bless $class, { pool => [$sr] } } .... }
i.e. object-composition..
The second way in this concentrate example seems better solution or at least easy to comprehend, but it also adds more runtime overhead. I have now to store pool of objects and add additional logic to support them. Also I have to add alot of additional logic inside these "object-classes" (f.e. new()-method).
One other drawback of this approach is that for any distinct functionality I will have to add another pool of objects (say I want to add IO operation that are not specific i.e. be able to store messages in file, redirect message to anoter server, steram them..etc.)

On the other hand the class-composition wont work 'cause I can have only one way of handling send/recv depending which interface-class I'm inheriting i.e. at runtime i will have to create pool of Servers !! Also this method gives you much leaner and clear way to compose the final Server class, 'cause all of the functionality can be developed separately and added in a LEGO-like way
I know that most of the things I mentioned here has to be decided on the per-project basis, depending on your final design.
But what if the final design is not entirily clear and you want to have both options available at any time..;)
Is there some middle-ground where you can have both methods, but still don't need to write alot of code
What is your opinion ? Sorry if I ask a trivial question that probably was solved somewhere.
Also of cource I'm interested for perl elaboration on the problem.

Replies are listed 'Best First'.
Re: Class or Object composition ??
by perrin (Chancellor) on Oct 03, 2006 at 20:53 UTC

    Inheritance is simpler and quicker but breaks pretty quickly when you want a "plugin" style application. Composition/delegation, where each piece can be implemented by a separate class if necessary and the implementation to use can be read from a config file or something, gives you a much more scalable plugin API. It requires some thinking up front though, and is overkill if you will not actually need to support plugins.

    Middle ground? Not really. You could start with inheritance and split things out when you need to support plugins, I suppose. It depends on the way the app will be developed in the future, e.g. if you want CPAN authors to be able to add functionality without bugging you, a composition approach is much better.

      Which modules on CPAN are good examples of the plugin style architecture?
      Template? DBIx::Class?
        There are not many examples of composition on CPAN because CPAN is mostly smaller pieces. DBIx::Class uses inheritance, modified by Class::C3. Template Toolkit has an excellent plugin API, but that's kind of separate from composition.

        However, if you look at the TT code, it does use composition internally. For example, a Template::Provider is a service for finding templates which the main Template object points to. You can implement the API and create a Template object that points to yours instead of the default one. It's a very good system for replacing bits and pieces.

        Another plugin system that worked out really well is Crypt::CBC, but again it's not so much composition as a specific plugin API.

Re: Class or Object composition ??
by stvn (Monsignor) on Oct 04, 2006 at 00:41 UTC

    The example you give is not appropriate for inheritence, since a Server is not a SendRecv, and instead it is more like a Server does SendRecv. This is the role model of class composition, sometimes called allomorphism (at least thats what chromatic always calls it).

    You might want to take a look at Moose, and in particular the (Perl 6 style) role features. Alternately there is Class::Trait or Perl6::Roles as well (there are some other "Role" modules on CPAN, but they are either incomplete or incorrect).

    As for composing the class vs. composing the object, I think this is probably something which should be dictated by the requirements. If you really need to have multiple instances all of which can do different types of servering, then use object composition. But the minute you might have several instances of one type of server, you might want to consider going with class compostion, and making custom subclasses for your needs.

    As for how you can do the object composition (if you choose that route), the Class::Trait module has a stable "runtime trait composition" feature which Ovid added several months ago. Perl6::Roles has that feature as well (and in fact was the primary reason dragonchild wrote that module). Moose only recently added this feature, and it is completely undocumented (aside from a test script in the t/ directory), so unless you really want Moose's other features, I would not recommend it yet.

    -stvn
      ++ good answer to a good question
      thanx,
      After I read some of the documetns i went to Class::Delegation, which seems to be what I named "runtime overhead" in my post. ;)
      So it seems that combination of Perl6::Role, Class::Delegation and inheritance can solve most of the problems and allow the design to be easily changed if a need arises on the fly.
      As a side question - Does the new Roles in perl6 cover the delegation-pattern ?
        As a side question - Does the new Roles in perl6 cover the delegation-pattern ?

        Yes, although not as extensively as Class::Delegation. You can see examples of it here. In addition Moose also supports Perl 6-ish style delgation like so:

        package Tail; use Moose; sub wag { ... } package Dog; use Moose; has tail => ( is => 'ro', isa => 'Tail', default => sub { Tail->new }, handles => { 'wag_tail' => 'wag' } ); ## later in your code ... my $fido = Dog->new; $fido->wag_tail; # is equivalent too $fido->tail->wag;
        Its seems to me that the main difference between Perl 6/Moose style delegation and Class::Delegation is the options for combining methods that Class::Delegation offers.

        -stvn
Re: Class or Object composition ??
by Mutant (Priest) on Oct 03, 2006 at 21:44 UTC
    I'm no OO guru, but I believe the decision you're making is termed "Composition vs Inheritance" (Inheritance being your first example, Composition your second).

    AFAIK, there is no right or wrong answer to this question. The rule of thumb is only use inheritance if it really is inheritance. That is, if the sub-class "is-a" special case of the base class.

    In your example, you have a server with some 'base' funtionality. I'm not clear from the example if this base functionality is actually standalone, i.e. it can be used without sub-classing, it's "abstract". But in either case, using inheritance seems to make sense. There are several examples of this in the Real World (e.g. Catalyst's multiple server modules (for Apache, CGI, etc) are all inherited from one base class).

    I would Google "Composition vs Inheritance" for more info (although a lot of stuff on Java of course).

    By the way, performance shouldn't really be a consideration here. That's "premature optimisation". Write the code in the way that makes the most sense design-wise (and maintenance-wise). Optimise later if necessary.
Re: Class or Object composition ??
by exussum0 (Vicar) on Oct 03, 2006 at 21:53 UTC
    From experience, any code that interacts with the outsdie world needs to be seperated out, as seperate objects. I'd suggest the decorator pattern.

    For instance, if you were implementing a calculator, your object would have methods such as add(...), subtract(...), divide(...). Each of these methods would call a decorator class you fed in at some point. What if you wanted to work w/ them as BigInteger, or IEEE Floating point, or some other method for floating point?

    The only difference from what I'm stating and your second example, is you wouldn't "use SendRcv;" w/i there. You'd do something like...

    $server = Server->new( SendRcv->new() )
    Or in two lines..
    $server = Server->new(); $server->set_comm_i_cant_think_of_better_name( SendRcv->new() )
    </code>