验证能有多优雅

背景

我们都知道ENTLIBVAB,也知道如果不在乎大量的XML损视力的话,VAB非常非常优雅,但是在不大的项目中,很多情况下我们依旧自己写着验证的代码

所以在这篇文章中,打算展示一下学习.NET一年半以来,写验证代码的各个阶段,并展示一种个人觉得比较优雅的验证代码的写法,如果大家有别的方案,也请提出来与大家分享哦

 

第一阶段--强写

所谓强写,自然就是强行地写了,从知道需要参数验证(很惭愧,学了.NET整整1个月才知道这事)开始,好长一段时间都在强写着验证的代码,也不记得什么时候开始觉得这么写不舒服,什么时候开始换成了别的方法,总之早期的代码中充斥着这样的片断

public void SomeMethod(string s)
{
    
if (s == null)
    {
        
throw new ArgumentNullException("s");
    }
    
if (s.Length == 0)
    {
        
throw new ArgumentException("s cannot be empty ");
    }
}

最终的结果是,一个.cs文件中有整整1/2的内容是这些可爱的if, throw和花括号

这个方案不用评价了,我自己会把他贬得很惨,再怎么说曾经也是为了这些东西写到手抽筋啊,痛苦啊

 

 

第二阶段--Guard类

 

嗯,MS很多项目中都有这个Guard类,把一些主要的验证的方法写在了类中,方法直接抛出异常,大致是这样的

public class Guard
{
    
public void NotNull(object value, string argName)
    {
        
if (value == null)
        {
            
throw new ArgumentNullException(argName);
        }
    }

    
//其他验证方法
}

 

调用的方法大致是这样的

public void SomeMethod(string s)
{
    Guard.NotNull(s, 
"s");
    Guard.NotEmpty(s, 
"s");
    Guard.ShorterThan(s, 
10"s");
    Guard.LongerThan(s, 
3"s");
    
//其他逻辑
}

看起来清爽多了,再也没有if, throw和美丽的花括号了,可喜可贺~可喜可贺~

 

但是!并不是一切都这么美好的!每一次调用方法都需要值一个字符串以表示参数的名称,这里写了4”s”,当然你会说4”s”没什么,但是写4”user.Name”再写6”user.CreationDate”呢……

什么感觉?手酸?NO~NO~这不是最重要的,重要的是写字符串的时候VS没有自动提示啊!你敢保证写10个不错一个字母么?

其实对这个阶段还是非常有感情的,怎么说都是对“把类似功能合在一起”的理念的尝试呢

 

第三阶段--扩展方法

然后,然后就有了C# 3.0,就有了扩展方法,然后Guard中的方法的第一个参数都加了一个this,调用就成了这样

public void SomeMethod(string s)
{
    s.NotNull(
"s");
    s.NotEmpty(
"s");
    s.ShorterThan(
10"s");
    s.LongerThan(
3"s");
    
//其他逻辑
}

基本我不认可这是一个阶段呢,只是用了点语法糖而已,最重要的字符串多次输入参数名称的问题根本没有得到解决,少打几个字会很快乐么……作为一个标准的程序员,我想说:NO!

 

 

第四阶段--不知道怎么说

 

就是现在在用的方法啦,刚刚“发明”出来的哦,个人自我感觉良好,但实在不知道怎么从设计上去解释,就先写一下实现方案吧

很久很久以前,有一个孤独的类,句叫ValidationHelper<T>,他的任务就是惩治世上所有不听话的参数,根据见过他的变量们的描述,他是长得这样的

 

Code

 

 

因为ValidationHelper<T>可以保存住参数的值和参数的名称,因此就一下子地解决了多次输入参数名称的问题,真不亏是大侠啊

但是,很多人都不知道,为什么功能这么少的ValidationHelper<T>可以消灭几乎所有的不规范参数,其实秘诀还在于扩展方法,通过扩展方法的联系,ValidationHelper<T>找到了很多伙伴,其实除暴安良的,是一个团队,而非一个人,下面来看看StringValidationHelper是怎么样对付不规范的string的吧

