Nas Regras de uso da injeção de dependência , os devdocs do Magento 2 afirmam:
Objetos renováveis não devem conter uma referência de campo a um objeto injetável, nem devem solicitar uma em seu construtor. Esta é uma violação da Lei de Deméter .
Entendo que esse é um bom objetivo, mas como isso é realmente possível nos modelos Magento 2?
Se dermos uma olhada no módulo Customer, que foi apresentado como um exemplo brilhante para a nova arquitetura, a assinatura do construtor do modelo do cliente é semelhante a esta:
public function __construct(
\Magento\Framework\Model\Context $context,
\Magento\Framework\Registry $registry,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Eav\Model\Config $config,
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
\Magento\Customer\Model\ResourceModel\Customer $resource,
\Magento\Customer\Model\Config\Share $configShare,
\Magento\Customer\Model\AddressFactory $addressFactory,
\Magento\Customer\Model\ResourceModel\Address\CollectionFactory $addressesFactory,
\Magento\Framework\Mail\Template\TransportBuilder $transportBuilder,
GroupRepositoryInterface $groupRepository,
\Magento\Framework\Encryption\EncryptorInterface $encryptor,
\Magento\Framework\Stdlib\DateTime $dateTime,
CustomerInterfaceFactory $customerDataFactory,
DataObjectProcessor $dataObjectProcessor,
\Magento\Framework\Api\DataObjectHelper $dataObjectHelper,
\Magento\Customer\Api\CustomerMetadataInterface $metadataService,
\Magento\Framework\Indexer\IndexerRegistry $indexerRegistry,
\Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
array $data = []
)
E Magento\Framework\Model\Context
sozinho, que é usado por todos os modelos, leva cinco argumentos injetáveis .
Aparentemente modelos, embora newable , não são um bom exemplo a todos para esta regra.
Quero seguir as práticas recomendadas com minhas próprias classes (nem mesmo modelos), mas preciso acessar itens como repositórios de entidades relacionadas ou o gerenciador de eventos. Qual seria a maneira preferida de lidar com isso sem quebrar a regra de cima?
Atualmente, costumo ignorá-lo ou, na melhor das hipóteses, vê-lo como orientação amigável, não como regra.
fonte
Estamos tentando afastar as pessoas do acesso direto ao código dentro de um módulo e, em vez disso, passando por uma API mais controlada e bem definida. O objetivo é permitir atualizações mais suaves entre os lançamentos - quanto mais pessoas usarem uma API definida, maiores serão as atualizações.
Um conceito importante nos arquivos di.xml é o elemento "preferência". Ele permite que o código faça referência a definições de interface (e, portanto, não esteja vinculado a uma implementação específica), mas quando você solicita uma instância, ele sabe qual classe usar.
Portanto, se você deseja uma instância CustomerInterface (que é uma classe que implementa a interface), solicita uma instância da interface (não procura a classe de implementação). Vamos procurar um elemento para você e usá-lo para identificar a classe de implementação. Dessa forma, outro módulo poderia substituir a preferência do arquivo di.xml e trocar por uma classe de implementação diferente (se houver algum bom motivo para fazê-lo).
Além disso, quando você cria objetos através do gerenciador de objetos dessa maneira, não precisa especificar os argumentos para a lista de construtores. O gerenciador de objetos novamente usa o arquivo di.xml para localizar todas as estruturas de dados necessárias e as fornece automaticamente ao construtor.
A diferença entre "classes de serviço" e "modelos de dados" em uma resposta separada é "classes de serviço" (que eu suponho que significa que as interfaces no diretório Api) fornecem métodos a serem chamados. Os "modelos de dados" (que eu suponho que significam as interfaces no diretório Api / Data) são estruturas de dados passadas para / de "classes de serviço". O objetivo é que alguém fora do módulo não precise saber qual classe está implementando as interfaces. Pode ser um modelo, um objeto de valor, não importa desde que você programe para as interfaces e nunca mencione nomes de classes diretamente (exceto no arquivo di.xml).
fonte