Статичний стан поганий, але як бути з заводською схемою?


13

Я працюю над проектом TDD, тому намагаюся якомога більше дотримуватися добрих стосунків, пов'язаних із таким розвитком. Один з них - максимально уникати статичного та глобального.

Я зіткнувся з цією проблемою: у мене об’єкт "стаття", який може мати "параметри" (додаткові "мікро-статті").

Я не можу зрозуміти, як мати хороший підхід, який не буде контрпродуктивним або генерувати надто багато запитів, тому що я опинився б у ситуації, коли все настільки нерозривно, що мені в основному потрібно робити 1 запит на об'єкт.

З моєї реальної точки зору, я бачу 3 варіанти:

1) Побудувати всередині статті:

class Article
{
    //[...]
    public function getArrOption(){
        //Build an array of Options instance.
        //return an array of Options.
    }
}

Pro: Прямо вперед

Const: Maintenability: Об'єкт статті тепер містить логіку побудови об’єкта Option. Це, ймовірно, призведе до дублювання коду.

2) Використання параметраFactory

class Article
{
    //[...]
    public function getArrOption(){
        return OptionFactory::buildFromArticleId($this->getId());
    }
}

Про: Логіка побудови не виходить із класу Article

Конст: Я порушую правило "статичного важко знущатися", тому важко перевіряю клас статті.

3) Відокремте всі логіки.

//Build the array of Option instance in a controller somewhere, using a Factory:
$arrOption = OptionFactory::buildFromArticleId($article->getId());

Про: Стаття поводиться лише з власною відповідальністю, і це не стосується його "батькового" посилання на варіанти. Речі справді розв'язані

Const: Буде потрібно більше коду всередині контролера щоразу, коли мені потрібно буде отримати доступ до параметрів. Це означає, що я ніколи не повинен використовувати Фабрику всередині предмета, і це звучить для мене щось утопічне ...

Який найкращий шлях? (Я щось пропустив?) Дякую.

Редагувати:

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


Я не впевнений, що це доречно, але я кодую PHP, тому "додаток" є станом менше. Ми повинні перезавантажити всі дані між кожною сторінкою, якщо вони не зберігаються в сесійному файлі cookie. Це означає, що ми не можемо попередньо завантажити все, як на мові програми.
— FMaz008

@job: Ну це тому, що статичний виклик всередині методу в основному неможливо замінити при тестуванні одиниць. Мета - використовувати ін'єкцію залежності. Але фабрика зазвичай статична, тому її не можна вводити.
— FMaz008

Відповіді:


12
  1. Статична статистика не є "поганою", вона неможлива. Ви все ще можете використовувати його там, де глузувати не має сенсу.

  2. Це не заводський зразок, він схожий на шаблон сховища, хоча може і не бути. Завод - це те, де у вас є кілька класів з одним інтерфейсом / базовим класом, і ви хочете відокремити логіку, яка вирішує, який клас повернути. Репозиторій отримує дані зі свого сховища, обмежуючи реалізацію цього сховища (Статтю не потрібно знати, чи зберігаються його параметри в одній БД, в іншій, XML-файлі, у файлі CSV тощо).

  3. Ви проігнорували можливість надання класу Article об’єкту ObjectFactory (або репозиторію чи будь-якого іншого) в конструкторі, на якому він може викликати метод buildFromArticle.

Мій PHP іржавий, але я думаю, що це виглядає приблизно так:

class Article
{
    private $_option_repository;

    public function __construct($option_repository) {
        $_option_repository = $option_repository;
    }

    //[...]

    public function getArrOption(){
        return $_option_repository->buildFromArticleId($this->getId());
    }
}

Я думаю, що це відповідає всім вашим плюсам вище.


Тож нормально мати екземпляри Factory / Repository / Mapper? Мені знадобиться контейнер залежності або щось подібне, тому що якщо нам потрібно ввести весь завод / сховище / картограф для всіх можливих об'єктів, які можуть бути повернуті об'єктом, це швидко зробило багато. (Стаття -> OptionGroup -> Варіант -> Стаття тощо)
— FMaz008

1
Це більше, ніж нормально, краще. Зазвичай я зарезервую статичне використання для видалення повторного коду, де він досить малий, щоб перевірити його в декількох класах. І так, контейнер IOC / DI полегшить ваше життя набагато простіше. Використовуйте один.
— пдр

1

Ось цитата з документа, яка стверджує, що статичні методи ніколи не потрібні, що абстрактні фабрики були заплутані, і передбачає незначну зміну мови у напрямку введення залежності як рішення.

Жорстке з'єднання між екземплярами та їхніми класами порушує інкапсуляцію, а разом із глобальною видимістю статичних методів ускладнює тестування. Зробивши введення функції залежності в мову програмування, ми можемо повністю позбутися статичних методів. Ми застосовуємо наступні смислові зміни:

(1) замінювати кожне виникнення глобальної інформації на доступ до змінної екземпляра;

(2) Нехай ця змінна інстанція буде автоматично введена в об'єкт, коли вона створена.

"Seuss: Розв'язування обов'язків від статичних методів для тонкої зернистості"

Wayback Machine Link


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