Code

好了,伙伴找到了,现在的问题是,当需要大侠帮助的时候,我们不得不使出全身的力气使用new来召唤大侠……这显然很不爽,因此又有了一扩展方法,我们称之为“工厂”

public static class Validation
{
    
public static ValidationHelper<T> InitValidation<T>(this T value, string argName)
    {
        
return new ValidationHelper<T>(value, argName);
    }
}

最后,我们是这样来打败黑暗势力的

public void SomeMethod(string s)
{
    s.InitValidation(
"s")
        .NotDefault()
        .NotEmpty()
        .ShorterThan(
10)
        .LongerThan(
3);
}

反正本人是找不到更好的方法了,还请大家指教了

posted @ 2008-09-01 21:36 Gray Zhang 阅读(2369) 评论(89)  编辑 收藏 网摘

  回复  引用  查看    
#1楼2008-09-01 21:40 | Justin      
沙发,先顶一下

好像ASP.NET还有一套验证控件吧

  回复  引用    
#2楼2008-09-01 21:43 | AstarNoLogin[未注册用户]
也顶一下~
  回复  引用  查看    
#3楼2008-09-01 21:44 | bluesky4485      
学习。
  回复  引用  查看    
#4楼2008-09-01 21:50 | 谦虚的天下      
很好,学习了!
  回复  引用  查看    
#5楼2008-09-01 22:35 | LuChaoShuai      
--引用--------------------------------------------------
Justin: 沙发,先顶一下<br><br>好像ASP.NET还有一套验证控件吧
--------------------------------------------------------
这个和验证控件没关系。

  回复  引用  查看    
#6楼[楼主]2008-09-01 22:42 | Gray Zhang      
谢谢大家的支持~这个确实和验证控件是没关系的哦,我只考虑怎么写验证才够漂亮,不会眼花不会疲劳,目标就是:让编程变得快乐!
  回复  引用  查看    
#7楼2008-09-01 22:47 | TerryLee      
其实用VAB还是挺好用的:)
  回复  引用  查看    
#8楼2008-09-01 22:48 | 水言木      
Great!
学习了!

  回复  引用  查看    
#9楼2008-09-01 22:48 | lexus      
刚一看,觉得奇怪怎么实现的类名都和我的一样,和lz的差不多http://www.cnblogs.com/lexus/archive/2008/08/23/1274729.html" target="_new">http://www.cnblogs.com/lexus/archive/2008/08/23/1274729.html
不过我在第三和第四阶段之间吧,呵呵

  回复  引用  查看    
#10楼[楼主]2008-09-01 22:48 | Gray Zhang      
@TerryLee
确实VAB很好用,有可视化配置也很方便,我不喜欢的是VAB用来验证方法的参数的时候,需要和PIAB结合用,个人不太想用AOP之类的东西呢

  回复  引用  查看    
#11楼[楼主]2008-09-01 22:49 | Gray Zhang      
@lexus
嗯,你的那个我也看过,只是静态的难保证同步问题,而我的实例化对象的缺陷是消耗资源较大,各有所长吧~

  回复  引用  查看    
#12楼2008-09-01 22:53 |       
我使用AOP的方法去验证参数,在方法上面加个attribute,里面对应了需要验证的方法。

唯一的缺点就是类必须继承ContextBoundObject,而且c#的消息机制性能比较低(虽然可以基本忽略)

  回复  引用  查看    
#13楼[楼主]2008-09-01 22:55 | Gray Zhang      
@辰
我倒是一直为了那些基本可以忽略的性能而挣扎着不用AOP呢……

  回复  引用  查看    
#14楼2008-09-01 23:46 | jillzhang      
的确很巧妙
  回复  引用  查看    
#15楼2008-09-02 00:06 | Windie Chai(笑煞天)      
wow,又学习到了!!!
  回复  引用  查看    
