代码之家  ›  专栏  ›  技术社区  ›  TheLQ

我怎么能写一个控制器而不使它成为上帝的对象呢?

  •  8
  • TheLQ  · 技术社区  · 14 年前

    在我的应用程序中,我有一个 Controller 这是从主方法开始的。控制器初始化钩子、数据库连接、UI、另一个连接和其他内容。它保存了程序的大部分状态(不,它不是单例)。在另一个例子中,bot有一个控制器,负责解释和发送命令。两者都是相当大的文件。

    我读过上帝的东西,但我真的不知道如何把它分开。如果我在bot中拆分了解释器和调度器,它将产生一个可怕的呼叫链(类似于 getBot().getParser().getOutput().sendMessage(recipient, message) )类似地,在第一个控制器中,如果我将内容拆分,您将只拥有保存字段的数据对象和一些别名实用程序方法。把他们分开只会让事情更糟。在你假设它是不可维护的之前,它实际上不是。我甚至没有写机器人控制器,但我仍然知道发生了什么。

    但问题是bot类有2000行长(如果我去掉javadoc的注释,可能会短一些),bot大约有1000行长。很多线条=上帝的物体。但是对于一个项目的一个或两个核心类来说,这样可以吗?

    4 回复  |  直到 12 年前
        1
  •  11
  •   David Titarenco    14 年前

    “很多行”并不意味着类是一个上帝的对象,这是一个很糟糕的基准,用来判断你是否应该重构某个东西。有些事情非常复杂,需要一个复杂的,本质上很大的物体。神的观念是什么样的阶级 .

    例如,如果我做了一个可以

    DoMyTaxes()
    GiveMeHugs()
    LogThisError()
    StartGameLoop()
    

    即使对象可能只有100行代码,它也可以作为上帝对象。其基本思想是,上述所有内容都是完全不相关的(在业务逻辑方面),因此,为什么它们在世界上都是同一对象的一部分。如果我决定让拥抱持续更长时间,我最终可能会搞砸我的税。输入IRS。

    但是,如果你正在研究一个物理模拟器,比如说, Classical() 类将具有方法/对象,例如:

    Space()
    Time()
    Velocity()
    Speed()
    Mass()
    Acceleration()
    Gravity()
    Force()
    Impulse()
    Torque()
    Momentum()
    AngularMomentum()
    Inertia()
    MomentOfInertia()
    ReferenceFrame()
    Energy()
    KineticEnergy()
    PotentialEnergy()
    MechanicalWork()
    VirtualWork()
    DAlembertsPrinciple()
    

    (由维基百科提供)

    这个物体不会是上帝的物体。它是一个复杂的物体。所有与牛顿物理学有关的东西都经过它,但它不是上帝的物体。它只是一个非常大的物体。以上可能是成千上万行的代码。

    这个 Quantum() 不用说,物体会更复杂。

    重申一下,这个想法是关于一个项目的 行为 不是 数据流 :

    你不在乎一个物体 拥有大量的应用程序数据,或者 大多数流量是否必须通过 单个对象。什么更有影响 关于可维护性是当一个单一的上帝 类(tm)包含太多行为 (业务代码)。

    如果你认为有问题,你可以尝试实现不同形式的 mediation 或更丑陋的图案,如 dependency injection .

        2
  •  3
  •   drekka    14 年前

    如果您对类的大小和复杂性不满意,那么它通常是一个很好的指示器,表明可以进行更好的设计。但不要只测量尺寸。如果一个类易于理解和遵循,但包含大量代码,这并不一定意味着它是重新分解的候选者。我已经看到人们被这些和他们在追求使事物变小的过程中制造的混乱所迷住,这比原始代码更糟糕。另一方面,我已经从头到尾通读了好几遍,但仍然不知道他们在做什么。

    我要问的问题是——如果我把这个给了另一个开发人员,他们是否能够很容易地理解和维护它?

    如果答案是肯定的,那么很可能你不需要做任何事情。如果不是这样,那么就按顺序重新进行因子分解。

    关于上帝的物体,阅读你的帖子,听起来好像这门课做的太多了。我想知道,首先您是否可以将状态重新分解为一组模型对象作为起点。然后您的类开始看起来更像某种类型的配置工厂。

        3
  •  2
  •   supercat    14 年前

    我建议物理/运动引擎必须与语言解释器分开;虽然语言解释器需要访问物理引擎的一些公共方法和属性,但没有理由机器人的两个方面应该在同一个C中。小姑娘。语言解释器本身可以细分为几个类,运动引擎也是如此。可能有一个主控对象,但它应该有相对少量的代码。它,主要的运动引擎,和主要的语言引擎,都应该将它们的大部分工作委托给组成它们的对象。

        4
  •  0
  •   Oliver Watkins    12 年前

    我认为这里的关键原则是“凝聚力”。

    DoMyTaxes()
    GiveMeHugs()
    LogThisError()
    StartGameLoop()
    

    …没有凝聚力。

    比如:

    GiveMeHug()
    GiveMeKisses()
    GiveMeHugs(int noOfTimes)
    GiveMeHugs(int noOfTimes, Person person)
    GiveMeHugsAndKisses()
    

    ..具有凝聚力,因为所有方法都相当相似。你可以在一个类中有1000个内聚方法,但它仍然不是一个上帝的对象,因为类的责任仍然有限。