简体   繁体   English

Java对象和内部值

[英]Java Objects and internal values

I am doing some diving into the object oriented world and trying to apply the principles of how the authors of the book Clean Code think a rich object should be constructed. 我正在深入研究面向对象的世界,并尝试应用“清洁代码”一书的作者认为应该构造一个丰富对象的原则。

However, I have run into a somewhat philosophical problem now and I am not too sure about how to deal with representation of an object. 但是,我现在遇到了一个哲学上的问题,我不太确定如何处理对象的表示形式。

In the book Clean Code you can read that a rich object should only expose behaviors and never its internal variables. 在“清理代码”一书中,您可以读到一个丰富的对象应该只暴露行为,而不应该暴露其内部变量。 This statement has other sources as well. 该声明还有其他来源。

But if you only expose behaviors, how do you then show a representation of the object in a GUI, if you can't reach the values of the internal variables? 但是,如果您仅公开行为,那么如果无法获得内部变量的值,那么如何在GUI中显示对象的表示形式?

Example: 例:

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;
    }

}

I might have a method on my Todo-aggregate root that returns a list of all new Todo's public List<Todo> listAllNewTodos(){} . 我的Todo聚合根目录上可能有一个方法,该方法返回所有新Todo的public List<Todo> listAllNewTodos(){} All the Todo's in the list have id's that represents the object. 列表中的所有Todo都有代表对象的ID。 But how do I make a representation of the id's if an object is only allowed to expose behaviors? 但是,如果只允许对象公开行为,我该如何表示ID?

EDIT: Right after posting this question I got a revelation. 编辑:发布此问题后,我得到了启示。 The book Clean Code also talks about that there is another type of structure in OOP. 清洁代码一书还谈到OOP中还有另一种类型的结构。 Not only objects with behaviors, but also data structures. 不仅有行为的对象,而且还有数据结构。 In this case I should probably view the Todo-class/instances as objects and the TodoID-instances as data structures that exposes its internal variables. 在这种情况下,我应该将Todo-class / instances视为对象,将TodoID-instances视为公开其内部变量的数据结构。 And thanks to that I CAN represent the Todo, with the TodoID-variables, in a GUI. 并感谢我可以在GUI中使用TodoID变量表示Todo。

You are doing it right, you should use Getters and Setters to reach the internal variables 您做对了,应该使用Getter和Setter来访问内部变量

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

You may also want to look into property change events. 您可能还想研究属性更改事件。 Using this mechanism your UI doesn't have to read the values, they are sent to the UI by the object whenever they change. 使用这种机制,您的UI不必读取值,只要值发生更改,对象就会将它们发送到UI。

Not all class variables might be "internal variables". 并非所有的类变量都可能是“内部变量”。 You can consider a variable internal if it is used by some behavior in your class but not needed by the consumers of your class. 如果类中的某些行为使用了该变量,但类的使用者却不需要它,则可以考虑使用该变量。

In your example, suppose that, you need to keep total time for each ToDo item and users can start a task multiple times. 在您的示例中,假设您需要保留每个ToDo项目的总时间,并且用户可以多次启动任务。 Then, you would need to declare an internal variable: 然后,您需要声明一个内部变量:

private Date latestStartTime;

Clearly, this variable should be used by startWorking and pause methods (which I didn't include) but will not be provided to calling methods. 显然,此变量应由startWorking和pause方法(我未包括)使用,但不会提供给调用方法。 For other fields, you can provide getter methods (and setter methods when your fields are not final) as @Gynnad has recommended. 对于其他字段,您可以按照@Gynnad的建议提供getter方法(当字段不是最终字段时,则提供setter方法)。 You can use them in UI. 您可以在用户界面中使用它们。

There might be other (and better) solutions, such as the one you mentioned in your edit. 可能还有其他(更好的)解决方案,例如您在编辑中提到的解决方案。 Just remember, these are all heuristics to create better code, not hard rules. 请记住,这些都是创建更好的代码的试探法,而不是硬性规则。

Have you taken a look at CQRS ? 您看过CQRS吗?

You would split up the tasks the user can do and the information he needs on a screen: 您将在屏幕上拆分用户可以执行的任务和他需要的信息:

When a user wants to do something, you don't need to have internal state: 当用户想要做某事时,您不需要具有内部状态:

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);
    }
}

and when you want to get query for information, you can create a separate layer: 当您要查询信息时,可以创建一个单独的层:

public class UnfinishedTodo
{
    public String getTitle()
    {
    }

    public TodoId getId()
    {
    }

    public String getCreatedBy()
    {
    }
}

(My Java is getting a bit rusty) (我的Java有点生锈了)

Here it will be possible (I don't know if it is wanted) to have a User domain object in your Todo, but still have a String back to the UI. 在这里,有可能(我不知道是否需要)在您的Todo中有一个User域对象,但仍然有一个String返回到UI。

In the book Clean Code you can read that a rich object should only expose behaviors and never its internal variables. 在“清理代码”一书中,您可以读到一个丰富的对象应该只暴露行为,而不应该暴露其内部变量。 This statement has other sources as well. 该声明还有其他来源。

But if you only expose behaviors, how do you then show a representation of the object in a GUI, if you can't reach the values of the internal variables? 但是,如果您仅公开行为,那么如果无法获得内部变量的值,那么如何在GUI中显示对象的表示形式?

This is because that the rich objects in the book Clean code are not designed for displaying in GUI, but for protecting invariants. 这是因为“清理代码”一书中的丰富对象不是为在GUI中显示而是为了保护不变量而设计的。 In your case, the business rule is not very complex and the TODO class is also responsible for query requirements, so it's fine to have some getter methods for now. 在您的情况下,业务规则不是很复杂,并且TODO类还负责查询需求,因此现在可以使用一些getter方法。

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

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