#16楼2008-09-02 07:43 | 拓荒者      
请教一下:
s.InitValidation("s")
.NotDefault()
.NotEmpty()
NotDefault()方法没有返回值,它后面再接着调用方法NotEmpty()是为什么呢?

  回复  引用  查看    
#17楼[楼主]2008-09-02 08:25 | Gray Zhang      
@拓荒者
呵呵,让你看出来了,昨天睡下以后才发现写错了点东西……所有的验证方法应该返回this指针才可以进行级联调用……
已经修改好了,原ValidationHelper的方法返回this指针,所有扩展方法返回传入的current指针就行了,唉出这么大的错误真失败啊

  回复  引用  查看    
#18楼[楼主]2008-09-02 08:48 | Gray Zhang      
@jillzhang
@Windie Chai(笑煞天)
谢谢支持,呵呵昨天写的有错误呢,void类型的根本不可能链式调用,现在改好了~

  回复  引用  查看    
#19楼2008-09-02 09:21 | Jerry Qian      
请问C#有current这个关键字吗.
  回复  引用  查看    
#20楼[楼主]2008-09-02 09:23 | Gray Zhang      
@Jerry Qian
没有……你看一下上面的代码,current是传入的参数名,我说得不清楚,不好意思……

  回复  引用    
#21楼2008-09-02 09:24 | XHTML[未注册用户]
很好 链式编程
  回复  引用  查看    
#22楼2008-09-02 09:24 | Jerry Qian      
原来是我看不到全部代码.
  回复  引用  查看    
#23楼[楼主]2008-09-02 09:25 | Gray Zhang      
@Jerry Qian
如果是FF的话看折叠的代码块有时会有问题,在IE下应该可以打开折叠代码块的

  回复  引用  查看    
#24楼2008-09-02 09:27 | Jerry Qian      
public ValidationHelper<T> CustomRule(Action<T, string> rule)

还有个问题啊.这个好像没有用到啊.

  回复  引用  查看    
#25楼[楼主]2008-09-02 09:29 | Gray Zhang      
@Jerry Qian
这是一个最终的扩展,不怎么用,因为只需要传一个委托进去就行,方便在临时扩展上用,比如这样写
s.InitValidation("s")
.CustomRule(str =>
{
if (str == "admin") throw new ArgumentException("cannot be admin...");
});

  回复  引用  查看    
#26楼2008-09-02 09:30 | Jerry Qian      
@Gray Zhang
明白啦,楼主真热心.谢谢!

  回复  引用  查看    
#27楼2008-09-02 09:47 | 晴空      
业务验证目前看只有XML的方案比较好,如果不用XML那么就要有另一套声明方案。
楼主的方案不错,就是扩展到业务领域的验证可能要做其他方面的工作。

  回复  引用  查看    
#28楼2008-09-02 09:50 | 戏水      
妙不可言 ~_~
  回复  引用  查看    
#29楼2008-09-02 10:56 | Peter Li      
用属性 Attributes, 兄弟!!!
  回复  引用    
#30楼2008-09-02 10:57 | 谁是验证终结者[未注册用户]
不错的思路.但是我还是不满足,

对于页面验证我的想法是最好能够用配置文件对需要配置的页面进行配置规则,就象java的struts等web框架一样,这样有好处的,以后验证有bug时可以动态修改验证规则不用再重新编译了,看来java在web开发的许多方面确实领先一步呵呵.

我还有一个问题一直解决不了,就是能否基于配置文件对页面表单验证的同时也能同步产生服务端验证,这样就很方便了,没有人喜欢客户端验证一次服务端又写重复代码验证一次.这种需求很难实现的.

再说一种比较可能能实现的需求吧:能否写服务端验证的代码后,程序运行时自动在客户端产生js验证代码.

反正我们的终极目的是只写一次验证代码产生客户端服务端两次验证的过程,最好是能基于配置文件的,目前我是实现不了,呵呵

  回复  引用  查看    
