O padrão de injeção de construtor do Magento permite que você gerencie com flexibilidade suas dependências de classe. No entanto, a injeção de construtor também significa que uma reação em cadeia da instanciação de objetos é geralmente o resultado quando você cria um objeto. (O objeto original tem dependências que têm dependências e esses objetos têm dependências e assim por diante.)
Se o construtor de uma classe é particularmente intensivo em recursos, isso pode levar a um impacto de desempenho desnecessário quando outra classe depende dele, se o objeto caro não for necessário durante uma solicitação específica.
Como exemplo, considere as duas classes a seguir:
class SlowLoading { public function __construct() { // ... Do something resource intensive } public function getValue() { return 'SlowLoading value'; } } class FastLoading { protected $slowLoading; public function __construct( SlowLoading $slowLoading ){ $this->slowLoading = slowLoading; } public function getFastValue() { return 'FastLoading value'; } public function getSlowValue() { return $this->slowLoading->getValue(); } }
Suponha que a classe SlowLoading
tenha um impacto de desempenho não trivial quando instanciada (talvez devido a uma consulta de banco de dados complexa ou uma chamada para uma API da Web de terceiros). Por causa da injeção de dependência no construtor FastLoading
, esse impacto é incorrido se FastLoading
for instanciado. Observe, no entanto, que a instância SlowLoading
é usada apenas no método getSlowValue
, o que significa que o custo do recurso é desnecessário se esse método nunca for chamado no objeto FastLoading
.
O Magento tem uma solução para esta situação: proxies. Proxies estendem outras classes para se tornarem versões carregadas preguiçosas delas. Ou seja, uma instância real da classe que um proxy estende é criada somente depois que um dos métodos da classe é realmente chamado. Um proxy implementa a mesma interface que a classe original e, portanto, pode ser usado como uma dependência em qualquer lugar da classe original. Ao contrário de seu pai, um proxy tem apenas uma dependência: o Object Manager.
Proxies são gerados e, portanto, não precisam ser escritos manualmente. Simplesmente faça referência a uma classe no formulário \Original\Class\Name\Proxy
e a classe será gerada se ela não existir.
Usando o exemplo anterior, um proxy pode ser passado para os argumentos do construtor em vez da classe original, usando a configuração de DI como segue:
<type name="FastLoading"> <arguments> <argument name="slowLoading" xsi:type="object">SlowLoading\Proxy</argument> </arguments> </type>
Com o proxy usado no lugar SlowLoading
, a classe SlowLoading
não será instanciada – e, portanto, as operações de construtor intensivo de recursos não executadas – até que o objeto SlowLoading
seja usado (ou seja, se o método getSlowValue
for chamado).
Como a configuração DI é usada para injetar um proxy, os proxies podem ser descartados para substituir suas classes correspondentes – ou substituições de proxy removidas – sem tocar no código do aplicativo.
Como um exemplo prático de um proxy, você pode ver a classe StoreManager
e, em seguida, ver a classe StoreManager
de proxy gerada.
Code generation
O Magento gera código para criar classes inexistentes. Como exemplo, veja o construtor Magento/Customer/Model/Resource/AddressRepository.
... public function __construct( \Magento\Customer\Model\AddressFactory $addressFactory, ...
O primeiro parâmetro de construtor tem um tipo de Magento\Customer\Model\AddressFactory
. No entanto, essa classe não existe na \Magento\Customer\Model
base de código do Magento 2. O Magento gera essa classe porque seu nome usa uma convenção reconhecida (nesse caso, porque o nome termina com Factory).
Ao contrário de outras linguagens ou bibliotecas, você pode olhar o código gerado no sistema de arquivos para ver o que realmente acontece e ainda depurar o código.
Quando o código é gerado?
Desde que o Magento não esteja configurado para o modo de produção, o código é gerado quando o aplicativo Magento não consegue encontrar uma classe ao executar o código.
- Uma classe Factory cria instâncias de um tipo. As factories são diretamente referenciadas no código do aplicativo.
- Você pode designar um Proxy para ser gerado para um tipo para garantir que o tipo não seja instanciado até que seja necessário. Os proxies são diretamente referenciados na configuração de DI.
- As classes do interceptor são geradas automaticamente para facilitar o sistema de plugins do Magento. Uma classe de interceptor estende um tipo e é retornada pelo Object Manager para permitir que várias classes de plugin insiram lógica em métodos diferentes. Os interceptores trabalham nos bastidores e não são diretamente referenciados no código do aplicativo.
Você também pode usar o compilador de código para gerar código a qualquer momento. No Magento 2, compilar seu aplicativo significa executar a geração de código para qualquer classe elegível encontrada pelo scanner de configuração/código, bem como realizar várias otimizações de injeção de dependência diferentes .
Por que você deveria regenerar o código?
Suponha que uma classe Factory ou Proxy para uma classe Customer seja gerada e a classe Customer tenha novos métodos adicionados a ela. Como um Factory ou Proxy existe no sistema de arquivos, ele não é regenerado. No entanto, a implementação Factory ou Proxy agora está incompleta porque não possui os novos métodos. Nesse caso, você deve gerar novamente a classe Factory ou Proxy.
Se a implementação do gerador de código for alterada, você deverá gerar novamente todas as classes. Isso é raro, no entanto.
Vantagens de gerar código
A geração de código é necessária no Magento 2. Gerar código garante o seguinte:
- O código está correto. Você não precisa se preocupar que o código gerado esteja delegando ao método errado ou esquecendo-se de um ponto-e-vírgula, e você não precise escrever testes para o código gerado.
- A geração de código grava o código padrão para permitir que você escreva um código mais desafiador e interessante.
- Implementação consistente. Todas as factories geradas funcionam da mesma maneira. Depois que você souber como funciona uma Factory, sabe como todas elas funcionam.
Responsabilidade do Object Manager pela compilação de código
Quando o código é alterado conforme discutido acima, o Object Manager o compila.
O compilador de código cria generated/metadata/global.php
, que é um mapa serializado em PHP de todas as definições de construtor misturadas com a configuração de vinculação de objetos definida em di.xml. O di.xml
é a configuração de injeção de dependência. Existe um global app/etc/di.xml
e pode ser definido para cada módulo .
Para mais informções veja, Code Generation e Proxies
Dúvidas? Posta aí!!!
Um abraço.