Irritado com toneladas de classes para DI em construtores de Magento 2 - existe uma maneira melhor?

8

No momento, estou incomodado de escrever construtores similares em massa, como os seguintes, em meus módulos.

public function __construct(
    \Magento\Framework\Model\Context $context,
    \Magento\Framework\Registry $registry,

    /* ... */

    \Foo\Bar\Model\Baz $baz,

    /* ... */

    \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
    \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
    array $data = []
) {
    $this->registry = $registry;

    /* ... */

    $this->baz = $baz;

    /* ... */

    /* some awesome stuff */
}

Em muitos casos, eu preciso de instâncias das mesmas classes em todo o meu módulo.

Então, eu estava me perguntando se seria uma maneira aceitável de usar uma ou duas classes auxiliares centrais, que fornecem as classes necessárias, em vez de defini-las em cada construtor.

Isso significa um padrão como este:

Classe auxiliar

namespace Foo\Bar\Helper

class Main
{
    protected $baz;



    public function __construct(
        \Magento\Framework\Model\Context $context,
        \Magento\Framework\Registry $registry,

        /* ... */

        \Foo\Bar\Model\Baz $baz,

        /* ... */
    ) {
        $this->registry = $registry;

        /* ... */

        $this->baz = $baz;

        /* ... */

        /* some awesome stuff */
    }



    public function getBazInstance()
    {
        return $this->baz;
    }
}

O construtor mais curto

public function __construct(

    \Foo\Bar\Helper\Main $mainHelper,

    \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
    \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
    array $data = []
) {
    $this->mainHelper = $mainHelper;

    /* some awesome stuff */
}

Neste ponto, não tenho certeza se terei de lidar com grandes desvantagens no futuro causadas por essa estrutura. Seria uma maneira aceitável de reduzir a quantidade de definições de DI?

Bukart
fonte

Respostas:

7

Confira \Magento\Framework\Model\Context, referenciado em seu exemplo. O que você descreve é ​​exatamente o que faz. Magento usa Contextobjetos semelhantes em todo o núcleo para encurtar listas de DI.

A única coisa a ter em mente é que isso não deve ser usado para ocultar más decisões arquitetônicas . Você deve considerar se cada uma das classes de que você precisa 'em todo o seu módulo' é realmente necessária e, em caso afirmativo, se existe uma maneira alternativa de organizar seu código que atinja melhor o mesmo objetivo. É fácil introduzir problemas de desempenho não intencionais.

Ryan Hoerr
fonte
bem, sim ... não deve ser usado para "esconder más decisões arquitetônicas". Meu ponto principal é a quantidade de auxiliares que tenho que usar (meus próprios e auxiliares principais) que as classes Context me pareciam fazer exatamente o que você disse, Eu só não tinha certeza. thx 4 conselho
bukart 01/09/16
Então, em termos leigos, ContextClasses são classes Magento que abrangem seções inteiras do Magento? ou seja, Contexto da categoria, ajudará a gerenciar Adicionar / Editar / Remover / Visualizar categorias sem a necessidade de importar várias classes para executar a mesma ação?
MackieeE
@MackieeE Não, não exatamente. Eles abrangem algumas dependências do Magento para a classe que você está olhando. Eles geralmente são bastante abstratos / distantes da cadeia de herança, não específicos para uma classe final específica (como Categoria). Se você olhar \Magento\Catalog\Model\Category, verá que está incluindo o mesmo que \Magento\Framework\Model\Contexteu mencionei - não há realmente nada sobre categorias. Você está procurando um repositório - dê uma olhada \Magento\Catalog\Api\CategoryRepositoryInterface.
Ryan Hoerr
4

Tenho certeza de que você não é o único nesse caso e, de alguma forma, entendo perfeitamente por que você pensou em fazer isso.

Para mim, o principal problema que vejo com essa abordagem é que você perde um dos principais benefícios da Injeção de Dependência, que é saber imediatamente do que sua classe depende ao verificar o construtor.

Outro benefício importante da Injeção de Dependência é que facilita o teste de código em uma estrutura automatizada. No seu caso, essa é definitivamente uma desvantagem.

Essas são as duas razões que surgem, mas pode haver mais.

EDIT: Vou apenas adicionar uma citação de Alan Kent (que faz parte do Magento) que você pode encontrar nos comentários desta pergunta :

Eu geralmente desencorajo a jogar métodos em uma classe auxiliar que não estão relacionados. É melhor ter classes separadas que representam propósitos reais. Ou use métodos estáticos; nesse caso, não há necessidade de um construtor (o código de chamada é responsável por obter identificadores para as estruturas de dados necessárias).

Raphael na Digital Pianism
fonte
Considerando que eu concordo plenamente com as razões acima. No entanto, como um novato no Magento, parece que há uma grande curva de aprendizado para aprender quais classes são necessárias e dependentes umas das outras antes que você possa começar a desenvolver.
MackieeE