#31楼2008-09-02 10:58 | Peter Li      
用属性就好啦, 何必这么麻烦?
  回复  引用  查看    
#32楼2008-09-02 11:03 | legio      
public void SomeMethod(string s)
{
s.InitValidation("s")不是很明白这是如何实现,请高手指教,谢谢

  回复  引用    
#33楼2008-09-02 11:15 | Duron800[未注册用户]
记得看过一个老外的文章,最后的形式就是想楼主的那样:
s.XX().YY().....

  回复  引用  查看    
#34楼2008-09-02 11:20 | Old Developer      
To楼主:
个人觉得使用Exception做验证,本身不是一个特别好的设计。.Net里的Exception在使用时是不适用于这种类型的场景。所以……

  回复  引用  查看    
#35楼[楼主]2008-09-02 13:14 | Gray Zhang      
@Old Developer
那么假设一个方法是void类型,验证失败的时候要怎么办呢?什么都不执行而让调用者误以为已经正确执行反而是不好的方案吧,如果异常这也不能用那也不能用,要用哪去呢,ArgumentException和ArgumentNullException又干嘛去呢

  回复  引用  查看    
#36楼[楼主]2008-09-02 13:16 | Gray Zhang      
@谁是验证终结者
用XML配置然后动态生成相应内容这很容易实现,高动态性的验证也有VAB了,我敢说JAVA里现在还没有一个和VAB一样配置方便灵活性足够高的验证框架,只需要简单扩展下VBA来生成相应的代码即可,也非常方便
而我要做的仅仅是针对“在程序中写验证”这个前提

  回复  引用  查看    
#37楼[楼主]2008-09-02 13:17 | Gray Zhang      
@Peter Li
属性也有属性的麻烦,在参数上加6个属性的话会使方法签名很不容易阅读,同时底下写一个框架也不方便吧
此文的目标仅仅是在“用代码写验证”这个前提下,探讨一下如何做到最好

  回复  引用  查看    
#38楼[楼主]2008-09-02 13:18 | Gray Zhang      
@legio
请看最后的Validation类的扩展方法,InitValidation只是返回一个ValidationHelper<T>而已

  回复  引用  查看    
#39楼[楼主]2008-09-02 13:29 | Gray Zhang      
@谁是验证终结者
有没有兴趣一起来尝试一下呢?基本配置来规划验证规则,随后通过不同的Provider生成不同的代码,比如客户端的js,服务器端的验证等等,差不多和Linq Provider的思想一样哦

  回复  引用  查看    
#40楼2008-09-02 16:33 | Activenetwork      
@Old Developer
那么假设一个方法是void类型,验证失败的时候要怎么办呢?什么都不执行而让调用者误以为已经正确执行反而是不好的方案吧,如果异常这也不能用那也不能用,要用哪去呢,ArgumentException和ArgumentNullException又干嘛去呢

----------------------------------------------------------------
@Gray Zhang
针对参数的验证,有很多种设计思路,我不敢说哪一种是最好,但是使用异常确实是最不好的设计思路之一。
如果发生异常,那么引发或处理异常时,会使用大量的系统资源和执行时间。引发异常只是为了处理确实异常的情况,而不是为了处理可预知的事件或流控制。如果在一个逻辑体之内,我们可以把执行逻辑和验证逻辑剥离出来,而不用仰仗执行逻辑的返回参数进行业务判断,这是一个基本思路。同时在执行逻辑中,我们需要更多的使用断言(Assert)。如果方法参数无效,而应用程序需要使用有效的参数调用方法,则可以引发异常。无效的方法参数意味着出现了异常情况。相反,在你上面的例子中,由于用户输入造成的无效数据,这是可以预见的,因此如果用户输入无效,则不要引发异常。
啰啰嗦嗦说了很多,也不知道说清楚了没有,但是最明显的例子是你可以做一个关于异常的试验,看看他的开销到底有多大。
Exception是.net平台提供给我们的一个很强大的工具,但是它应该被应用在正确的地方。

  回复  引用  查看    
#41楼[楼主]2008-09-02 16:38 | Gray Zhang      
@Activenetwork
在异常的理解上,和你不是非常一致呢,我认为用户的输入才是最不可预见的因素,并且,异常应该是一种合理的通知方式,就像有位园友说的,异常是特殊的正常,如果说必须在真正不正常的时候才使用异常的话,光一个Response.Redirect就会抛一个异常,而跳转自然完全是可以预见的

  回复  引用  查看    
#42楼2008-09-02 16:46 | 坏人      
引发异常有助于编程模型的统一,我也一直徘徊在异常使用的度上,但现在更倾向于不去关注异常的性能损失了。
  回复  引用  查看    
#43楼2008-09-02 16:47 | 坏人      
谁的异常终结者的提法我很赞同,通过C#产生出JS校验框架是很棒的主意,我一直想这样做,只是一直没去实现
  回复  引用  查看    
#44楼[楼主]2008-09-02 16:49 | Gray Zhang      
异常相比返回值的一个优点是,可以更明确地说明问题,比如一个方法
bool AddUser(string username, int age);
当username或age的值无效时,应当返回false,当username与主键冲突时,也返回false,那么从返回值上是不可能看出来到底哪出了问题了
使用异常的话,可以写
void AddUser(string username, int age);
当值无效时用ArgumentException,当主键冲突时用InvalidOperationException,加上Message属性的效果,判断起来非常容易,在界面上也相应地可以给出更明确的错误信息了

  回复  引用  查看    
#45楼2008-09-02 16:49 | 坏人      
LZ的方法还是不错,VAB还没看,既然你如此看好VAB,何必再做一个?仅仅不喜欢配置文件?
  回复  引用  查看    
#46楼2008-09-02 16:50 | Activenetwork      
@Gray Zhang
^_^
很高兴能与你继续讨论。我也得以有机会把自己的思路整理清楚。
我对异常的“可预知”和“不可预知”的表述大概不太准确,所以你会有上面的疑惑,所以我尝试描述得更加准确一些。
以我个人的经验来看,需要使用异常来处理的情况,多半是一些我们通过代码无法解决的问题,例如我们需要使用的外部系统如打印机、扫描仪、甚至数据库等在底层调用内部出现错误的情况。这些情况我们在编码和运行时无法预见,也无法在代码中进行错误处理,所以需要借助异常来实现应用的用户友好性。而用户输入对我们来讲,是程序依靠自身逻辑完全可控,可以通过非异常的方式继续错误修正的情形,如果我们可以不使用异常,为什么一定要呢?仅仅是编码方便吗?换句话说,我的理解就是,除非必须使用异常的情况,我们都尽量不要使用它。

  回复  引用  查看    
#47楼[楼主]2008-09-02 16:50 | Gray Zhang      
@坏人
这会涉及到生成怎么样的js代码,比如是不是用jquery,或者错误信息在哪显示之类的,因此我的设想就是用Provider Pattern了,不知道谁有兴趣一起搞搞

  回复  引用  查看    
#48楼2008-09-02 16:50 | 坏人      
Gray Zhang,明确说明问题其实好解决,关键是异常无论在事务、远程等场景下简化编程模型的作用。
  回复  引用  查看    
#49楼[楼主]2008-09-02 16:51 | Gray Zhang      
@坏人
VAB要作方法的参数验证就得PIAB配合,相当于加了一层AOP,性能损失不比扔几个异常差多少……

  回复  引用  查看    
#50楼2008-09-02 16:51 | 坏人      
否则的话,完全可以做个泛型类把返回参数和相关的确定性信息包装一下就O了的事。
  回复  引用  查看    
#51楼2008-09-02 16:53 | 坏人      
下午有个会,现在思路不太灵活,回头空了聊下,只是如果用PROVIDER的哈,这个场景随便搞个容器恐怕更简单。
  回复  引用  查看    
#52楼[楼主]2008-09-02 16:53 | Gray Zhang      
@Activenetwork
关于这一点,即使.NET框架本身也是非常含糊的,没有给我们开发者指明一条道路,比如Type.GetType方法,可以传一个throwOnError参数指定是不是通过异常的方式通知,再比如Membership.CreateUser的最多参数的重载方法,此方法就没用异常而是用了一个枚举来表示错误,再比如Membership.CreateUser的其他重载,就用了异常来通知错误……这也导致我们开发者不知道什么时候应该用异常,什么时候应该避免了

  回复  引用  查看    
#53楼2008-09-02 16:54 | Activenetwork      
@Gray Zhang
其实没有必要使用返回值做验证方式,你的验证类写得很好啊,为什么不使用独立的验证函数去做参数验证,然后使用逻辑函数做流程处理呢?

  回复  引用  查看    
#54楼2008-09-02 16:54 | 坏人      
PIAB看起来很熟,不记得是什么了,AOP的话,貌似现在的织入方式性能损失并不大,不用太计较,伸缩性以及规模才是考虑的重点
  回复  引用  查看    
#55楼[楼主]2008-09-02 16:54 | Gray Zhang      
@坏人
在远程模型下,异常会很麻烦,因为异常本身是语言所特有的,不能送到web service之类中间机制中去

  回复  引用  查看    
#56楼2008-09-02 16:55 | 坏人      
不不不,远程场景下,使用异常并不复杂,而且将会保证你整个业务的连贯性
  回复  引用  查看    
#57楼2008-09-02 16:56 | 坏人      
恩,不过你如果要说异构平台,我就不说什么了,以便内部的分布,我都是同构平台,呵呵
  回复  引用  查看    
#58楼[楼主]2008-09-02 16:56 | Gray Zhang      
@Activenetwork
正常的情况下,其实一个系统中,UI层有验证,这里的验证是不会抛异常的,仅仅提示用户
到了业务层,我认为在正常情况下,所有输入来自UI层,应当是有效的,因此遇上参数无效的机会非常少,也同时说明了一个问题,业务层中如果遇上参数无效,则是用户通过其他不正当途径进行调用的,因此扔异常
我的设计是这样的,单独写参数验证的方法的话会使业务接口膨胀并在接口中存在于核心业务无关的方法,我不太喜欢

  回复  引用  查看    
#59楼[楼主]2008-09-02 16:57 | Gray Zhang      
@坏人
呵呵,前段时间拿WCF开刀,异常搞得我头疼呢

  回复  引用  查看    
#60楼2008-09-02 16:57 | 坏人      
不能多说了,还有事,很期待LZ可以做一个能够集合JS的东西出来,VAB我先看看之后再来发言
  回复  引用  查看    
#61楼2008-09-02 16:58 | 坏人      
Gray Zhang,不要把参数校验放到UI去,很麻烦很头疼很不爽。。。我以前那样干,现在几乎不敢那样干了
  回复  引用  查看    
#62楼[楼主]2008-09-02 17:00 | Gray Zhang      
@坏人
比如WEB,你不在UI放检验等于每次回发服务器检查,流量上就吃不消啊~
呵呵你先忙吧~随时欢迎讨论~

  回复  引用  查看    
#63楼2008-09-02 17:01 | Activenetwork      
--------------------------------------------------------------------
比如WEB,你不在UI放检验等于每次回发服务器检查,流量上就吃不消啊~
呵呵你先忙吧~随时欢迎讨论~
--------------------------------------------------------------------

@Gray Zhang
那是因为你混淆了client side validation和server side validation. ^_^有些东西是省不来的。

  回复  引用  查看    
#64楼[楼主]2008-09-02 17:04 | Gray Zhang      
@Activenetwork
嗯,我这里说的UI层的检验特指的就是web中用js的部分或者FORM远程环境下在客户端上的实时输入检验,个人认为这些东西是省不下来的,能省的只有WEB下比如aspx页面中的检验,这些是可以留给业务去做的,当然业务如何去处理无效参数,是用默认值,或者用异常,其实自己也不确定,比如
User GetUserByName(string name);
这个方法如果name无效我就会返回null
void AddUser(User user);
这个方法如果user中有属性无效我就比较倾向于抛出异常,异常中就可以明确说明哪一个属性有问题,更好地去提示用户

  回复  引用  查看    
#65楼2008-09-02 17:06 | 坏人      
实在忍不住,你说的是UI是指的IE端?那样更加不可,WEB开发的基本原则,不可相信request过来的任何数据
  回复  引用  查看    
#66楼2008-09-02 17:06 | 坏人      
另外,关于WCF中的异常处理,网上好象文章很多,没有你想象中那么复杂。
  回复  引用  查看    
#67楼[楼主]2008-09-02 17:07 | Gray Zhang      
@坏人
对啊,不相信request过来的数据,因此在业务层还有一次校验呢,在IE端的js检验只是为了保证“多数正常人的使用方法的情况下过来的数据是正确的”,同时也减少一些无谓的“无效数据-验证-返回提示”的流量

  回复  引用  查看    
#68楼2008-09-02 17:07 | Activenetwork      
:)
我觉得讨论已经很充分了。对彼此来说,改变他人的想法真得很难,呵呵。
Anyway I don't like exception misusage.

  回复  引用  查看    
