Является ли класс, который управляет несколькими классами, "объектом бога"?
Читая статью в Википедии о объектах Бога, он говорит, что класс - это объект Бога, когда он знает слишком много или делает слишком много.
Я вижу логику в этом, но если это правда, то как вы соединяете каждый класс? Разве вы не всегда используете мастер-класс для подключения управления окнами, подключений к БД и т. Д.?
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
все, что нужно знать, это одно целое число - количество десятичных знаков. Он может быть создан непосредственно объектом бога приложения, который знает магическое число (или менеджер преф, или, что еще лучше, числовые префы), не превращая средство форматирования в сам объект бога. Кроме того, любые компоненты, которые должны отформатировать числа, могли бы получить средство форматирования вместо объекта бога. Побеждает все вокруг.
Подводя итог, можно сказать, что проблема не в существовании божественного объекта, а в акте придания богоподобного статуса другим объектам волей-неволей.
Между прочим, принцип дизайна, который решает эту проблему, стал известен как Закон Деметры. Или "при оплате в ресторане отдайте серверу свои деньги, а не кошелек".
По моему опыту, это чаще всего происходит, когда вы имеете дело с кодом, который является продуктом управления проектами "Разработка по мере продвижения" (или его отсутствие). Когда проект не продуман и не спланирован, а обязанности объекта бесполезны и не делегированы должным образом. В этих сценариях вы обнаружите, что "божий объект" - это ловушка для кода, который не имеет какой-либо очевидной организации или делегирования.
Проблема не в взаимосвязанности или соединении различных классов и является проблемой с бог-объектами, а в том, что бог-объект много раз может выполнять большинство, если не все обязанности своих потомков, и довольно непредсказуемы (кем-либо другим чем разработчик) относительно того, каковы их определенные обязанности.
Простое знание о "множественных" классах не делает человека Богом; знание о нескольких классах для решения проблемы, которая должна быть разбита на несколько подзадач , делает Бога.
Я думаю, что внимание должно быть сосредоточено на том, следует ли разбить проблему на несколько подзадач, а не на количество классов, о которых знает данный объект (как вы указали, иногда необходимо знать о нескольких классах).
Боги слишком раздуты.