Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • Though that wasn't the main point of the post, which was that if you just go about converting base classes to roles where you have recurrence of god objects, you will get god objects implemented with roles ;-)

    As you showed, in real life lots of stuff that happens to be working probably shouldn't be. Many a time i find myself reading through old code and saying to myself something along the lines of "OH F*ET!$%*Y HOW THE H*U$!(&Y DID THIS PIECE OF &$!(&!Y% EVER WORK TO BEGIN WITH?!!". Something l

    • by Ovid (2709) on 2009.12.04 11:52 (#71313) Homepage Journal

      I certainly hope, though, that it didn't sound like I was being too critical of your reasoning. You had a great post.

      I'm concerned about the God Object comments, though. I think it's easy to create God Objects with roles and to fundamentally misunderstand OO, but God Objects are less of a concern (I think) with roles. For example, with Test::Builder generating TAP and providing the ability to share the TAP generator, you suggest that these are behaviors which can be separated by delegating to a TAP generator. That's really interesting because, from the point of view of the consumer, you present the same interface. So does T::B do too much? For the programmers in the "let's have a class for every possible thing we can ever think of doing" camp, then yes, it does too much. However, it's really easy to use and the convenience of conflating these behaviors seems to outweigh the drawbacks of "doing too much".

      A more concrete example would be the ill-fated Pixie project:

      use Pixie;
      use Customer;

      my $customer = Customer->new({
        name     => 'Bob',
        salesman => $some_salesman,
      });

      my $pixie = Pixie->new->connect(
        'dbi:mysql:dbname=test',
        user => $user,
        pass => $pass
      );

      # Save an object
      my $cookie = $pixie->insert($some_object);

      Why am I creating two objects and writing this boilerplate code just to persist something? Sure, we get separation of concerns, but what I want to do is this:

      use Customer;

      my $customer = Customer->new({
        name     => 'Bob',
        salesman => $some_salesman,
      });

      $customer->save;

      Sure, I'm putting a cross-cutting concern on the Customer object, but the convenience is worth it. But how many cross-cutting concerns should I bake into an object (via delegation or otherwise?) before the convenience is overwhelmed by the complexity? Roles, at least, can mitigate this, while still making objects easier to use and maintain. When you drive a car, it's not a car object with four wheel objects and an engine object and a steering wheel object. It's just a car.

      What I would like to see, and what I don't think anyone has ever done, is define God Objects in anything even remotely close to a quantifiable manner. What does "does too much" mean? That's where much of the "God Object" debate fails for me :)

      • And to illustrate the point, consider the opposite of the god object: ravioli code [c2.com]. It can be equally unmaintainable.

        • Attempting a definition of a "God Object"

          Any object that implements a model for more than one concept simultaneously.

          To take your "car" analogy for a second, you don't drive just a car. The interface presented to you delegates the actions you make to other components you don't have to think about yes, but at no point are the Engine Block, Steering Assembly, Chassis or Wheels wholly consumed by the "car". There are even those of us who prefer cars that make you *more* aware of this (manual transmission for e

      • Because you can always implement $customer->save in terms of a well factored interface, but going the other way is much harder.

        The interface that T::B would present is just one facet (albeit a very important one). It used to be that the tradeoff was too much java style boilerplate or a god object, but Moose's handles feature lets you have a nice interface on the outside and flexibility without needing combinatorial explosion on the inside.

        The point is that for 99% of the usage you can still use T::B beca