#69楼2008-09-02 17:08 | 坏人      
通常的做法是JS先检查,提供良好体验以及节约POST动作,逻辑中再次检验,把好安全关。
  回复  引用  查看    
#70楼2008-09-02 17:09 | Activenetwork      
@坏人
I agree with you.

对了,最近没有看到你上msn呢,还在成都不?

  回复  引用  查看    
#71楼2008-09-02 17:09 | 坏人      
Activenetwork,有的时候异常也没那么臃肿,至少他可以让你自动的回滚事务,否则如何将事务之类的东西甩到AOP中去?
  回复  引用  查看    
#72楼[楼主]2008-09-02 17:10 | Gray Zhang      
@Activenetwork
不过这么一说倒是有点想法,其实完全可以把我这东西改造成用户决定是不是抛异常的嘛~开工改造去

  回复  引用  查看    
#73楼2008-09-02 17:11 | 坏人      
Activenetwork,我说看你名字有点眼熟,没细看,不好意思,还在,公司网络限制,上不了,都晚上在,呵呵
  回复  引用  查看    
#74楼2008-09-02 17:11 | Activenetwork      
@坏人
回滚事务时使用异常就是我说的不得已的情形,我的原则是能不用则不用。程序员的脑袋里一定要有概念,使用异常,数据连接,反射……都是要花钱的!!!

  回复  引用  查看    
