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


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.