作者

文章 liu bo · 九月 21, 2023 4m read

通过自定义数据类型实现参数统一验证优化重构代码

前言

对于第三方接口进行交互的时候,往往需要大量的进行参数合法性校验。以前的方法就是对每个参数进行验证。如下截图: image

上图的会存在大量的if else if else..,如果字段很多,那导致一个方法存在大量的验证的代码,那我们考虑是否可以进行统一的验证参数的合法性。

思路

平时建立类的时候我们可以写参数MAXLEN=100,TRUNCATE=1 是否截取等,那找找这些参数的定义地方。如截图:

image 那我们想要定义自己的参数,该如何定义呢?根据面向对象设计原则之一:

里氏替换原则(Liskov Substitution Principle,LSP):子类型必须能够替换掉他们的基类型。即,在任何父类可以出现的地方,都可以用子类的实例来赋值给父类型的引用。当一个子类的实例应该能够替换任何其超类的实例时,它们之间才具有是一个 (is-a) 关系

那我们可以自定义数据类型,继承%Library.String,这样子类继续使用父类的参数,还可以自定义自己的参数。此处以字符串为例,其他的数据类型一样的原理。 自定义类型就为String.

实现

  1. 自定义数据类型

`

/// 自定义数据类型实现继承的String
Class Design.DataType.String Extends %Library.String
{

/// 是否为空 1 必填 0 可以为空
Parameter NOTBLANK = 0;

/// 代码值,写取global的表达式? $XECUTE 执行?
Parameter DICCODE;

/// 不为空的错误消息
Parameter MESSAGE;

/// 错误码值错误
Parameter CODEERRMESSAGE;

/// 类型 INT,STRING,FLOAT,NUMBER,DATE,DATETIME
Parameter TYPE = "STRING";

/// 是否时间类型
Parameter ISDATE = 0;

/// 时间格式:yyyy-MM-dd=>3  yyyyMMdd=8 dd/MM/yyyy=1	默认
Parameter DATEFORMAT = 3;

/// 条件取值验证
Parameter CONDITION;

/// 是否需要在当前时间之后,比如预约时间
Parameter ISAFTER;

/// 是否在当前直接之前 比如出生日期
Parameter ISBEFORE;

}

`

2.定义模型类 `

Class Design.DataType.Person Extends (%RegisteredObject, %XML.Adaptor)
{

/// 姓名
Property pname As String(MAXLEN = 100, MESSAGE = "人员姓名不能为空!", NOTBLANK = 1, TRUNCATE = 1);

/// 生日
Property birth As String(DATEFORMAT = 3, ISBEFORE = 1, ISDATE = 1, MESSAGE = "出生日期不能为空!", NOTBLANK = 1, TRUNCATE = 1);

/// 性别
Property sexCode As String(CODEERRMESSAGE = "性别代码错误!", DICCODE = "$O(^CT(""SEX"",0,""Code"",", MAXLEN = 100, MESSAGE = "性别代码不能为空!", NOTBLANK = 1);

/// ...此处省略  民族,国籍,学历等等
/// 工作描述
Property job As Job;

}

`

3.统一验证的方法代码 `

/// 校验对象的工具类
Class Design.DataType.ValidUtil Extends %RegisteredObject
{

/// 判断对象是否有效
/// TODO:嵌套对象可以自己研究研究
ClassMethod IsValid(obj As %ObjectHandle, Output errmsg As %String) As %Status
{
	s ClsName=obj.%ClassName(1)
	s validFlag=$$$OK
	s Name=""
	f{
		s Name=$o(^oddDEF(ClsName,"a",Name)) 
		q:Name="" 
	    s Val=$Property(obj,Name)
	    w Name_"="_Val,!
	    ;获取属性对应的参数
	    ;是否为空
	    s NOTBLANK=$g(^oddDEF(ClsName,"a",Name,"P","NOTBLANK"))
	    i (NOTBLANK=1)&&(Val=""){
		  s errmsg= $g(^oddDEF(ClsName,"a",Name,"P","MESSAGE"))  
		  s validFlag=0
		  q 
		}
		;是否码值校验
		s DICCODE=$g(^oddDEF(ClsName,"a",Name,"P","DICCODE"))
		i DICCODE'=""{
		   SET cmd="(out){ s out="_DICCODE_""""""_$$ALPHAUP^SSUTIL4(Val)_""",""""))"_" q 1}"
		   SET rtn=$XECUTE(cmd,.rowId)
		   i rowId="" {
			  s errmsg=$g(^oddDEF(ClsName,"a",Name,"P","CODEERRMESSAGE"))
			  s validFlag=0
			  q 
		   } 
		}
		;是否时间格式校验
	    s ISDATE=$g(^oddDEF(ClsName,"a",Name,"P","ISDATE"))
	    if ISDATE=1 {
		   s DATEFORMAT=$g(^oddDEF(ClsName,"a",Name,"P","DATEFORMAT"))
		   s result=$zdh(Val,DATEFORMAT,"","","","","","-1","时间格式错误","")
           if result="时间格式错误"{
	          s errmsg="字段"_Name_"["_Val_"]"_"时间格式错误"
	          s validFlag=0
			  q  
	       }
	       //时间与当前时间的验证
	       s ISBEFORE=$g(^oddDEF(ClsName,"a",Name,"P","ISBEFORE"))
	       if ISBEFORE=1{
		      if result>+$h {
			      s errmsg="字段"_Name_"["_Val_"]"_"不能超过当前日期!"
			      s validFlag=0
				  q  
		      }
		   }
		   s ISAFTER=$g(^oddDEF(ClsName,"a",Name,"P","ISAFTER"))
	       if ISAFTER=1{
		      if result<+$h {
			      s errmsg="字段"_Name_"["_Val_"]"_"不能小于当前日期!"
			      s validFlag=0
				  q  
		      }
		   }
		}
	}
    q validFlag
}

}

`

测试

  1. 测试不为空 image

  2. 测试code错误 image

3.测试时间格式错误 image

4.测试时间的值先后 image

[^1]

**参数还需要进行大量的验证,此处只是示例,可能存在错误,欢迎批评纠正**

[^1]:

Comments

姚 鑫 · 九月 28, 2023

提供了很好的思路

0