13

阅读关于上帝对象的维基百科条目,它说当一个类知道太多或做得太多时,它就是一个上帝对象。

我看到了这背后的逻辑,但如果这是真的,那么你如何将每个不同的类结合起来?你不总是使用大师班来连接窗口管理、数据库连接等吗?

4

4 回答 4

16

主函数/方法可能知道窗口、数据库和其他对象的存在。它可以执行总体任务,例如将模型引入控制器。

但这并不意味着它管理所有的小细节。它可能对数据库或窗口的实现方式一无所知。

如果是这样,它可能会被指责为上帝的对象。

于 2010-12-30T05:44:06.883 回答
8

上帝对象是一个对象,它直接或间接地包含对应用程序中大多数(如果不是全部)对象的引用。正如问题所观察到的,在应用程序中避免使用上帝对象几乎是不可能的。 某些对象必须包含对各种子系统的引用:UI、数据库、通信、业务逻辑等。请注意,上帝对象不必是应用程序定义的。许多框架都有内置的上帝对象,名称如“应用程序上下文”、“应用程序环境”、“会话”、“激活器”等。

问题不在于上帝对象是否存在,而在于如何使用它。我将用一个极端的例子来说明......

假设在我的应用程序中,我想标准化显示数字时要显示的小数位数。但是,我希望精度是可配置的。我创建了一个类,其职责是将数字转换为字符串:

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 manager... WTF,我必须模拟14种方法!数字首选项!?!算了,这个类很简单,我不需要测试它......

假设应用程序上下文有另一个方法,getDatabaseManager(). 上周我们使用的是 SQL,因此该方法返回了一个 SQL 数据库对象。但本周,我们决定更改为 NoSQL 数据库,该方法现在返回一个新类型。是否NumberFormatter受到变化的影响?嗯,我不记得了……是的,可能是,我看到它在构造函数中需要一个应用程序上下文……让我打开源代码看看……不,我们很幸运:它只访问getPreferenceManager()... 现在让我们检查其他 93 个将应用程序上下文作为参数的类...

如果对首选项管理器或数字首选项对象进行更改,则会发生相同的情况。这个故事的寓意是一个对象应该只包含对它执行其工作所需的事物的引用,并且只有那些事物。在 的情况下NumberFormatter,它只需要知道一个整数——小数位数。它可以直接由知道幻数的应用程序上帝对象(或首选项管理器或更好的数字首选项)创建,而无需将格式化程序本身转换为上帝对象。此外,任何需要格式化数字的组件都可以使用格式化程序而不是上帝对象。全场取胜。

因此,总而言之,问题不在于上帝对象的存在,而在于随意赋予其他对象以上帝般的地位的行为。

顺便说一句,正面解决这个问题的设计原则被称为得墨忒耳定律。或者“在餐厅付款时,给服务员你的钱而不是你的钱包。”

于 2011-01-23T16:19:41.060 回答
3

以我的经验,这种情况最常发生在您处理的代码是“随用随开发”项目管理(或缺乏)的产品时。当一个项目没有经过深思熟虑和计划并且对象职责松散并且没有正确委派时。在这些场景中,您会发现“上帝对象”是没有任何明显组织或委托的代码的统称。

上帝对象的问题不是不同类的互连或耦合,而是上帝对象多次可以完成其派生子对象的大部分(如果不是全部)职责,并且相当不可预测(由其他任何人比开发人员)关于他们定义的职责是什么。

于 2010-12-30T05:42:16.793 回答
2

仅仅知道“多个”类并不能使一个成为上帝。了解多个类以解决应该分成几个子问题的问题 确实使一个人成为上帝。

我认为重点应该放在一个问题是否应该分成几个子问题,而不是给定对象知道的类的数量(正如你所指出的,有时了解几个类是必要的)。

大神们夸大了。

于 2010-12-30T05:51:05.027 回答