关于在对象中包含参数时验证方法参数的最佳实践,我有一个问题。例如,如果您有:
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和主要的逻辑。所以,那些是必需的。所有其他学生的getter不必填充。可以先验证Student对象,然后再用我需要的四种方法吗?我觉得这有点误导,因为我将此Student对象传递给此方法,但并非所有字段都是必需的,因此它实际上是一个半填充对象被发送到此方法。我觉得很奇怪。
答案 0 :(得分:2)
如果必须必须填充某些属性才能使Student有效,则应考虑使用所需参数定义非默认构造函数,并从类中删除任何默认构造函数(如果需要) ,验证getter中的属性值)。这可确保只能创建有效的Student对象。
如果其他属性对于学生来说真的是可选的,那对我来说看起来完全没问题。当然,您需要仔细考虑用例并仔细分析域模型,以确定哪些参数是必需的,哪些是可选的。
答案 1 :(得分:1)
考虑一下您正在创建的概念:学生报告。该方法仅使用一组学生数据并不重要,因为这些是您报告的当前要求。也许他们将来会改变。也许他们不会。但它似乎是正确的设计,因为它更易于改变。
现在验证比较棘手。报告是否需要特殊的验证,与学生的正常验证不同?如果是这种情况,那么请务必在报告中对其进行验证:
public void printStudentReport(Student student) {
validateStudent(student);
// print the report....
}
但是如果验证对于一组客户端(可能是printStudentReport
和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....
}
答案 2 :(得分:0)
如果你只需要4个来自学生的属性,那么我强烈建议你改变你的方法来单独学习它们。
通过这种方式,您可以将您的打印方法与学生分开,并带来所有带来的好处。
答案 3 :(得分:0)
一个选项是让Student对象验证它的数据创建(以及编辑期间),因此当您传递Student对象时,您始终可以确定它们是有效的。
但是有一个假设是,在程序的所有区域中,相同的验证约束将适用于Student对象,因此可能不是一个选项。
答案 4 :(得分:0)
人口稀少的物体很常见。特别是如果您无法控制填充对象的数据源。我说只需要验证printStudentReport()所需的Student字段就可以了。我经常编写类似的报告生成方法,这些方法根据必要的数据进行验证,但如果存在,则会提供来自对象的任何额外数据。
答案 5 :(得分:0)
你也可以尝试接口方法,而不是传递学生对象,你传递一个接口。这意味着您可以拥有仅实现该对象的该部分的学生对象。
public void printStudentReport(MyInterface student)
接口可以包含验证方法
答案 6 :(得分:0)
我遇到的一个问题是逻辑是否真的是报告逻辑或学生逻辑。在报告中,您可以编码:
thing = (student.getX() + student.getY() ) * student.getZ();
或只是
thing = student.getThing();
我认为可能有些东西属于学生。
那么我们得到的情况是,我们无法计算事物,因为某些X,Y或Z未正确初始化。因此调用getThing()可能会抛出异常,但这感觉很奇怪。为什么一个对象提供了一些getThing()功能但是却无法做到呢?
在我看来,您的学生课程需要重构。学生可以执行一系列核心功能,并且足以允许生成某些报告。因此,您可以说IRegistered接口和更丰富的IActiveStudent接口。您的报告类需要IRegistered,其他类需要IActiveStudent。
各种学生对象在其一生中改变了他们的能力,就像Caterpiller变成了飞蛾。你没有在caterpiller上使用fly()方法,因此你不需要在所有lepidoptra类上使用canYouFlyYet()方法。