Является ли класс, который управляет несколькими классами, «божественным объектом»? - PullRequest
13 голосов
/ 30 декабря 2010

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

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

Ответы [ 4 ]

16 голосов
/ 30 декабря 2010

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

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

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

7 голосов
/ 23 января 2011

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

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

Кстати,Принцип дизайна, который решает эту проблему, стал известен как Закон Деметры .Или «при оплате в ресторане отдайте серверу свои деньги, а не кошелек».

3 голосов
/ 30 декабря 2010

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

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

2 голосов
/ 30 декабря 2010

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

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

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

...