#75楼2008-09-02 17:12 | 坏人      
其实之前我还倒腾了一个ExcuteState<T>,好象里面有Succeed,Message,ReturnValue,哈哈,现在也还在用
  回复  引用  查看    
#76楼2008-09-02 17:14 | 坏人      
@Activenetwork,这些是明白的,不过我觉得当下的观念应该有些改变,我现在比较注重代码的伸缩性以及
  回复  引用  查看    
#77楼2008-09-02 17:14 | 坏人      
更低的人力成本建造更大规模的代码,在这时候,适当的使用AOP等方法,自动化的事务,确实可以有效的降低人力提高代码规模
  回复  引用  查看    
#78楼2008-09-02 17:16 | 坏人      
数据连接则是另外个话题了,不讨论,那个话题已经是老生常谈的事了。
  回复  引用  查看    
#79楼2008-09-02 17:17 | 坏人      
而如果使用自动化的事务,很多“已知错误”的时候屏蔽异常的话,会挺麻烦,我没有想到更好的解决办法,于是我妥协了
  回复  引用  查看    
#80楼2008-09-02 17:20 | Activenetwork      
@坏人
不陪你们在这里发疯盖楼了,这些话题扯起来不会有完的。有时间msn聊。

  回复  引用  查看    
#81楼2008-09-02 17:23 | 坏人      
难得发次疯:D多理解,恩,空了聊,都先忙吧,8.
  回复  引用  查看    
