samedi 12 septembre 2015

Is there a name for this design pattern (pass yourself into one of your own dependencies), and what are the pitfalls of such a technique?

I don't blindly follow design patterns (we really just need to understand object communication IMO), but I also don't want to be ignorant of them either.

Is there a name for a design pattern (similar to the Delegation Pattern used here or perhaps some double-dispatchy-strategy-patterny thing-a-ma-bopper) but instead of rewriting each method and delegating, you would just pass a reference ($this) back to yourself into the dependency? And is this a reasonable solution to have in a programmers tool box?

Need a practical example? Sure...Continue on...


Consider you are using a DI container and have perhaps some Controller (MVC) method like this:

Figure 1:

// Phew! Four dependencies injected here:
public function index(QueryManagerInterface $handler, BlogQueryInterface $blogQuery, RenderQueryPDFInterface $queryPDFRenderer, RequestInterface $request) {

    // Do some "managing" of a query, then render it into a PDF

    $queryManager->setQuery($query);
    $queryManager->addInput($request->input());
    $queryPDFRenderer->setQuery($query);
    $output = $queryPDFRenderer->render();

    return $output;
}

Now instead imagine your Controller method looks like this:

Figure 2:

// Nice! Just two dependencies!
public function index(BlogQueryInterface $blogQuery, RequestInterface $request) {

    $blogQuery->getQueryManager()->addInput($request->input());
    $output = $blogQuery->getPDFRenderer()->render();

    return view('index', $output);
}

How did I do this? All the code is the same in all these classes, except I updated the class of $blogQuery:

Class BlogQuery Implements BlogQueryInterface, QueryManageableInterface, PDFRenderableInterface {

   public function __construct(QueryManagerInterface $manager, $PDFRendererInterface $pdfRenderer){

      // Here I pass a reference of this own class into its dependencies
      $this->manager = $manager->setQuery($this);
      $this->pdfRenderer = $pdfRenderer->setQuery($this);
   }

   public function getQueryManager() { return $this->manager; }
   public function getPDFrenderer() { return $this->pdfRenderer; }

   ...

}

The pros of Figure 2 are:

  • Less dependencies on Controller method
  • Less lines of code
  • Composition over inheritance (more loosely coupled?).
  • No need to "type a lot" like when using the Delegation pattern.

What pattern did I use in Figure 2? What are the cons of such an approach? Is such an approach going to get me ridiculed by a senior dev?

Aucun commentaire:

Enregistrer un commentaire