DDD参数验证方式

bingyang 13-06-04
    

banq 你好,请问在DDD模型中准确说不管DDD这种模式还是传统的领域模式,参数(输入参数可能是个值对象,引用对象)验证,都是必须的,(我知道的几种方式,可能还有其他验证方式,请指教),大致做法如下:
1,在方法前部分写 if (xx >0 || yy<0 || jj.Name==null) throw ........
2,把 if (xx >0 || yy<0 || jj.Name==null) throw ........ 这种写法封装成一个验证小函数void Verifyxxx(....)或者 boo Verifyxxx(....),在主函数前调用这个 Verifyxxx 函数
3,对于多对象验证用访问者模式验证
4,用AOP去实现验证,

请问,有没有一种比较优雅的验证方式,是的方法满足 职责单一或者看起来比较舒服 ?

    

jdon007
2013-06-05 01:06

我是这样的写的,未必合理,仅供参考和讨论:

一、在服务端,定义两个异常类:XxxException, XxxRuntimeException (Xxx一般为项目名的简称),且处理参数错误的原则是fail-fast,有错就抛出。

1、 在处理请求的类中(业务场景),提供一个校验方法,抛出checked exception和unchecked exception

/** 验证所有的请求参数,fail-fast */
public void validate() throws XxxException {
// 调用验证某个参数的方法, 比如判断是否携带了令牌,令牌是否合法
// 将任何单个参数检验抛出的异常,比如日期格式错误,空指针异常等转化为XxxExcpetion
// 将所有内部可能出现的异常,比如连接池资源耗尽、SQL异常等,转化为XxxRuntimeException
// 具体参数校验的实现,放在单独的一个类中,可以通过继承来复用公共参数的校验和通用的校验方法。
}

2、在servlet中,捕获两种异常,并打印不同级别的日志和返回不同的响应

try {
processor.validate();
// 返回正常处理的结果
} catch(XxxException e){
// 打印警告日志,说明客户端参数出错了
// 返回400错误的提示
} catch(XxxRuntimeException e) {
// 打印错误日志,说明服务端内部出错了
// 返回500错误的提示
}


二、在应用端,比如android应用,会将参数校验放在(业务对象)中,业务对象所有的字段都是public,没有getter和setter方法。
应用端的校验之所以放在业务对象中,是因为某个具体的应用相对于服务,其参数校验的语境相对单一。


class BusinessObject {
public boolean isValid() {

}

public void persist() {
// 持久化
}
}

在调用的地方

if (bo.isValid()) {
bo.persist();
} else {
// 提示用户哪里出错了
}

bingyang
2013-06-05 09:37

2013-06-05 01:06 "@jdon007
"的内容
二、在应用端,比如android应用,会将参数校验放在(业务对象)中,业务对象所有的字段都是public,没有getter和setter方法。
应用端的校验之所以放在业务对象中,是因为某个具体的应用相对于服务,其参数校验的语境相对单一。

...

这种方式,用起来比较简洁,把验证和方法真正逻辑分开,对于这个验证可以让调度者去使用,不知道bang 对这个问题怎么看。

banq
2013-06-05 10:02

验证也属于一种规格模式,检查是否符合我们要求的特定规格。

用一个Specification模式接口去实现,Specification接口中有一个isSatisfied方法来判断是否符合。

bingyang
2013-06-05 13:29

2013-06-05 10:02 "@banq
"的内容
用一个Specification模式接口去实现,Specification接口中有一个isSatisfied方法来判断是否符合 ...


Specification 对于实体验证很方便,如果一个方法零散的参数比方说,void Insert(string name,int size,IList<string> list)这种情况对name,size,list的验证,该如何做才会是程序看起来比较美观,现在一般多数做法在 Insert前部分 if name 为空,if size <=0 ......,规格模式是否同样适用这种情况?

2Go 1 2 下一页