#82楼[楼主]2008-09-02 17:26 | Gray Zhang      
哈哈被我改成InitValidation可以这么写了
InitValidation(value, "argName", throwOnError);
当throwOnError为true时验证失败就抛异常,为false时验证失败不抛异常,最后用.IsValid属性来看验证是否正确,当然不正确时怎么处理依旧由调用者决定了

  回复  引用    
#83楼2008-09-02 17:29 | 谁是验证终结者[未注册用户]
@Gray Zhang
xml配置文件只能单独产生客户端验证,要产生服务端验证很难的,
不写一句服务端代码还能能进行验证,除非还是用配置文件的方法,拦截点击事件的方法,好像挺复杂的,但是如果能够实现只写一次验证规则代码,然后客户端服务端都能通用那真的太妙了

  回复  引用  查看    
#84楼[楼主]2008-09-02 17:31 | Gray Zhang      
@谁是验证终结者
服务器端的代码肯定是要动态的,不能要编译才有效的,一个可行的方法是(以WEB为例),获取post的数据后对每个数据根据配置文件进行检查,当然程序员还是要写一句ValidateRequest(HttpContext.Current.Request);之类的……

  回复  引用    
#85楼2008-09-02 17:53 | 谁是验证终结者[未注册用户]
突然间找到一个很好的方法就是客户端可以和服务端共享一份正则表达式啊(通过属性绑定),如果这些正则表达式能够写在配置文件里面那就更好了(此时就是全局缓存绑定),以后验证有bug时只需修改配置文件就好了,呵呵,妙哉,简单易行啊
  回复  引用  查看    
