实体合法性校验

13-05-23 Evil
    

初学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()) { 
<p>[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;
	}
<p>

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

    

banq
2013-05-23 16:34

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

Evil
2013-05-24 10:21

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修改过]

banq
2013-05-24 12:18

2013-05-24 10:21 "@Evil

"的内容

我感觉这样会显得很累赘,还是说我不在setter里校验,而是在业务方面里面调用校验方法如下 ...

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

http://www.jdon.com/45378