Los captadores de magia en Varien_Object
(M1) y DataObject
(M2) son una práctica común, pero con Magento 2 se siente mal usarlo.
Bueno:
- fácil de leer / escribir
Malo
- Causa problemas al usar dígitos en las claves (vea: Magento 2: forma diferente de obtener el campo de una colección u obtener el atributo Obtener producto personalizado usando el caso de camello )
- las herramientas de análisis de código se quejan de métodos no existentes
Pregunta
Con Magento 2 tenemos dos nuevos métodos:
getDataByKey($key)
getDataByPath($path)
¿Hay alguna buena razón para seguir usando getData($key)
o algún objeto mágico?
Editar:
@Vinai gracias. No mencioné el @method
método, porque mi enfoque era bastante diferente.
Solo ayuda al IDE, pero no tiene impacto en otras cosas.
Existen varios PR combinados que son "microoptimizaciones" como la conversión en (int)
lugar de intval()
u obtener el tamaño de la matriz fuera de los bucles (incluso para matrices pequeñas).
Por otro lado hay
captadores mágicos, que tienen algo de "sobrecarga" como describió Marius ...
strtolower(trim(preg_replace('/([A-Z]|[0-9]+)/', "_$1", $name), '_'));
getData($key)
Mehtods también tienen que hacer 2-3 controles adicionales ...if ('' === $key) {
if (strpos($key, '/')) {
if ($index !== null) {
Para el propio código, estoy totalmente de acuerdo en preferir métodos reales, pero en los mismos casos no es posible ... por ejemplo, ha creado un evento personalizado ...
$value = $observer->getVar_1();
$value = $observer->getData('var_1');
$value = $observer->getDataByKey('var_1');
Usar 3rd con me /** @var some $value */
parece mejor. (?)
Respuestas:
La pregunta anterior es sobre el uso de métodos mágicos vs.
getDataByKey
ogetDataByPath
. Creo que también hay una tercera opción, y que está implementando métodos getter y setter reales.Los
getData*
métodos, todos ellos tienen la desventaja de que tienen que ser anotado para la inferencia de tipos de trabajo.Por lo general, eso se hace con una
/* @var string $foo */
anotación sobre lagetData*
llamada.Esto es un poco mal, porque el tipo de datos debe declararse en la clase que contiene los datos, no en la clase que llama
getData*
.La razón de esto es que si los datos cambian, es más probable que la clase se actualice, no todos los
getData*
sitios de llamadas.Es por eso que creo que los métodos reales aumentan la capacidad de mantenimiento en comparación con el uso de
getData*
accesores.Así que creo que se reduce a una compensación entre la mantenibilidad y la implementación más rápida (menos código para escribir).
Afortunadamente, hoy en día los IDE son realmente buenos para crear las implementaciones getter y setter para nosotros, por lo que ese argumento ya no se aplica.
Otro argumento contra los captadores y setters mágicos que falta en la pregunta anterior es que no es posible crear complementos para ellos.
El único otro valor que creo que puedo agregar al tema es tratar de recopilar las razones para usar o no usar
@method
anotaciones, si la implementación de métodos reales está fuera de discusión por alguna razón.Pros
@method
anotación es un poco menos de código para escribir en comparación con la implementación de un getter y setter real. Sin embargo, esto es apenas cierto hoy en día porque los IDE son buenos para generar métodos de acceso, por lo que ya no es un beneficio real.Contras
@method
existen una anotación y un método real con el mismo nombre, la firma del tipo de anulación anula el método real durante el análisis de código estático, que es lo contrario de lo que hace el intérprete PHP. Esto nuevamente puede conducir fácilmente a errores sutiles.Por las razones anteriores, personalmente no uso
@method
anotaciones si puedo evitarlas.Para el código que está destinado a vivir mucho tiempo, implemento métodos getter y setter reales. La ganancia de mantenimiento vale el esfuerzo de activar el IDE para generarlos.
Para obtener más código experimental durante un pico, o para un simple detalle de implementación de un módulo
getData*
, también uso métodos, porque soy flojo.fuente
Sí, huele mal, pero puede (¿y debería?) Evitarse. Creo que este es un código muy común y a menudo sugerido:
El problema es que simplemente adivina que el valor de retorno es de tipo
Foo
con ungetId()
método invocable .Para mantenimiento, ¿por qué no asumir el tipo de variable y agregar un
InvalidArgumentException
?Esto también corrige el análisis de código estático en caso de que
$model->getProduct()
tenga diferentes tipos de retorno, comoFoo|false
. En el primer caso, se quejaría de llamardoSomething()
posiblefalse
.fuente