我以前的痛苦,你也拥有吗?

记得笔者在以前使用Delphi/C++/Java开发软件时,经常需要撰写许多的输入验证码,例如当用户输入身份证号,或是输入数值时,都需要根据企业逻辑来检查用户输入的数据是否正确,通常许多的验证逻辑程序代码几乎都是一样的,但是对于不同的程序语言,不同的开发环境都可能需要不断重写。更麻烦的是,由于一个团队拥有许多的开发人员,因此不同的开发人员可能会使用不同的程序代码,不同的验证逻辑,并且分散在整个应用程序不同的地方进行数据验证的工作。这造成了许多的困扰,例如当验证逻辑需要修改或是更正时,可能忘记改某些地方,或是由于开发人员撰写的方式不同,而让一些臭虫因此而出现。虽然后来许多的开发人员把这些验证程序代码封装成函式库统一让开发人员使用,或是封装成组件让开发人员使用,例如现在.NET/Java都提供了一些简单,常用的Validation组件,但是验证程序代码分散在整个应用程序不同的地方的问题仍然无法得到解决,而由这个现象延伸出的问题也一样存在。那么我们有什么好方法可以解决吗?

在回答之前也许我们应该想想这些验证程序代码的目的到底是什么?在这些验证程序代码中除了一般检查用户输入的字符,格式,长度或是语意之外,最重要的验证工作应该是用户的输入应该符合应用程序的企业逻辑规则,不是吗?

因此如果我们能够把这些验证程序代码进行的工作定义在企业逻辑模型之中,那么不管日后开发人员使用什么程序语言,或是在应用程序的什么地方,开发人员只需要在需要进行验证程序代码的工作时从企业逻辑模型中最出定义好的验证逻辑,再根据这些验证逻辑来验证用户输入的数据。如此一来一旦验证逻辑有改变或是更新,我们只需要更新定义在企业逻辑模型之中的验证逻辑,那么由于整个应用程序都是从企业逻辑模型中取得验证逻辑,那么我们不就解决了可能忘记更改一些分散在不同地方的问题了吗? 更进一步的想想,如果我们能够使用一段通用的程序代码来检查企业逻辑规则,而不需要对每一个不同的用户输入撰写不同的程序代码来检查,那么不是更棒吗(如果读者真的开发过这样的应用程序验证逻辑,就知道笔者说的痛苦,以及难以维护的程序代码了)?

问题是,能够有方法解决这长久以来的痛苦吗?

也许有可能,让我们继续往下看。

在UML中,开发人员可以使用OCL来定义类别/属性的验证逻辑或是约束条件,之后开发人员便可以在程序代码中藉由EcoSpace取得这些约束条件(Constraints),并且使用来验证异动的对象是否符合这些约束条件,一旦符合约束条件才能够更新回数据来源之中。在ECO架框中支持了这样的机制,ECO藉由提供开发人员使用OCL为ECO类别/ECO属性定义约束条件,以及在ECO架框中提供服务让开发人员能够在程序代码中存取这些约束条件并且执行约束条件以便验证对象。

在您了解了上面讨论的观念之后,接下来的内容中将深入的说明如何在企业逻辑模型中使用OCL来定义约束条件,并且使用来验证对象。

在企业逻辑模型中定义约束条件

开发人员可以在ECO的类别设计家中藉由对象检视器设定类别或是属性的Constraints特性来定义约束条件。使用Constraints特性定义约束条件时开发人员必须了解下面的观念:

l         Constraints特性可以定义任何数目的约束条件

l         约束条件是使用OCL来撰写的

l         开发人员使用Constraints特性定义约束条件后,如果用户违反了约束条件那么仍然可以更新对象回数据来源。因此检查对象是否违反约束条件是开发人员的责任,开发人员必须确定对象在更新回数据来源之前没有违反约束条件。

现在让我们以图1的范例模型来说明如何定义约束条件以及如何在程序代码中检查企业逻辑模型的约束条件。

图1  范例模型

如下图所示,我们可以点选Joiner类别,并且在对象检视器中定义Constraints特性:

图2  在ECO设计家中为类别/属性定义约束条件

