OOP:是否应该在班级或前端处理有效数据?

时间:2014-02-04 15:01:25

标签: oop

假设我有一个多边形类。它唯一的私有数据是一系列点。是否应该在假设阵列至少有3个点的情况下编写类,并且程序的GUI或输入部分确保有三个点?或者成员函数是否应该测试数据有效性并在需要时返回错误消息?

4 个答案:

答案 0 :(得分:2)

其他答案中有一些好处。我会试着在这里说出来:

  • 最终,模型负责了解它是否处于有效状态。
  • 如果模型处于有效状态,UI需要知道。
  • 用户界面可以保护模型免受无效状态的影响,并通过验证输入提供良好的用户反馈。

存在一些挑战:

  • 如果模型和UI都有验证代码,则结果是模型/ UI中的重复代码或验证职责的模型和UI之间的分割。
  • UI验证变得混乱,因为某些数据字段依赖于其他数据字段。想象一下收集邮政编码和州(适用于美国邮政地址)的应用程序。如果您更改状态,是否希望UI立即弹出一个显示“无效邮政编码”的对话框?不,那会很烦人。 UI应该为用户提供将模型置于有效状态的机会。
  • 抛出异常以捕获验证错误是一种严厉的处理方式。通常,你会想要一些不那么突兀的东西。

以下是我想要进行复杂验证的内容:

  • 允许用户输入无效值。
  • 创建一个名为ValidationError的类,其中包含对单个验证错误的可读描述。
  • 提供getValidationErrors()isValid()等模型方法。
  • 在对模型进行任何更改之前,请调用UI isValid()getValidationErrors()。如果存在任何验证错误,请让UI向用户显示错误。阻止用户继续操作,直到错误得到修复。

这种方法的优点是:    - 更多的验证控制。您可以决定何时以及要验证的内容。    - 在模型中集中验证逻辑。 UI仅负责获取和显示模型生成的错误。    - 如果模型在调用save / commit方法之前调用isValid(),则其他其他代码对模型进行无效更改的风险较小。    - 没有异常处理程序。

考虑创建一个ValidationRule类。每个规则都包含有效内容的代码,如果无效,则生成错误消息。 ValidationRule类有一个方法validate(aModel)。如果您的编程语言支持闭包或一流函数,这将特别容易。

这导致每个模型类都可以拥有一个ValidationRule对象的动态集合,它在调用isValid()getValiationErrors()时会参与其中。或者,使用访问者模式,以便模型与验证完全分离。这就是我在验证框架中所做的。

在模型不在客户端上的分布式应用程序中,在将更改发送到服务器之前进行一些基本验证通常是明智的。客户端和服务器之间的往返时间可能很长,您不希望向服务器发送明显无效的请求。

最后,一个对象的有效性有时取决于不同对象中的数据!在这些情况下,我让验证规则接受多个对象,并使用控制器对象(或者我创建一个上下文对象)来以较低的粒度级别管理验证。

答案 1 :(得分:1)

GUI验证仅适用于用户提示。

模型应该对其自身的完整性负责,因为数据可能来自不同的来源,而不是来自用户[例如,后台同步]。

答案 2 :(得分:1)

恕我直言,精心设计的课程将始终保护其不变量。因此,该类必须验证并始终确保它处于有效状态。

用户界面也可以做到这一点,或者只是依靠课程。

看看Mark Seemann的博文here

答案 3 :(得分:1)

如果课程预计至少有3分,你必须通过课程界面确保它。实现此目的的唯一方法(实际上唯一且最好的)是在类构造函数参数中接收多边形的点,并在点小于3时抛出异常(请记住,在良好的OOP设计中,异常不能被视为错误,但违反了隐含合同)。 然后,您只需要保持未修改这些点的值。想想他们在Java中的“最终”。请记住,无论是什么使您的对象在每个可能的可能多边形中的某个多边形都不会被修改。例如,如果您在构造函数中分配了点,那么这些点应该在数量和值的整个对象的生命周期中保留。 总是回想起OOP中最纯粹的对象定义:对象是现实生活实体的计算表示。如果您的对象表示多边形P,则它应该永远不会更改以表示另一个多边形或任何其他现实生活实体。如果它实际上不代表真实世界的多边形,那么你绝不能创建一个“Polygon”对象。而这只能通过类构造函数来实现。 按照这些设计指南,您永远不需要添加代码来验证您的对象是Polygon类中的多边形,因为它是对象范例中的真正多边形。 创建多边形时,请尝试try {} catch {},如果需要,让构造函数抛出NotPolygonException。