dimanche 17 avril 2016

How to pass parameters to constructor of dependency from within dependent class? Create provider?

For example, my DependentClass depends on some AbstractCsv class. Here is the declaration of AbstractCsv's factory (http://ift.tt/1FxCeSm):

public static AbstractCsv::createFromFileObject(SplFileObject $obj): AbstractCsv

And here is the declaration of DependentClass's constructor:

class DependentClass {
    public function __construct(AbstractCsv $csv) { /* implementation... */ }
    // implementation...
}

As you can see, to instantiate AbstractCsv, I need to pass in an instance of SplFileObject to dependency's factory function AbstractCsv::createFromFileObject. To create an SplFileObject, I need a filename. DependentClass stores the filename needed (or, for example, the filename is calculated dynamically within DependentClass at runtime).

How can I pass an instance of AbstractCsv into the DependentClass's constructor, if:

  • the filename is defined inside the DependentClass itself,
  • and also to create an instance of AbstractCsv, I first have to create an SplFileObject and then an AbstactCsv? It is a vicious circle!

I currently see the only solution to break this circle: DependentClass should not depend on AbstractCsv, but on its factory which will provide an instance of AbstractCsv to DependentClass on-demand. This also will eliminate the need to create SplFileObject within the DependentClass:

class DependentClass {
    public function __construct(CsvProvider $csvProvider) { /* implementation... */ }
    // implementation...
    public function someMethod($value) {
        $filename = rand($value); // somehow calculate $filename
        $csvFile = $this->csvProvider($filename);
        $csvFile->fwrite($someData);
    }
}

class CsvProvider {
    public function get(string $filename) : AbstractCsv {
        return AbstractCsv::createFromFileObject(new SplFileObject($filename));
    }
}

I think, this problem is common and occurs very often, right? I'm currently new to DI, so I wonder: is this solution really the right way to solve this problem? And what's the name of such factories? I called it provider. Is it a correct term for this?

Aucun commentaire:

Enregistrer un commentaire