开发人员可以直接在Constraints特性中输入OCL或是点选Constraints特性旁的按钮启动Constraints编辑器,点选Constraints编辑器下方的Add按钮加入约束条件。下面的图形加入了两个约束条件,每一个约束条件必须输入约束条件的名称以及约束条件的OCL叙述,例如NameNotEmpty约束条件规定了Name属性不可为空白,同样的EMailNotEmpty也是类似的规定。

图3  启动约束条件编辑器为Joiner类别定义约束条件

最后,范例企业逻辑模型也为DevCoSeminar的MaxCount属性定义了最多参加人数的约束条件必须小于120人:

图4  启动约束条件编辑器为DevCoSeminar类别定义约束条件

定义完Constraints的约束条件后,让我们再解释一下封装约束条件的IConstraint界面。

IConstraint界面

在ECO架框中企业逻辑模型中的约束条件是由IConstraint接口封装,定义的,开发人员藉由ECO架框服务接口存取到IConstraint接口,再藉由执行IConstraint接口定义的约束条件来验证对象是否符合企业逻辑。下面是IConstraint接口的定义:

public interface IConstraint: IModelElement

{

IExpression Body { get; }

IEcoConstraint EcoConstraint { get; }

}

IConstraint接口有两个只读属性,其中的Body即代表封装的约束条件,而EcoConstraint则是专属于ECO的额外信息。Body属性型态是IExpression接口,而IExpression接口的定义如下:

public interface IExpression

{

string Language { get; }

string Body { get; }

}

IExpression接口也有两个只读属性,其中的Language属性会回传约束条件使用的语言,通常都是”OCL”,代表是由OCL撰写的约束条件。而Body属性则是约束条件本身。例如前面的“NameNotEmpty”约束条件,它的IConstraint.Body.Body属性便是self.Name.Length>0。

IEcoConstraint接口也定义了两个只读属性,IsAutoGenerated属性回传这个约束条件是否是自动产生的,而Description则是约束条件的叙述文字:

public interface IEcoConstraint

{

bool IsAutoGenerated { get; }

string Description { get; }

}

因此在ECO程序代码中,要根据约束条件来验证对象,它的执行步骤如下:

l         从ECO企业逻辑对象中取得所有的约束条件的IConstraint接口对象

l         一一的使用IOclService执行这些约束条件并且判断约束条件是否符合

l         如果ECO企业逻辑对象符合约束条件才能够更新回数据来源

l         如果ECO企业逻辑对象不符合约束条件,那么就通知用户进行后续的处理

了解了IConstraint界面以及处理约束条件的步骤之后,接下来我们就可以使用范例和程序代码来展示如何使用约束条件了。

在程序代码中验证对象的约束条件

要如何使用程序代码来检查定义在企业逻辑模型中的约束条件呢? 其实非常的简单的,本书在第4章已经介绍了ECO的企业逻辑模型的静态通用机制,因此我们可以使用下面的步骤来完成检查企业逻辑模型中的约束条件:

l         在更新异动对象回数据来源之前,藉由使用IDirtyListService服务界面取得用户所有异动的对象

l         藉由ECO的企业逻辑模型的静态通用机制取得定义在企业逻辑模型中的约束条件

l         藉由IOclService服务接口一一的执行约束条件并且检查是否违反约束条件

l         如果没有违反任何的约束条件就更新对象回数据来源中

l         如果违反约束条件的话,保留违反约束条件的对象,要求用户进一步的处理

了解了进行约束条件检查的步骤之后,让我们看一些实际的程序代码来验证上面的步骤。

在下面的片段程序代码中是准备呼叫EcoSpace的UpdateDatabase方法把用户异动的对象更新回数据来源中,但是在这之前,它先呼叫了DoCheckObjectConstraints方法以便确定所有异动的对象是符合企业逻辑模型中的约束条件,否则DoCheckObjectConstraints会产生一个例外错误。

001    procedure TWinForm.Button2_Click1(sender: System.Object; e: System.EventArgs);

002    begin

003      try

004        DoCheckObjectConstraints;

005        EcoSpace.UpdateDatabase;

006      except on E: Exception do

007        MessageBox.Show ('对象违反约束条件' + e.Message +'无法更新回数据库',

008                          MessageBoxButtons.OKCancel, MessageBoxIcon.Asterisk);

009      end;

end;

