A объект бога - это объект, который прямо или косвенно содержит ссылки на большинство, если не на все объекты в приложении.Как следует из вопроса, почти невозможно избежать наличия объекта бога в приложении. Некоторые объекты должны содержать ссылки на различные подсистемы: пользовательский интерфейс, базу данных, коммуникации, бизнес-логику и т. Д. Обратите внимание, что объект 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
все, что нужно знать, - это одно целое число - количество десятичных знаков.Он может быть создан непосредственно объектом бога приложения, который знает магическое число (или менеджер преф, или, что еще лучше, числовые префы), не превращая средство форматирования в сам объект бога.Кроме того, любые компоненты, которые должны отформатировать числа, могли бы получить средство форматирования вместо объекта бога.Побеждает все вокруг.
Итак, подведем итог: проблема не в существовании божественного объекта, а в акте придания богоподобного статуса другим объектам волей-неволей.
Кстати,Принцип дизайна, который решает эту проблему, стал известен как Закон Деметры .Или «при оплате в ресторане отдайте серверу свои деньги, а не кошелек».