0

当参数包含在对象中时,我有一个关于验证方法参数的最佳实践的问题。例如,如果您有:

public class Student {
   public int getStudentId();

   public String getStudentName();

   public String getStudentSSN();

   public double getStudentGpa();

   public String getStudentMajor();

   // Other student related getters
}

然后,我有一个方法:

public void printStudentReport(Student student);

在这种方法中,我需要执行涉及 ID、姓名、GPA 和专业的逻辑。所以,这些是必需的。不必填充所有其他学生吸气剂。是否可以先验证 Student 对象,然后验证我需要的这四种方法?我觉得这有点误导,因为我将此 Student 对象传递给此方法,但并非所有字段都是必需的,因此它实际上是一个半填充对象被发送到此方法。对我来说似乎很奇怪。

4

7 回答 7

2

如果必须始终填充某些属性以使 Student 有效,则应考虑使用所需参数定义非默认构造函数,并从类中删除任何默认构造函数(如果需要,验证 getter 中的属性值)。这确保只能创建有效的学生对象。

如果其他属性对于学生来说真的是可选的,那么对我来说它看起来完全没问题。当然,您需要仔细考虑用例并仔细分析领域模型,以确定哪些参数是必需的,哪些是可选的。

于 2010-07-28T16:12:23.540 回答
1

想想您正在创建的概念:学生报告。该方法仅使用一组学生数据并不重要,因为这些是您报告的当前要求。也许他们将来会改变。也许他们不会。但这似乎是正确的设计,因为它更能适应变化。

现在验证更加棘手。报告是否需要一种特殊的验证,不同于学生的正常验证?如果是这种情况,那么一定要在报告中验证它:

public void printStudentReport(Student student) {
  validateStudent(student);
  // print the report....
}

但是如果验证对于一组客户端来说是通用的(可能是 forprintStudentReport和 for saveStudentInDatabase),那么您可以创建一个验证类:

public class FloogleStudentValidator { // or some good name that tells us what this validation does
  public void validate(Student student) { }
}

// ...

public void printStudentReport(Student student) {
  new FloogleStudentValidator().validate(student);
  // print the report....
}

对于不同类型的学生验证,您将有不同的课程。

但是,如果验证对整个系统来说是通用的,那么我更愿意将它放在Student班级本身中,或者在它填充到学生实例中时对其进行验证。

public void printStudentReport(Student student) {
  student.validate();
  // print the report....
}
于 2010-07-28T16:29:02.377 回答
0

如果您只需要 Student 的 4 个属性,那么我强烈建议您更改方法以单独获取它们。

这样,您就可以将打印方法与 Student 分离,并带来所有好处。

于 2010-07-28T16:16:06.517 回答
0

一种选择是让 Student 对象在创建时(以及在编辑期间)验证它的数据,因此当您传递 Student 对象时,您始终可以确保它们是有效的。

但这假设在程序的所有区域中,相同的验证约束将应用于 Student 对象,因此可能不是一个选项。

于 2010-07-28T16:18:03.407 回答
0

半人口的对象是很常见的。特别是如果您无法控制填充对象的数据源。我说只验证 printStudentReport() 所需的 Student 字段就可以了。我经常编写类似的报告生成方法,这些方法根据必要的数据进行验证,但如果对象存在,则会提供来自对象的任何额外数据。

于 2010-07-28T16:21:02.200 回答
0

您也可以尝试接口方法,而不是传递学生对象,而是传递接口。这意味着您可以拥有仅实现对象的该部分的学生对象。

public void printStudentReport(MyInterface student)

然后接口可以包含一个验证方法

于 2010-07-28T16:21:11.967 回答
0

我想到的一个问题是逻辑是否真的是报告逻辑或学生逻辑。在报告中,您可以编码:

  thing = (student.getX() + student.getY() ) * student.getZ();

要不就

  thing = student.getThing();

我的看法是,可能有些东西属于学生。

所以我们得到这样的情况,我们无法计算事物,因为某些 X、Y 或 Z 没有正确初始化。所以调用 getThing() 可能会抛出异常,但这感觉很奇怪。为什么一个对象应该提供一些 getThing() 能力,但又不能做到这一点?

在我看来,您的 Student 课程需要重构。学生可以执行一组核心功能,它们足以生成某些报告。因此,您可以说 IRegistered 接口和更丰富的 IActiveStudent 接口。您的报表类需要 IRegistered,而其他类需要 IActiveStudent。

各种 Student 对象在其一生中会改变它们的能力,就像毛毛虫变成飞蛾一样。您在毛毛虫上没有 fly() 方法,因此您不需要在所有鳞翅目类上使用 canYouFlyYet() 方法。

于 2010-07-28T16:26:00.743 回答