Magento 2 - хороша практика використовувати / уникати магічних дільниць?


21

Чарівні геть на Varien_Object(M1) та DataObject(M2) - звичайна практика, але в Magento 2 використовувати його неправильно.

Добре:

  • легко читати / писати

Поганий

Питання

У Magento 2 у нас є два нові методи:

  • getDataByKey($key)
  • getDataByPath($path)

Чи є якісь вагомі причини все-таки використовувати getData($key)чи будь-які магічні геть?


Редагувати:

@Vinai спасибі Я не згадував @methodметод, тому що мій підхід був зовсім іншим.

Він лише допомагає IDE, але не впливає на інші речі.

На цьому є кілька PR-об'єднанихf, які є "мікрооптимізаціями", такими як кастинг (int)замість intval()або отримання розміру масиву зовнішніх циклів (навіть для невеликих масивів).

З іншого боку є

  1. магічні геттери, які мають деякі "накладні витрати", як описав Маріус ....

    strtolower(trim(preg_replace('/([A-Z]|[0-9]+)/', "_$1", $name), '_'));
  2. getData($key) Мехтоди також мають 2-3 додаткові перевірки ...

    • if ('' === $key) {
    • if (strpos($key, '/')) {
    • if ($index !== null) {

Для власного коду цілком погоджуються віддавати перевагу реальним методам, але в тих же випадках це неможливо ... наприклад, ви створили власну подію ...

$value = $observer->getVar_1();
$value = $observer->getData('var_1');
$value = $observer->getDataByKey('var_1');

Використання 3rd з /** @var some $value */мені здається найкращим. (?)


1
Ви можете додати методи до блоку doc класу, щоб інструменти аналізу коду не скаржилися на неіснуючі методи. Крім того, я думаю, що використання цифр у клавішах є самою поганою практикою, тому її не слід вказувати як "Погано" тут imo.
Лілі Бергонзат

Відповіді:


20

Наведене вище питання стосується використання магічних методів проти getDataByKeyабо getDataByPath. Я думаю, є й третій варіант, і це реалізація реальних методів геттера та сеттера.

Усі getData*методи мають той мінус, що їх потрібно помітити для висновку типу роботи.
Зазвичай це робиться з /* @var string $foo */приміткою над getData*викликом.
Це трохи смердюче, тому що тип даних повинен бути оголошений у класі, який містить дані, а не в класі, який викликає getData*.
Причиною тому є те, що якщо дані змінюються, клас, найімовірніше, буде оновлюватися не на всіх getData*сайтах викликів.
Ось чому я думаю, що реальні методи підвищують ремонтопридатність порівняно з використанням getData*аксесуарів.

Тому я думаю, що це зводиться до компромісу між ремонтом і швидшою реалізацією (менше писати код).

На щастя, сьогодні IDE дуже добре створюють реалізацію getter та setter для нас, тому цей аргумент насправді вже не застосовується.

Ще один аргумент проти магічних геттерів та сеттерів, яких немає у вищезазначеному питанні, полягає в тому, що створити плагіни для них неможливо.

Єдине інше значення, яке, на мою думку, я можу додати до теми, - це намагання зібрати причини використання або не використання @methodанотацій, якщо реалізація реальних методів чомусь не підлягає.

Плюси

  • @methodАнотації трохи менше коди записи по порівнянні з реалізацією реального отримання і установки. Це навряд чи справді, хоча в даний час ІДЕ добре створює методи доступу, тому це вже не є реальною вигодою.

Мінуси

  • Справа легко піде не так.
    • Анотації - це коментарі, вони легко застарівають, коли код розвивається, але примітки не оновлюються. Реальні методи більш надійні.
    • Можна додати кілька анотацій з підписами різного типу без помилки інтерпретатора - поведінка статичного аналізу коду не визначена, і це може призвести до тонких помилок, які важко відстежити.
    • Якщо @methodіснують як анотація, так і реальний метод з тим самим іменем, підпис типу анотації перекриває реальний метод під час аналізу статичного коду, що є протилежним тому, що робить інтерпретатор PHP. Це знову ж таки може легко призвести до тонких помилок.

З вищезазначених причин я особисто не використовую @methodанотацій, якщо можу їх уникнути.
Для коду, який призначений прожити довгий час, я реалізую реальні методи отримання та встановлення. Підвищення ремонтоздатності вартує зусиль, щоб викликати IDE для їх генерації.

Для отримання більш експериментального коду під час шипу або для простої деталізації реалізації модуля я також використовую getData*методи, тому що я лінивий.


Приємний підсумок. Дякую, Віней. Це відповідає більше, ніж я насправді запитував.
sv3n

1

Усі getData*методи мають той мінус, що їх потрібно помітити для висновку типу роботи.

Зазвичай це робиться з /*@var string $foo */приміткою над getData*викликом. Це трохи смердюче, тому що тип даних повинен бути оголошений у класі, який містить дані, а не в класі, який викликає getData *.

Причиною тому є те, що якщо дані змінюються, клас, найімовірніше, буде оновлюватися не на всіх getData*сайтах викликів. Ось чому я вважаю, що реальні методи збільшують ремонтопридатність порівняно з використанням доступу getData *.

Так, він смердючий, але можна (і слід?) Уникнути. Я думаю, що це дуже поширений код і часто пропонується:

/** @var Foo $product */
$product = $model->getProduct()
if ($product->getId()) {
    $product->doSomething();
}

Проблеми полягають у тому, що ви просто здогадуєтесь, що повернене значення має тип Fooз методом, що викликається getId().

Для ремонтопридатності, чому б не припустити змінний тип і не додати InvalidArgumentException?

$product = $model->getProduct()
if ($product instanceof Foo && $product->getId()) {
    $product->doSomething();
}

Це також фіксує статичний аналіз коду у випадку, якщо він $model->getProduct()має різні типи повернення Foo|false. У першому випадку він скаржиться doSomething()на можливі дзвінки false.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.