业务规则 - 他们在OOP中的位置?

Jay*_*Jay 3 java oop validation business-logic

我有一节课:时间表.

public class Schedule {

private int locationNum;
private int cost;
private String costReason; 
private Date weekOfChange;
private Date dayOfChange;
private String changeReason; 

// and all those getters and setters

public Schedule(int locationNum, int cost, String costReason, Date weekOfChange, Date dayOfChange, String changeReason) throws ApplicationException {
//change is all or nothing - all attributes are present or none
if((weekOfChange!=null && dayOfChange!=null && changeReason!=null) || (weekOfChange==null  && dayOfChange == null && changeReason == null))  {
this.weekOfChange = weekOfChange;
this.dayOfChange = dayOfChange;
this.changeReason = changeReason;
}
else { throw new ApplicationException();}
//similary another if block to ensure that if cost is specified 
//then there exists the corresponding reason code for it.
}
}
Run Code Online (Sandbox Code Playgroud)

到目前为止,我喜欢我的Schedule课程.但是,我没有完成检查,我将不得不做一些其他检查:

  • locationNum是数据库中的有效商店编号.
  • 是changeReason文本数据库中6个不同的changeReason代码之一.
  • 等等....

通常情况下,我不会在Schedule类中写这些,显然,我不能从这个类中调用DAO.因此,我将拥有一个业务层和某种验证器类,接受一个类型为Schedule的对象,并按顺序执行一堆数据库验证并收集显示/任何错误.

现在,这是我的问题:

  1. 如果您将Schedule视为POJO并认为对象不负责验证自身 - 我必须将构造函数中的所有代码移动到业务层的验证器类.但是,如果我这样做,是不是安排贫血?这是他们所谓的违反单一责任原则吗?
  2. 让我假设我将构造函数中的代码移动到业务层类,以便各种验证现在都在我的业务层中.让我们假设有人在我的数据存储区中将dayOfChange更改为NULL,现在我正在从我的数据库中加载对象.现在,有了这种对象,我的应用程序可以破解,不是吗?因为我会编写代码,假设验证规则得到满足.我想我的问题变得令人困惑,但我想说的是,在这种情况下,我宁愿在构造函数中完成这些检查,以确保Schedule类隐藏的数据的完整性.
  3. 通常怎么做?什么是最佳做法?

感谢您参与此讨论.

rus*_*ldb 5

如果你真的拥有"所有那些getter setter",那么你需要比构造函数更好地验证你的类.如果你的类的不变量是所有weekOfChange,dayOfChange和changeReason必须为null或者不是所有都必须不为null,那么你的setter很快就会把你的类置于无效状态.你的意思是拥有制定者还是你的意思是你的阶级是不可改变的?

在担心验证之前,应该对你的班级进行分析.查看给定状态的所有有效状态和不变量.然后,您将了解您的类是否应该是可变的或不可变的.如果你有相互依赖的共变量(比如weekOfChange,dayOfChannge和changeReason),将它们打包到自己的类中并使用Schedule类中的组合是有意义的.这会将关于这些事物字段的"规则"放在一个地方并简化时间表.

与其他合作领域相同(如成本和成本原因).然后,Schedule由自我验证类组成.如果这两者都是不可变的,并且Schedule也是不可变的,那么你的自我就更容易了.

所以,回答你的问题:一个类定义它的状态和不变量更好,并且在可行的情况下只向其合作者公开最小值.附表的内部状态的责任应该依赖于附表,并且只需稍加设计就可以相对容易地进行.

所以你有了

    class Schedule {
         private Change change;
         private Cost cost;
         private Location location;

        public Schedule(Location location, Cost cost, Change change) {
           this.change = change;
           this.cost = cost;
           this.location = location;
        }
}
Run Code Online (Sandbox Code Playgroud)

和colloborators一样

public class Change {
    private Date weekOfChange; //shoudln't these two fields be one, a date is a date after all??
    private Date dayOfChange; //shoudln't these two fields be one??
    private String changeReason; 

    public Change(Date weekOfChange Date dayOfChange, String changeReason) {
      this.weekOfChange = weekOfChange;
      ...etc.
    } 
}
Run Code Online (Sandbox Code Playgroud)

虽然我强烈建议您通过防御性复制客户端代码传递的任何可变值来保护您的类不变量.