Является ли класс, который управляет несколькими классами, "объектом бога"?

Читая статью в Википедии о объектах Бога, он говорит, что класс - это объект Бога, когда он знает слишком много или делает слишком много.

Я вижу логику в этом, но если это правда, то как вы соединяете каждый класс? Разве вы не всегда используете мастер-класс для подключения управления окнами, подключений к БД и т. Д.?

4 ответа

Решение

Основная функция / метод может знать о существовании окон, баз данных и других объектов. Он может выполнять сложные задачи, такие как представление модели контроллеру.

Но это не значит, что он управляет всеми мелкими деталями. Вероятно, он ничего не знает о том, как реализована база данных или окна.

Если это так, его можно обвинить в том, что он является объектом Бога.

Объект бога - это объект, который прямо или косвенно содержит ссылки на большинство, если не на все объекты в приложении. Как следует из вопроса, почти невозможно избежать наличия объекта бога в приложении. Некоторые объекты должны содержать ссылки на различные подсистемы: пользовательский интерфейс, базу данных, коммуникации, бизнес-логику и т. Д. Обратите внимание, что объект god не обязательно должен определяться приложением. Многие фреймворки имеют встроенные объекты God с такими именами, как "контекст приложения", "среда приложения", "сессия", "активатор" и т. Д.

Вопрос не в том, существует ли объект бога, а в том, как он используется. Я проиллюстрирую на крайнем примере...

Допустим, в моем приложении я хочу стандартизировать, сколько десятичных разрядов точности отображать при отображении чисел. Однако я хочу, чтобы точность была настраиваемой. Я создаю класс, в обязанности которого входит преобразование чисел в строки:

class NumberFormatter {
    ...
    String format(double value) {
        int decimalPlaces = getConfiguredPrecision();
        return formatDouble(value, decimalPlaces);
    }

    int getConfiguredPrecision() {
        return /* what ??? */;
    }
}

Вопрос в том, как getConfiguredPrecision придумать что вернуть? Одним из способов было бы дать NumberFormatter ссылка на глобальный контекст приложения, который он хранит в поле члена, называемом _appContext, Тогда мы могли бы написать:

return _appContext.getPreferenceManager().getNumericPreferences().getDecimalPlaces();

Сделав это, мы только что сделали NumberFormatter в объект бога, а также! Зачем? Потому что теперь мы можем (косвенно) ссылаться практически на любой объект в приложении через его _appContext поле. Это плохо? Да, это.

Я собираюсь написать модульный тест для NumberFormatter, Давайте настроим параметры... ему нужен контекст приложения?! WTF, у меня есть 57 методов, которые мне нужно высмеивать. Ох, для этого нужен только менеджер pref... WTF, я должен издеваться над 14 методами! Числовые префы!?! Винт это, класс достаточно прост, мне не нужно проверять это...

Допустим, у контекста приложения был другой метод, getDatabaseManager(), На прошлой неделе мы использовали SQL, поэтому метод возвратил объект базы данных SQL. Но на этой неделе мы решили перейти на базу данных NoSQL, и теперь метод возвращает новый тип. Является NumberFormatter повлияло изменение? Хммм, я не могу вспомнить... да, может быть, я вижу, что это берет контекст приложения в конструкторе... позвольте мне открыть исходный код и взглянуть... Нет, нам повезло: это только доступ getPreferenceManager()... теперь давайте проверим остальные 93 класса, которые принимают контекст приложения в качестве параметра...

Этот же сценарий возникает, если вносятся изменения в менеджер предпочтений или в числовой объект предпочтений. Мораль этой истории заключается в том, что объект должен содержать только ссылки на то, что ему нужно для выполнения своей работы, и только эти вещи. В случае NumberFormatterвсе, что нужно знать, это одно целое число - количество десятичных знаков. Он может быть создан непосредственно объектом бога приложения, который знает магическое число (или менеджер преф, или, что еще лучше, числовые префы), не превращая средство форматирования в сам объект бога. Кроме того, любые компоненты, которые должны отформатировать числа, могли бы получить средство форматирования вместо объекта бога. Побеждает все вокруг.

Подводя итог, можно сказать, что проблема не в существовании божественного объекта, а в акте придания богоподобного статуса другим объектам волей-неволей.

Между прочим, принцип дизайна, который решает эту проблему, стал известен как Закон Деметры. Или "при оплате в ресторане отдайте серверу свои деньги, а не кошелек".

По моему опыту, это чаще всего происходит, когда вы имеете дело с кодом, который является продуктом управления проектами "Разработка по мере продвижения" (или его отсутствие). Когда проект не продуман и не спланирован, а обязанности объекта бесполезны и не делегированы должным образом. В этих сценариях вы обнаружите, что "божий объект" - это ловушка для кода, который не имеет какой-либо очевидной организации или делегирования.

Проблема не в взаимосвязанности или соединении различных классов и является проблемой с бог-объектами, а в том, что бог-объект много раз может выполнять большинство, если не все обязанности своих потомков, и довольно непредсказуемы (кем-либо другим чем разработчик) относительно того, каковы их определенные обязанности.

Простое знание о "множественных" классах не делает человека Богом; знание о нескольких классах для решения проблемы, которая должна быть разбита на несколько подзадач , делает Бога.

Я думаю, что внимание должно быть сосредоточено на том, следует ли разбить проблему на несколько подзадач, а не на количество классов, о которых знает данный объект (как вы указали, иногда необходимо знать о нескольких классах).

Боги слишком раздуты.

Другие вопросы по тегам