在DoCheckObjectConstraints方法中先在007行取得IDirtyListService接口,接着进入010行的for循环一一的取出每一个异动的对象并且呼叫DoHandleDirtyObject来检查每一个异动对象的约束条件是否符合。

001    procedure TWinForm.DoCheckObjectConstraints;

002    var

003      dol : IDirtyListService;

004      Iobj : IObject;

005    begin

//藉由IdirtyListServices取得异动的对象

007      dol := EcoSpace.DirtyListService;

008      if (dol.HasDirtyObjects) then

009      begin

010        for Iobj in dol.AllDirtyObjects do

011        begin

012          DoHandleDirtyObject(Iobj);

013        end;

014      end;

015    end;

最后的DoHandleDirtyObject方法在008行取得IOclService接口,在009行进入for循环,藉由IObject界面的UmlType.Constraints取得定义在这个对象类别中的所有约束条件,接着在012行呼叫IOclService的Evaluate方法来执行/评量约束条件。如果有任何对象违反了任何的约束条件就产生一个例外错误。

001    procedure TWinForm.DoHandleDirtyObject(Iobj : IObject);

002    var

003      IOcl : IOclService;

004      ICnt : IConstraint;

005      iCount: Integer;

006      bResult : boolean;

007    begin

008      IOcl := EcoSpace.OclService;

009      for iCount := 0 to Iobj.UmlType.Constraints.Count - 1 do

010      begin

011        ICnt := Iobj.UmlType.Constraints.Item[iCount];

012        bResult := boolean(IOcl.Evaluate(Iobj as IElement,iCnt.Body.Body).AsObject);

013        if (not bResult) then

014          raise Exception.Create(ICnt.Name);

015      end;

016    end;

现在如果我们执行上面的范例程序代码并且搭配图3和图4定义的约束条件,那么我们可以看到当执行下面的范例程序并且在DevCoSeminar对象的MaxCount属性中输入超过120的数值:

图5  修改DevCoSeminar对象的MaxCount属性值

那么在更新对象回数据来源之前就会看到下面的例外错误,代表上面的程序代码果然检查出了对象违反了约束条件。

图6  程序代码检查出用户输入的数据违反了约束条件

如果我们接着又如下图对Joiner类别进行异动并且试着把EMail属性清为空白:

图7  程序代码检查出用户输入的数据违反了约束条件

那么在更新对象回数据来源之前我们又可以看到范例程序检查出Joiner对象违反了EmailNotEmpty的约束条件。

从上面的程序代码看到了什么? 如果您有注意的话会发现只需要使用相同的一份程序代码,在一个程序/函式中就可以检查任何对象的任何约束条件。这和以前许多开发人员需要使用不同的程序代码,在不同的地方检查不同的用户输入资料是完全不一样的,这可以让程序代码更容易维护,也不容易产生臭虫,或是因为疏失而造成的错误。

如果我们进一步的结合.NET/开发工具提供的Validation组件和约束条件,那么我相信大多数的程序代码验证工作都可以顺利,有效率的完成。

您注意到,感觉到了使用模型和约束条件的好处了吗?

 
 
 
 
 
 
 

