Un detalle que creo no tuvo la amplificación suficiente con el lanzamiento de Magento 2.4, es un cambio que se introdujo de cara a los controllers.

No, no se va a romper nada, no aún.

El post no se trata sobre explicar los puntos a favor y en contra de la herencia y la composición. Simplemente voy a crear un ejemplo basado en el código que deberíamos empezar a adaptar y algunos ejemplos de referencia.

Supongamos que tengo mi módulo que sólo es un controller y su layout para inyectar el título (además de los archivos mínimos que se necesitan para que un módulo pueda existir).

El archivo de layout estará ubicado dentro de view/frontend/layout/sample_test_index.xml. Y contendrá:

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="page.main.title">
            <action method="setPageTitle">
                <argument translate="true" name="title" xsi:type="string">Controller con Composición y sin Herencia</argument>
            </action>
        </referenceBlock>
    </body>
</page>

Si escribiera el controller como lo hacíamos/hacemos hasta ahora, el código sería algo así.

<?php

declare(strict_types=1);

namespace Barbanet\Sample\Controller\Test;

use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Framework\App\Action\HttpGetActionInterface;
use Magento\Framework\App\ResponseInterface;
use Magento\Framework\Controller\ResultInterface;
use Magento\Framework\View\Result\Page;
use Magento\Framework\View\Result\PageFactory;

/**
 * Class Index
 */
class Index extends Action implements HttpGetActionInterface
{
    /**
     * @var PageFactory
     */
    private $pageFactory;

    /**
     * @param Context $context
     * @param PageFactory $pageFactory
     */
    public function __construct(
        Context $context,
        PageFactory $pageFactory
    ) {
        parent::__construct($context);
        $this->pageFactory = $pageFactory;
    }

    /**
     * @return ResponseInterface|ResultInterface|Page
     */
    public function execute()
    {
        return $this->pageFactory->create();
    }
}

Si hacen eso ahora verán que la clase Action está deprecada. La forma adecuada ha de ser:

<?php

declare(strict_types=1);

namespace Barbanet\Sample\Controller\Test;

use Magento\Framework\App\Action\HttpGetActionInterface;
use Magento\Framework\App\ResponseInterface;
use Magento\Framework\Controller\ResultInterface;
use Magento\Framework\View\Result\Page;
use Magento\Framework\View\Result\PageFactory;

/**
 * Class Index
 */
class Index implements HttpGetActionInterface
{
    /**
     * @var PageFactory
     */
    protected $resultPageFactory;

    public function __construct(
        PageFactory $resultPageFactory
    ) {
        $this->resultPageFactory = $resultPageFactory;
    }

    /**
     * @return ResponseInterface|ResultInterface|Page
     */
    public function execute()
    {
        return $this->resultPageFactory->create();
    }
}

Y si ahora accedo a www.dominio.com/sample/test, debería ver esta pantalla.

Vale aclarar que aún no está implementado en el core ya que se busca evitar la aparición de problemas de incompatibilidad con módulos de terceros debido a que los controllers no son parte de la API pública.

Según la hoja de ruta se comenzará el refactoring del core a partir de 2.5, lo cual no quita que desde hoy nuestros controllers puedan quitarse la pesada e innecesaria herencia.

Para leer más sobre este cambio y sobre las mejoras de performance, se puede repasar el post del Dev Blog en los Community Forums (de comienzos de este año).