Os getters mágicos em Varien_Object
(M1) e DataObject
(M2) são práticas comuns, mas com o Magento 2 parece errado usá-lo.
Boa:
- fácil de ler / escrever
Ruim
- Causa problemas ao usar dígitos nas chaves (consulte: Magento 2: maneira diferente de obter o campo de uma coleção ou o atributo Obter produto personalizado usando a caixa camel )
- ferramentas de análise de código reclamam de métodos inexistentes
Questão
Com o Magento 2, temos dois novos métodos:
getDataByKey($key)
getDataByPath($path)
Existe alguma boa razão para continuar usando getData($key)
ou algum método mágico?
Editar:
@Vinai thanks. Não mencionei o @method
método, porque minha abordagem era bem diferente.
Isso apenas ajuda o IDE, mas não tem impacto em outras coisas.
Existem vários PRs mesclados que são "micro-otimizações", como converter para em (int)
vez de intval()
ou obter o tamanho da matriz fora de loops (mesmo para pequenas matrizes).
Por outro lado, existem
getters mágicos, que têm algumas "despesas gerais", como Marius descreveu ....
strtolower(trim(preg_replace('/([A-Z]|[0-9]+)/', "_$1", $name), '_'));
getData($key)
os mehtods também precisam de 2-3 verificações adicionais ...if ('' === $key) {
if (strpos($key, '/')) {
if ($index !== null) {
Para o próprio código, concordo totalmente em preferir métodos reais, mas nos mesmos casos não é possível ... por exemplo, você criou um evento personalizado ...
$value = $observer->getVar_1();
$value = $observer->getData('var_1');
$value = $observer->getDataByKey('var_1');
Usar o terceiro com /** @var some $value */
parece melhor para mim. (?)
Respostas:
A questão acima é de cerca usando métodos mágicas vs.
getDataByKey
ougetDataByPath
. Eu acho que também existe uma terceira opção, que é implementar métodos getter e setter reais.Todos os
getData*
métodos têm a desvantagem de que precisam ser anotados para que a inferência de tipo funcione.Geralmente isso é feito com uma
/* @var string $foo */
anotação acima dagetData*
chamada.Isso é um pouco fedorento, porque o tipo de dados deve ser declarado na classe que contém os dados, não na classe que chama
getData*
.A razão para isso é que, se os dados forem alterados, é mais provável que a classe seja atualizada, nem todos
getData*
os sites de chamada.É por isso que acho que métodos reais aumentam a capacidade de manutenção em comparação ao uso de
getData*
acessadores.Então eu acho que tudo se resume a uma troca entre manutenção e implementação mais rápida (menos código para escrever).
Felizmente, hoje em dia os IDEs são realmente bons em criar as implementações getter e setter para nós, de modo que esse argumento não se aplica mais.
Mais um argumento contra getters e setters mágicos que está faltando na pergunta acima é que não é possível criar plugins para eles.
O único outro valor que acho que posso acrescentar ao tópico é tentar coletar os motivos para usar ou não as
@method
anotações, se a implementação de métodos reais estiver fora de questão por algum motivo.Prós
@method
anotação é um pouco menos de código para escrever em comparação com a implementação de um getter e setter reais. Isso ainda é verdade atualmente, porque os IDEs são bons em gerar métodos de acessadores, portanto, isso não é mais um benefício real.Contras
@method
existir uma anotação e um método real com o mesmo nome, a assinatura do tipo de anotação substituirá o método real durante a análise estática do código, que é o oposto do que o intérprete PHP faz. Isso novamente pode facilmente levar a erros sutis.Pelas razões acima, eu pessoalmente não uso
@method
anotações se puder evitá-las.Para código que se destina a durar muito tempo, implementei métodos getter e setter reais. O ganho de capacidade de manutenção vale o esforço de acionar o IDE para gerá-los.
Para um código mais experimental durante um pico, ou para um simples detalhe de implementação de um módulo
getData*
, também uso métodos, porque sou preguiçoso.fonte
Sim, é mal cheiroso, mas pode (e deve?) Ser evitado. Eu acho que esse é um código muito comum e frequentemente sugerido:
O problema é que você simplesmente adivinha que o valor de retorno é do tipo
Foo
com um método que pode sergetId()
chamado.Para manutenção, por que não assumir o tipo de variável e adicionar um
InvalidArgumentException
?Isso também corrige a análise de código estático no caso de
$model->getProduct()
diferentes tipos de retorno - comoFoo|false
. No primeiro caso, ele reclamaria sobredoSomething()
a possibilidade de recorrerfalse
.fonte