我以前的痛苦,你也拥有吗?相关推荐

  1. 人工智能的技术变革:HMS Core让你也拥有《星球大战》中的机器人

    文章来源:InfoQ 你还记得<星球大战>电影中的礼仪机器人 C-3PO 吗?就是那个承担着不同种族.不同物种间翻译交流作用的礼仪机器人.C-3PO 通过从数据库中下载资料来更新自己的语言 ...

  2. 三分钟让你也拥有一个很酷炫的GitHub展示页面(保姆级教程)

    目录 让我们开始吧! 1.创建一个新的存储库 2.更新README文件 3.✨美化您的个人资料!✨ GitHub README 统计 GitHub 个人资料奖杯 添加标题或封面图片 添加浮动图像或 G ...

  3. webview 禁止苹果自动下拉_苹果手机如何拥有百变铃声?酷狗铃声1分钟搞定!-时尚呼吸...

    众所周知,目前的智能手机分为安卓和苹果两大阵营,虽然各有优点,但是在设置来电铃声这方面,苹果手机的IOS系统真不如安卓灵活,许多人为此伤脑筋.其实苹果手机设置铃声并不难,酷狗铃声分分钟将它搞定! 不止 ...

  4. 一篇对于了解我自己,挖掘我自己,从而成长的文章

    什么是高敏感人格 这段时间开始将自身精力'由外转内',更多的关注自身,从生理身体,到内在心理,寻找真正的自己,从而帮助自己更好的成长 人生,就是在不断的寻找自己 感谢武志红老师公众号的课程,以下均出自 ...

  5. 一个人该怎样找到自己真正热爱和擅长的事,并以此规划自己的人生?

    文章目录 一个人该怎样找到自己真正热爱和擅长的事,并以此规划自己的人生? **一.有关擅长的4个错误认知** **二.做好这3步,拥有擅长之事** **1.生成兴趣清单** **2.缩小选择范围** ...

  6. 成就你一生的100个哲理1-10

    修身养性篇1.别被不必要的"包袱"压垮 一对靠捡破烂为生的夫妻,每天一早出门,拖着一部破车到处捡拾破铜烂铁,等到太阳下山时才回家.他们回到家的时候,就在门口的院子里摆上一盆水,搬一 ...

  7. 虚拟化服务器故障,修复vSphere vCenter服务器故障的技巧

    如果vSphere环境没有遵循最佳实践,那么通常意味着需要花费更多的时间和精力来解决vCenter服务器出现的问题. 也许你也拥有类似的体会,有时我会在数据中心的排错过程当中获得一些平时难以学习到的经 ...

  8. 学而思的python课怎么样_有在用学而思网校的同学觉得孙墨漪老师怎么样?报她的课值得吗?...

    我觉得很值得. 很棒. 是的,一千个人心中就有一千个哈姆雷特,而对于一个老师的评价,每个人也可能是褒贬不一. 但是,到目前来说,孙老师带来给我的都是积极正面的影响. 我原先跟的老师并不是孙墨漪老师班, ...

  9. 牛人三个月内花不到 5000 美元拿到 CS 学位

    [编者按]从小,别人家的孩子一直都是优秀的!国外牛人大学入学一学期后,觉得课程授课过于繁琐且效率很低,于是自己钻研,自认学成之后放弃奖学金并退学.然而近年因为学位问题屡屡碰壁,于是他又花了不到 500 ...

最新文章

  1. 每个优秀程序员必须具备的技术技能
  2. 实验一:JDK下载与安装、Eclipse下载与使用总结心得
  3. 新生男婴自带新冠抗体,感染者母亲如今抗体消失,医生:抗体转移了
  4. python3 获取 文件 文件夹大小
  5. 香港的CIA线服务器是什么?
  6. flutter - 如何在 dart/flutter 中收听流值
  7. Deep Learning(深度学习)学习笔记整理系列之LeNet-5卷积参数个人理解
  8. 1077篇!ICCV2019接收结果公布,你中了吗?(附7篇论文链接,含Oral)
  9. 几行代码实现谷歌百度搜索对比
  10. Python的__init__和self是做什么的?
  11. C# 让应用程序只运行一个实例
  12. 尚硅谷JVM笔记(宋红康主讲)
  13. mysql jdbc 5.6_mysql5.6 jdbc驱动官网下载|
  14. 电脑突然变成繁体字,格式化代码快捷键失灵
  15. docker基础(11):自定义tomcat镜像启动与访问
  16. access身份证号掩码_access中怎么设置掩码控制数字范围
  17. matlab筛选excel数据统计,#excel筛选数据#如何用excel表格中的数据制图
  18. python:while 的无条件循环
  19. Linux 文件服务
  20. 纯HTML+CSS带说明的黄色导航菜单

热门文章

  1. 作为一本书,我是如何把别的Java系列卷死的!
  2. 蒲公英服务器搭建小程序,uniapp 小程序打包发布
  3. 程序员的可迁移技能和经验
  4. 简单聊聊Long Short Term Memory Network (LSTM)和 Gated Recurrent Unit (GRU)两种强大的RNN变体
  5. 关于vue2高德地图使用
  6. 微信公众平台开发-java
  7. 计算机电源接口在哪,电脑电源接口定义图解
  8. Beaver 论文阅读笔记
  9. 关于 “Ubuntu 18.04.2 LTS _Bionic Beaver_ - Release amd64 (20190210)” 的盘片插入驱动器“/cdrom/”再按「回车」键 的解决问题
  10. STM32cubemx教程 DAC+TIM+DMA