为了账号安全,请及时绑定邮箱和手机立即绑定

在 Java 中放置 Comprobations 的位置?

在 Java 中放置 Comprobations 的位置?

慕桂英3389331 2021-12-22 16:04:11
在创建必须验证条件的对象时,我一遍又一遍地提出了这个问题。检查应该在尝试创建对象之前还是在对象本身的构造函数中进行?为了更好地说明它,这里有一个例子:假设我们有一个学生经理,一位教授,他将学生对象添加到他们的列表中。创建新的学生对象时,我们必须检查他的名字是否最多 20 个字符。class Professor{    LinkedList<Student> studentsList;    Professor(){        studentsList = new LinkedList<Student>();    }    public Student addStudent(String studentName){        // Place 1        if (studentName.length <= 20)            studentList.add(new Student(studentName));        else             // Do another thing    }}class Student {    String name;    Student(String studentName){        // Place 2        if (studentName.length <= 20)            name = studentName);        else            // Don't create the object and throw exception     }}所以基本上我的问题是,在尝试创建学生之前,应该在“地点 1”中进行检查,还是在学生的构造函数中的“地点 2”中进行检查。
查看完整描述

2 回答

?
慕婉清6462132

TA贡献1804条经验 获得超2个赞

对象为自己负责

通常在面向对象编程 (OOP) 中,我们希望对象对自己负责。应该在内部处理有关其内部状态完整性的业务规则(或委托给构建者——见下文)。这个想法是 OOP 中正式称为封装的一部分。


所以在你的例子中,Professor班级不应该担心Student班级的规则,比如学生姓名的长度。该Student级应执行其自身的完整性。我们希望这些完整性规则的逻辑位于一个地方,而不是分散在整个应用程序中。


事实上,Professor类不应该实例化Student对象。在您的示例中暗示,必须有其他方将学生分配给教授。也许是一个Tutorial负责跟踪由教授监督的几个学生的作业和进度的对象。这Tutorial应该是实例化Student对象,或者传递Student从其他来源(例如数据库服务对象)接收的对象。


当Student对象到达 时Professor,它们应该是有效的。本Professor类不应该是什么让一个被关注Student的有效与否。该Professor只应是什么让一个有关Professor有效。


class Professor{

    List< Student > students;

    …

    public void addStudent( Student student ){

        Objects.requireNonNull( student , "Received NULL rather than a Student object. Message # 68a0ff63-8379-4e4c-850f-e4e06bd8378a." ) ;  // Throw an exception if passed a null object.

        Objects.requireNonNull( this.students , "Collection of Student objects is NULL. Message # c22d7b22-b450-4122-a4d6-61f92129569a." ) ;  // Throw an exception if the `students` list is not established.

        this.students.add( student ) ;

    }

}

除了对象对自己负责的想法之外Professor,不实例化Student对象的另一个原因是方便测试。如果Student对象来自某个其他来源,则该来源可以使用尚未完成、禁用某些功能(例如数据库访问)或被设计用于测试场景的虚假数据替代的类或接口提供虚假对象Student。


建造者模式

如果您有多个需要验证才能实例化新对象的属性,您可能需要使用Builder 模式。您定义了一个额外的类,例如,StudentBuilder它具有为学生所需的每个部分的方法。


通常,这些方法都返回相同的StudentBuilder对象以方便调用链。


不同的人对建筑商有不同的风格。一种方法是提供一种有效性检查方法,或者一种提供阻止构建所需对象的问题列表的方法。


有些人使用 likewith而不是 accessor 方法set来表明,虽然我们暂时在构建器上设置一个属性,但真正的意图是在另一个类的对象上设置一个属性。


StudentBuilder sb = new StudentBuilder().withFirstName( "Alice" ).withLastName( "Coleman" ).withEmail( "x@y.com" );

if( sb.isValid() ) {

    Student s = sb.build() ;

    …

}


查看完整回答
反对 回复 2021-12-22
?
动漫人物

TA贡献1815条经验 获得超10个赞

在简单的程序中,没有太大关系。在复杂的应用中,有许多因素决定了这一点:

  • 在某些情况下,具有无效值的对象是否仍然存在?(即使它们包含无效值,它们是否有意义?)

  • 验证很贵吗?(是否需要计算、网络连接或数据库操作?)

  • 可以验证吗?(我们是否已经拥有验证所需的所有信息?)

  • 验证是否有自己的阶段,在这个阶段与其他对象一起验证或针对其他对象进行验证?

  • 是否有现有的约定或要求?

等等...

因此,大多数情况下,这将由架构或设计约束或与更大应用程序相关的其他因素决定。在非常小的程序中,您可能找不到任何决定验证最佳位置的因素。

在上面显示的示例对象创建代码中,您通常不会默默地跳过超过 20 个字符的值,但在这种情况下通常会抛出异常。如果这是数据处理而不是有意过滤短于 20 个字符的记录,您不想默默地忽略不合适的记录。(想象一下,谁会手动检查为什么在 1000 条记录的集合中,有 5 条记录丢失了,并且没有错误消息表明出了什么问题。所以你可能会看到,上述方法无论如何都没有实际使用。)


查看完整回答
反对 回复 2021-12-22
  • 2 回答
  • 0 关注
  • 130 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信