繁体   English   中英

Java对象和内部值

[英]Java Objects and internal values

我正在深入研究面向对象的世界,并尝试应用“清洁代码”一书的作者认为应该构造一个丰富对象的原则。

但是,我现在遇到了一个哲学上的问题,我不太确定如何处理对象的表示形式。

在“清理代码”一书中,您可以读到一个丰富的对象应该只暴露行为,而不应该暴露其内部变量。 该声明还有其他来源。

但是,如果您仅公开行为,那么如果无法获得内部变量的值,那么如何在GUI中显示对象的表示形式?

例:

public class Todo {

    private final TodoID id;
    private final String createdBy;
    private final String currentOwner;
    private final String description;
    private final Status status;

    private Todo(String createdBy, DateTime creationDate, String description, Status status, String todoName) {
        this.id = new TodoID(creationDate, todoName);
        this.createdBy = createdBy;
                this.currentOwner = createdBy;
        this.description = description;
        this.status = status;

    }

    public void startWorking(String name){
        if(Status.IN_PROGRESS > this.status){
        // Set status to IN_PROGRESS
        // Set current owner to name    
        } else {
          throw new RuntimeException(this.currentOwner + " has already started working on this task or it might be finished already.");
    }

    public static TodoID create(TodoValues values) {
        Todo todo = new Todo(values.createdBy, 
                             values.creationDate, 
                             values.description, 
                             values.status, 
                             values.todoName);
        // Operations to save the Todo-instance in a database
        return todo.id;
    }

}

我的Todo聚合根目录上可能有一个方法,该方法返回所有新Todo的public List<Todo> listAllNewTodos(){} 列表中的所有Todo都有代表对象的ID。 但是,如果只允许对象公开行为,我该如何表示ID?

编辑:发布此问题后,我得到了启示。 清洁代码一书还谈到OOP中还有另一种类型的结构。 不仅有行为的对象,而且还有数据结构。 在这种情况下,我应该将Todo-class / instances视为对象,将TodoID-instances视为公开其内部变量的数据结构。 并感谢我可以在GUI中使用TodoID变量表示Todo。

您做对了,应该使用Getter和Setter来访问内部变量

参见http://docs.oracle.com/javaee/6/tutorial/doc/gjbbp.html

您可能还想研究属性更改事件。 使用这种机制,您的UI不必读取值,只要值发生更改,对象就会将它们发送到UI。

并非所有的类变量都可能是“内部变量”。 如果类中的某些行为使用了该变量,但类的使用者却不需要它,则可以考虑使用该变量。

在您的示例中,假设您需要保留每个ToDo项目的总时间,并且用户可以多次启动任务。 然后,您需要声明一个内部变量:

private Date latestStartTime;

显然,此变量应由startWorking和pause方法(我未包括)使用,但不会提供给调用方法。 对于其他字段,您可以按照@Gynnad的建议提供getter方法(当字段不是最终字段时,则提供setter方法)。 您可以在用户界面中使用它们。

可能还有其他(更好的)解决方案,例如您在编辑中提到的解决方案。 请记住,这些都是创建更好的代码的试探法,而不是硬性规则。

您看过CQRS吗?

您将在屏幕上拆分用户可以执行的任务和他需要的信息:

当用户想要做某事时,您不需要具有内部状态:

public class StartWorkingOnTodoCommandHandler : CommandHandler<StartWorkingOnTodoCommand>
{
    public void handle(StartWorkingOnTodoCommand command)
    {
        Todo todo = session.get<Todo>(command.getId());
        User user = session.get<User>(command.getUserId());
        todo.startWorking(user);
    }
}

当您要查询信息时,可以创建一个单独的层:

public class UnfinishedTodo
{
    public String getTitle()
    {
    }

    public TodoId getId()
    {
    }

    public String getCreatedBy()
    {
    }
}

(我的Java有点生锈了)

在这里,有可能(我不知道是否需要)在您的Todo中有一个User域对象,但仍然有一个String返回到UI。

在“清理代码”一书中,您可以读到一个丰富的对象应该只暴露行为,而不应该暴露其内部变量。 该声明还有其他来源。

但是,如果您仅公开行为,那么如果无法获得内部变量的值,那么如何在GUI中显示对象的表示形式?

这是因为“清理代码”一书中的丰富对象不是为在GUI中显示而是为了保护不变量而设计的。 在您的情况下,业务规则不是很复杂,并且TODO类还负责查询需求,因此现在可以使用一些getter方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM