我目前正在使用hibernateconstraintvalidator来实现我的验证。但是我的审稿人不喜欢在代码中使用if/else或!操作员。我可以使用哪种设计模式删除验证逻辑中的if/else?
public class SomeValidatorX implements ConstraintValidator<SomeAnnotation, UUID> {
@Autowired
SomeRepository someRepository;
@Override
public boolean isValid(UUID uuid, ConstraintValidationContext context) {
return !(uuid!=null && someRepository.existsById(uuid)); //The reviewer doesn't want this negation operator
}
}
在下面的代码中,他不想要if/else
public class SomeValidatorY implements ConstraintValidator<SomeAnnotation, SomeClass> {
@Autowired
SomeRepository someRepository;
@Override
public boolean isValid(SomeClass someObject, ConstraintValidationContext context) {
if(someObject.getFieldA() != null) { //He doesn't want this if statement
//do some operations
List<Something> someList = someRepository.findByAAndB(someObject.getFieldA(),B);
return !someList.isEmpty(); //He doesn't want this ! operator
}
return false; // He was not fine with else statement in here as well
}
}
旁注:我们必须使用域驱动设计(如果有帮助的话)
2条答案
按热度按时间cngwdvgl1#
可以检查空对象模式。一般的模式是禁止
null
完全脱离你的代码。这就消除了丑陋null
检查。在这一点上,我同意你的代码审查。以下建议将导致:
避免空检查
在引入空对象模式之前,只需应用模式或约定来强制初始化所有引用。这样你就可以确定
null
整个代码中的引用。所以当你遇到
NullPointerException
,你不能通过引入null
检查,但通过初始化引用(在构造时),例如使用默认值、空集合或空对象。大多数现代语言都支持通过注解进行代码分析,比如
@NonNull
它检查参数之类的引用,并在参数为null
/未初始化。javax.annotation
例如,提供了这样的注解。使用这样的注解可以保护库代码不受空参数的影响。
空对象模式
而不是
null
引用时,可以使用有意义的值或专用的空对象初始化每个引用:定义空对象协定(不是必需的):
定义基类型:
定义空对象:
定义默认实现:
全部初始化
Account
使用NullAccount
班级:或者使用
NullAccount
返回失败的状态示例(或默认值),而不是返回null
:试做模式
您可以使用的另一个模式是try-do模式。您只需测试操作本身,而不是测试操作的结果。操作负责返回操作是否成功。
在文本中搜索字符串时,无论结果是否找到,都可以返回布尔值,而不是返回空字符串,甚至更糟
null
:在您的特殊情况下,您可以更换
findByAAndB()
带着一个containsAAndB() : boolean
实施。组合模式
最终的解决方案实现空对象模式并重构find方法。原来的结果
findByAAndB()
因为你想测试A
以及B
. 另一种方法public boolean contains()
将改进您的代码。重构后的实现如下所示:
改进的验证:
v7pvogib2#
很久以前,在时间的开始。有一个指导方针说方法应该只有一个出口点。为了实现这一点,开发人员必须跟踪本地状态并使用if/else才能到达方法的末尾。
今天我们更清楚了。通过尽可能早地退出一个方法,在阅读代码时将整个流程保持在我们的头脑中会容易得多。更简单的代码意味着更少的错误。更少的错误等于更少的错误。
在我看来,这就是为什么评审员不喜欢代码。它不是那么容易阅读,因为它可以。
我们举第一个例子:
代码说的是“不是这个:(uuid不应该是空的,它必须存在)”。这容易理解吗?我想不是。
另一种选择是:“如果uuid不存在就可以了,但是如果uuid存在,则该项可能不存在”。
或在代码中:
更容易阅读,对吧(我希望我的意图是正确的;))
第二个例子
好 啊。你在说:
如果字段a不为空:
在找到a和b的地方建立一个列表
如果该列表不为空,则失败,否则成功。
否则失败
一个简单的结论是:
如果没有指定字段a就可以了
如果指定了字段a,则它必须与b一起存在。
翻译成代码:
在c#我们有
Any()
它与isEmpty
在这种情况下,我更喜欢它,因为它消除了否定。有时需要否定。在存储库中编写新方法来避免它是没有意义的。但是,如果
findByAAndB
仅用于此,我将其重命名为ensureCombination(a,b)
以便在有效情况下返回true。试着边说边写代码,这样就更容易在脑海中描绘代码了。你不是说“我没吃饱,我们去吃午饭吧”,是吗?;)