Molesto por toneladas de clases para DI en constructores de Magento 2, ¿hay una mejor manera?

8

En este momento estoy molesto de escribir constructores similares en masa como los siguientes en mis 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 */
}

En muchos, muchos casos, necesito instancias de las mismas clases en todo mi módulo.

Entonces me preguntaba si sería una forma aceptable de usar una o dos clases auxiliares centrales, que proporcionan las clases necesarias, en lugar de definirlas en cada constructor.

Esto significa un patrón como este:

Clase 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;
    }
}

El constructor más corto

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 */
}

En este momento no estoy seguro de si tendré que lidiar con grandes desventajas en el futuro causadas por esta estructura. ¿Sería esta una forma aceptable de reducir la cantidad de definiciones de DI?

bukart
fuente

Respuestas:

7

Echa un vistazo \Magento\Framework\Model\Context, referenciado en tu ejemplo. Lo que describe es exactamente lo que hace. Magento utiliza Contextobjetos similares en todo el núcleo para acortar las listas DI.

Lo único a tener en cuenta es que esto no debe usarse para ocultar malas decisiones arquitectónicas . Debería considerar si cada una de las clases que necesita 'en todo su módulo' es realmente necesaria, y si es así, si existe una forma alternativa de organizar su código que logre mejor el mismo objetivo. Es fácil introducir problemas de rendimiento no intencionales.

Ryan Hoerr
fuente
bueno, sí ... no debería ser usado para "esconder malas decisiones arquitectónicas". Mi mayor punto es la cantidad de ayudantes que tengo que usar (mis propios y principales ayudantes). Las clases de Contexto me parecieron hacer exactamente lo que dijiste, Simplemente no estaba seguro. THX 4 consejos
bukart
Entonces, en términos simples, ¿las Contextclases son clases de Magento que abarcan secciones enteras de Magento? es decir, Contexto de categoría, ¿ayudará a administrar Agregar / Editar / Eliminar / Ver categorías sin la necesidad de importar varias clases para realizar la misma acción?
MackieeE
@MackieeE No, no del todo. Abarcan algunas de las dependencias de Magento para la clase dada que estás viendo. Por lo general, son bastante abstractos / muy por encima de la cadena de herencia, no específicos de una clase final particular (como Categoría). Si miras \Magento\Catalog\Model\Category, verás que incluye lo mismo \Magento\Framework\Model\Contextque mencioné: en realidad no hay nada sobre categorías en absoluto. Estás buscando un repositorio, échale un vistazo \Magento\Catalog\Api\CategoryRepositoryInterface.
Ryan Hoerr
4

Estoy bastante seguro de que no eres el único en este caso y de alguna manera entiendo totalmente por qué pensaste en hacer esto.

Para mí, el problema principal que veo con este enfoque es que pierdes uno de los principales beneficios de la Inyección de dependencias, que es saber de inmediato de qué depende tu clase al verificar el constructor.

Otro beneficio importante de la Inyección de dependencias es que hace que el código sea más fácil de probar en un marco automatizado. En su caso, ese es definitivamente un inconveniente.

Esas son las dos razones que surgen, pero puede haber más.

EDITAR: solo voy a agregar una cita de Alan Kent (que es parte de Magento) que puedes encontrar en los comentarios de esta pregunta :

Generalmente desaconsejo lanzar métodos a una clase auxiliar que no están relacionados. Es mejor tener clases separadas que representen propósitos reales. O utilice métodos estáticos en cuyo caso no hay necesidad de un constructor (el código de llamada es responsable de obtener identificadores para las estructuras de datos necesarias).

Raphael en Digital Pianism
fuente
Considerando que estoy totalmente de acuerdo con las razones anteriores. Sin embargo, como novato en Magento, parece que hay una gran curva de aprendizaje para aprender qué clases se requieren y dependen unas de otras antes de que pueda comenzar a desarrollarse.
MackieeE