[英]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来访问内部变量
您可能还想研究属性更改事件。 使用这种机制,您的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.