对象的详细程度如何?

时间:2009-12-10 12:37:53

标签: c# oop

我正在开发一种HMI应用程序,并且正在创建定义特定机器的对象。让我们说这是为了争论的车。

引擎的对象很明显。引擎上有一些常见的传感器,这是一些安装在引擎对象上的几个属性的对象。油门属性当然是一个输入。

这辆车至少有一扇门。每扇门都可以有一个窗户,它可以打开,也可以电动操作。如果它是电动的,它将取决于汽车的动力来运行。

现在,我应该将门作为汽车对象的属性暴露出来,还是将它保密并让汽车对象在OpenDoor和RollDownWindow函数中操作门是最明智的?活动怎么样?我应该在引擎上公开事件,例如LowOnOil事件,还是我应该在汽车对象中处理它反过来又可能有像EngineIsLowOnOil这样的事件?

你会怎么做?

9 个答案:

答案 0 :(得分:8)

通过考虑建立模型的原因,可以回答这个以及所有类似的问题。创建一个独立于您尝试解决的问题的模型是绝对没有意义的,并且通常不可能这样做。

例如,如果您正在构建电子燃油喷射控制系统,那么车辆上的车门数量(甚至车辆本身的车辆数量)都没有意义,也不应该建模。

答案 1 :(得分:7)

让我们探讨一下打开汽车门的例子(比如左前方)。人们可以采取几种方法(包括你建议的方法):

  1. Car.OpenFrontLeftDoor
  2. Car.OpenDoor(FRONTLEFT)
  3. Car.Door(FRONTLEFT)。开
  4. Car.Part(DOOR_FRONTLEFT)。开
  5. Car.Part(DOOR_FRONTLEFT).DoAction(OPEN)
  6. 它们都不对或错,这取决于具体情况。我相信还有很多方法。

    1号是一种硬编码函数方法。这对于非常简单的固定情况很有用。但如果你的模型需要适应变化,它将变得无法管理。

    5号采用参数化方法。后者更灵活,需要更大的设计才能完成,但对于一个简单的问题可能会有点过分。

    另外请记住,您的汽车对象可以呈现与内部实施不同的外部界面。例如,你可以在内部使用方法5但是提供一个接口,例如1,并在引擎盖下翻译函数调用(没有双关语)。

    最终,做出这样决定的能力来自经验。让自己暴露在良好的OO设计,阅读书籍,检查好软件的源代码。最重要的是,尝试不同的设计,看看自己有什么作用和原因。

答案 2 :(得分:4)

爱因斯坦说:“尽可能简单,但不要简单。”

从一个空对象开始。在开发整个模型时,只向那些对象添加那些NECESSARY属性。

答案 3 :(得分:2)

我认为这是一个很难回答的非常通用的问题。我的最佳答案是“这取决于您的需求以及您要解决的问题域”。

答案 4 :(得分:2)

在您给出的情景中,我通常倾向于在现实生活情况下考虑它。

因此车门不是私人的,即车门可以公开进入。汽车没有打开车门(除非它是一辆非常酷的车!)用户会打开车门。因此,门应该是汽车的公共财产。

在揭露事件方面,这实际上取决于你是否打算处理这些事件。例如,OnLowOil事件可能是您希望处理的事件,即通知可能会执行Car.Engine.FillOil的用户

答案 5 :(得分:0)

我喜欢简单易懂。在你的领域/对象中想想你将如何谈论对象以确定建模方法,你会说我的车需要油还是我的汽车发动机需要油?

这取决于域名。汽车工厂的域名与汽车租赁域名不同。

我会为每个窗口和事件提供多个窗口属性,以及窗口状态/位置。

答案 6 :(得分:0)

没有正确或错误的模型;有些模型或多或少对您的特定用途有用。

正如其他人所说,首先考虑哪些信息与您的需求相关。然后丢弃其余的。删除不必要的细节的过程称为抽象。如果我们不执行抽象,我们的模型将与它们所代表的真实世界实体完全相同!这将是无用的,因为建模的最终目标是获得现实的简化版本,允许我们在缺席的情况下对其进行推理。

答案 7 :(得分:0)

我认为这里有几个人也有同样的观点,但我会再试一次。

您正在询问我应该或不应该公开“开门”活动的问题。除了另一个问题之外,这个问题没有答案:你打算如何使用它?

最终,模型是手段而不是目标,因此模型不能在上下文之外定义。甚至(特别是)如果您正在构建模型以将其作为独立产品销售,您必须考虑客户将如何使用它 - 再次 - 是关于上下文的讨论。

尝试以其他任何方式回答这些问题(直觉?)将是针对指针结束计数恶魔的练习

答案 8 :(得分:0)

如果有疑问,请从另一种方法考虑问题:“我如何测试这些对象?” “我怎么测试窗户?” “什么会让测试变得最简单?”作为一个懒惰的程序员,这对我来说是一个非常重要的问题。我希望编写测试简单,但在证明我的代码有效方面非常有效。

在您的情况下,您的车门可以打开和关闭,门上有可以打开和关闭的窗户,它们可能会也可能不会电动操作。你会如何测试“窗口”功能?窗口的存在是否依赖于引擎?它是否依赖于汽车,还是仅仅依赖于车门?不同的门是否有不同形状的窗户,有不同的规则或不同的旅行量?不同的门是否使用相同的电动机来驱动窗户,或者左侧安装与右侧安装的窗户电机是否不同?

并且考虑到客户可能会给出一个要求“窗口仅在引擎运行时工作”的要求,但这是真的吗?在大多数汽车中,当汽车的电源开关转到“开”时,窗户工作。换句话说,窗户操作是依赖于发动机中的旋转曲轴,还是实际上取决于12伏电?那么你真的需要汽车中的引擎实例来测试窗口,还是只需要一块电池?

一旦你开始问这些问题,你可能会得出结论,电动车窗口应该有自己的一套测试(上/下/部分/全程/等),所以它变得很好成为自己班级的候选人。不同门的数量可能很复杂,因此您认为“门工厂”可能是适合创建的类,可以管理所有不同类型的门。孤立地测试事物总是比较容易:看看关于测试窗口函数的发动机油门设置应该是什么的更难的问题?传动装置或门开/关状态怎么样?所有这些排列使得很难测试,即使它们与窗口是否工作无关。所以这些让我觉得窗口类应该尽可能独立测试。在现实世界中,您只需要12伏电压来测试安装在门上的电动车窗。因此,在您建模的世界中,您只需要一个模拟或假的电源对象来提供建模的电源,而不是发动机对象或传动装置。这是一个更简单的测试。

在考虑了这些想法之后,你开始意识到在测试中传递依赖关系(这里是窗口测试的电源)使它们易于测试;因此,在模型中组装真实组件的方法意味着在工厂中封装结构将是创建汽车的最简单方法;因此,建造汽车可能会建议使用抽象工厂模式将所有依赖项注入汽车。

你甚至可以从一个简单但脆弱的Car类开始,它带有硬编码引擎和硬编码门,然后重构它以添加如上所述的测试。你可能仍然会得到独立的Car,Door和Window对象,以及一个抽象的工厂模式,根据正在建造的汽车模型创建它们。这个想法被称为“紧急设计”。