实体合法性校验

初学DDD,对一些基本问题不清楚
对于实体合法性校验,校验方法是在实体里实现。但是在何处调用呢?
是由服务层业务逻辑主动调用还是由持久层主动调用?
或者通过事件触发进行被动调用(如在实体的setter方法里触发事件或是其他可能的地方触发)



public class Service{
public Service(IDao dao) {//可以依赖注入
super();
this.dao = dao;
}
IDao dao = null;
/**
* CRUD作为业务逻辑
*/

/***************************************************************/
public void insertCustomer(Customer2 customer) throws Exception {
if (customer.isValid()) {
[u][b]调用合法性验证是放在Service 的insertCustomer里?还是放在Dao的insertCustomer[/b]/u]
dao.insertCustomer(customer);
} else {
throw new BusinessException2(
"customer实体无效");
}
}
}


public class Customer2 implements IEntityValidate {
private long id;
private String name = null;
private List<Order> orders = null;
@Override
public boolean isValid() {
if (getName() == null) {
return false;
}
// .....
Iterator iter = orders.iterator();
while (iter.hasNext()) {
Order o = (Order) iter.next();
if (!o.isValid()){
return false;
}
}
return true;
}

[该贴被Evil于2013-05-23 10:57修改过]

就inserCustomer这个业务来看,应该是创建客户对象,那么校验应该是在这个客户对象的构造函数中。

2013-05-23 16:34 "@banq "的内容
就inserCustomer这个业务来看,应该是创建客户对象,那么校验应该是在这个客户对象的构造函数中。 ...

嗯,就是个新增customer的业务,不知道我这样子理解大侠您的意思是否正确,如果我要新增一个客户,要求客户必须要能提供name和email,那么就必须为Customer对象新增一个构造函数如下:
Customer(String name, String email){
this.name = name ;
this.email = email;
if(!this.isValid()){//在isValid中验证name和email是否合法
throw new BusinessException("不合法custommer对象");
}
}

考虑一下场景:如果通过以上构造方法新增了一个合法customer对象,但是customer却说要修改email地址,那么我必须得为customer对象的emai属性定义一个setter方法如下吗?

public void setEmail(String email){
String oldEmail = this.email;
this.email = email;
if(!this.isValid()){//在isValid中验证name和email是否合法
this.email=oldEmail;
throw new BusinessException("不合法custommer对象");
}
}
这时如果customer还有其他的一些属性如telephome,qq,那么我必须得为每个属性定义一个类似上面的setter方法吗?我感觉这样会显得很累赘,还是说我不在setter里校验,而是在业务方面里面调用校验方法如下:
public void updateCustomer(String id,String email,String telephone,String qq ){
Customer c = dao.reLoadCustomer(id);
String oldEmail = c.getEmai();
String oldTel = c.getTelephone();
String oldQq = c.getQq();
c.setEmail(email);
c.setTelephone(telephonte);
c.setQq(qq);
if(!c.isValid()){ //调用校验方法
c.setEmail(oldEmail);
c.setTelephone(oldTel);
c.setQq(oldQq);
throw new BusinessException(“不合法对象”);
}
}
[该贴被Evil于2013-05-24 10:59修改过]

2013-05-24 10:21 "@Evil
"的内容
我感觉这样会显得很累赘,还是说我不在setter里校验,而是在业务方面里面调用校验方法如下 ...

应该在Customer中实现这些行为,这些验证行为都属于维护Customer对象自身逻辑一致性的方法,参考这个贴一直强调领域模型必须要有自己的行为,不能分离到其他地方:
http://www.jdon.com/45378