#86楼[楼主]2008-09-02 17:56 | Gray Zhang      
@谁是验证终结者
我就是这个意思啊,所有的验证放在配置文件里,然后
1.有一个分析器将配置转为面向对象的表达形式(可能是表达式或者别的)
2.JavaScriptProvider将第1步拿下来的内容转成js并输出到html中
3.ServerSideProvider将第1步拿下来的内容分析并在用户post数据的时候进行验证
4.XxxProvider再干点别的,YyyProvider再干别的,就这样……

  回复  引用  查看    
#87楼2008-09-02 21:29 | airwolf2026      
哇...好久没有看到这样的眼前一亮的文字了.赞!
  回复  引用  查看    
#88楼2008-10-04 20:35 | Doho      
今天我又找到这篇帖子来了,发现这个验证方法确实很直观很好用,可以直接跟Enterprise Library 里的异常模块结合起来使用。
  回复  引用  查看    
#89楼2009-01-02 11:32 | stu_acer      
总体来说最后一种方案的确不错了 但是有一个问题啊 就是引用类型的时候变量本身为null时 ,压根走不到NotDefault()那步, s.InitValidation("s")的时候就已经报Object reference not set to an instance of an object.异常了,这个问题不知你发现没有?如何解决呢?貌似扩展方法没有办法解决null的验证哦,难道针对null又回到第二阶段?

    public ValidationHelper<T> NotDefault()
    {
       
if (Value.Equals(default(T)))
        {
           
if (Value is ValueType)
            {
               
throw new ArgumentException(
                    String.Format(
"参数{0}不能使用默认值http://images.cnblogs.com/dot.gif" />", Name), Name);
            }
           
else
            {
               
throw new ArgumentNullException(
                    String.Format(
"参数{0}不能为nullhttp://images.cnblogs.com/dot.gif" />", Name), Name);
            }
        }
       
return this;
    }

发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 1281526




相关文章:

相关链接: