4

Say I have a large object - think EntityManager of an ORM such as Doctrine, or a custom DAO object, or what have you. Object, output of which is required to be used inside a class, but the object itself could be transient - do its job and then go out of scope.

It does not always matter if such object is large or not, but that it is not necessary to be a part of the class. However its byproduct is. Example:

//i.e. Doctrine\ORM\EntityManager
class BigTerribleDatabaseObject
{
    //300 methods and 20 properties
}

When Not using DI

BigTerribleDatabaseObject is only used to get some data and then it is discarded.

class Small
{
    public getData($id)
    {
        $db = new BigTerribleDatabaseObject();
        return $db->getDataById($id);
    }
}

Using DI

BigTerribleDatabaseObject becomes a permanent resident of the small class, despite being injected (it's injected and then it stays).

class Small
{
    private $db;
    function __construct(BigTerribleDatabaseObject $db)
    {
        $this->db = $db;
    }

    public getData($id)
    {
        $db = $this->db;
        return $db->getDataById($id);
    }
}

My Issue

I sometimes do a print_r statement for debugging purposes on an object. Like so:

//first line depending on whether or not I use DI or not:
$myClass = new Small(new BigTerribleDatabaseObject())
$myClass = new Small()

print_r($myClass);

With DI $myClass prints contents of Small AND also all the content of the BigTerribleDatabaseObject, because BigTerribleDatabaseObject is part of Small.

This floods my screen and sometimes even crashes my browser because in my case it is Doctrine's entity manager and it is huge and unwieldy.

Without DI I get a nice printout of just my very small class. Which I think is cleaner.

So I have to pick between "nice and small debug printout with no DI" or "use DI but suffer Large and unwieldy debug printout".

Question

I much prefer smaller printout. Does that mean I have to discard using Dependency Injection techniques? Can I use something else? Is that a necessary Evil of DI-ing large transient objects?

1

1 Answer 1

6

Note that in your current example, there is not much benefit from passing the object by the caller, since Small does not become decoupled from the database. So you should not stop using DI - quite the opposite, you should start to use it correctly.

Instead of injecting the object of class BigTerribleDatabaseObject, you could inject a factory method for those kind of objects into Small to avoid the need for calling the constructor directly. Or better, the factory could directly encapsulate the database read operation to give your SmallFootprintInnocentClass a chance to be tested with a "mock" factory, with no access to the real database. Something along the lines of

class Small
{
    private $myDataFactory;
    function __construct(function $myFactory)
    {
        $this->$myDataFactory = $myFactory;
    }

    public getData($id)
    {
        return $myDataFactory($id);
    }
}

(forgive me if I got the syntax wrong, I am not a fluent PHP programmer).

Since the factory will probably have no or minimal internal state, the print_r will result in a minimal printout.

6
  • thanks. What you are suggesting then is just to keep using DI but use a Factory instead exposing the factory but hiding the big object behind it. Also I have changed my class name to just Small realizing that it was too much to read. Plus, less letters -> easier to spot which one was smaller
    – Dennis
    Commented Mar 1, 2016 at 21:30
  • @Dennis You don't have to use factory per se. You can instead to choose the path of fixing the design of your BigTerribleDatabaseObject, split it into several smaller, more specific, classes. Still, Doc Brown is right that there's something fundamentally wrong with your current design which is more than ready for refactoring.
    – Andy
    Commented Mar 1, 2016 at 21:42
  • @DavidPacker: I guess the whole point of the question is that BigTerribleDatabaseObject might not be easily split into smaller objects (though, if possible, that would probably be a good idea). However, just splitting the big object into smaller ones alone won't decouple the class from the database.
    – Doc Brown
    Commented Mar 1, 2016 at 21:58
  • BigTerribleDatabaseObject in my case is Doctrine's EntityManager library class. Can't change it, it's not mine, but when printing it out is causes much havoc, sometimes flooding the screen with useless to me information, or even breaking the browser for whatever reason (either it is just too big or there is recursion somewhere or a memory leak when trying to print it out)
    – Dennis
    Commented Mar 1, 2016 at 22:52
  • @Doc, what do you think of inverting control entirely and have a Factory Method for Small instead, where SmallFactory instantiates the Small object, populates with data gotten via BigTerribleDatabaseObject, and then returns a clean lean populated Small object to the caller?
    – Dennis
    Commented Mar 1, 2016 at 23:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.