逻辑或运算和逻辑与运算业务实操分析
在正常的业务维护中,最怕维护别人写的代码,尤其是没有任何注释的代码。而项目文档在项目搭建的时候不重要,但后面如果有人接手,既没有项目文档,注释也懒得写,那么一些较为复杂的业务逻辑会成为噩梦。
半天梳理业务逻辑,尤其对着仅有的注释部分去尝试推测、理解代码逻辑。这里就涉及到与和或的逻辑预算,逻辑或和逻辑与运算都不是简单的多条件交集、并集。逻辑或在一个或者多个条件中有一个为 true,结果就是 true;在所有条件都为 false 的时候,结果才是 false。逻辑与相反,只要一个为 false,结果就是 false;需要所有条件都为 true,结果才是 true。
并且或和与运算存在短路原则,当或运算的前面条件返回了 true,后面的条件都不会执行了。同样的当与运算的前面条件返回了 false,后面的条件也不会执行。
逻辑与运算实例
统计已分案案件,且账龄未发生变化,且分案类型不是 a,b,c,d,e
for (CaseInfo caseInfo:list){
CaseInfoUser oldCaseInfoUser = caseInfoUserService.selectCaseInfoUserByCaseId(caseInfo.getId());
if(oldCaseInfoUser != null
&& caseInfo.getAging().equals(oldCaseInfoUser.getAging())
&&!"a".equals(oldCaseInfoUser.getCaseRuleCode())
&&!"b".equals(oldCaseInfoUser.getCaseRuleCode())
&&!"c".equals(oldCaseInfoUser.getCaseRuleCode())
&&!"d".equals(oldCaseInfoUser.getCaseRuleCode())
) {
num++;
continue;
}
....
}
原来的代码里有 9 个这样相同逻辑的与,然后在想自己接触到的代码写法,好像可以优化。都是不等于,可以把所有的值放到一个 List 中,通过 contains 方法来判断分案类型是否在列表中。
优化后的代码:
List<String> ruleCodes = Arrays.asList("a","b","c","d"...);
for (CaseInfo caseInfo:list){
CaseInfoUser oldCaseInfoUser = caseInfoUserService.selectCaseInfoUserByCaseId(caseInfo.getId());
if(oldCaseInfoUser != null
&& caseInfo.getAging().equals(oldCaseInfoUser.getAging())
&& !ruleCodes.contains(oldCaseInfoUser.getCaseRuleCode())
) {
num++;
continue;
}
...
}
突然发现 continue;
,这个 continue;
不是针对 if,而是 for 循环的。所以 if 语句的逻辑就变成了 统计已分案案件,且账龄未发生变化,且分案类型不是 a,b,c,d,e,不重新分案
。
逻辑或运算实例
在匹配到分案规则,且分案规则不为空的前提下,需要强调只有案件从未分案,或者分案规则、规则对应的分案组别、组别下的组员发生变化,才会重新分案。
之所以没有跟前面的 if 逻辑与部分合并,主要是因为需要根据匹配到的分案规则做逻辑。
之前的逻辑:
//1.1 查看案件之前是不是已经分过规则,看下账龄有没有变化。有变化在处理
//24.4.11 若分案规则 - 分案组别、组员发生变化,重新分案
for (CaseInfo caseInfo:list) {
...
CaseCollectionGroupUser oldGroupUser = null; // 之前的分案用户
List<CaseCollectionGroupUser> newGroupUsers = null; // 新规则的分案用户
if (oldCaseInfoUser != null) { // 之前的分案用户记录
oldGroupUser = caseCollectionGroupUserService.selectCaseCollectionGroupUserById(oldCaseInfoUser.getCaseGroupUserId());
// newGroupUsers = caseCollectionGroupUserService.selectCaseCollectionGroupUserByGroupId(caseRule.getGroupId());
}
if (caseInfo.getCaseRuleId() == null
|| !caseRule.getId().equals(caseInfo.getCaseRuleId()
|| !Objects.equals(oldGroupUser.getGroupId(), caseRule.getGroupId())))
|| oldGroupUser == null
// || !newGroupUsers.stream().map(CaseCollectionGroupUser::getUserId).collect(Collectors.toList()).contains(oldGroupUser.getUserId())))
) {
...
}
...
}
注释 1.1 的需求,通过 if + continue
已经实现了。
注释 24.4.11 若分案规则 - 分案组别、组员发生变化,重新分案
,逻辑是递进的:
- 案件从未分案
- 案件已分案,匹配的分案规则发生变化
- 案件已分案,匹配的分案规则未变,分案组别、组员发生变化
分案规则判断比较简单,直接比较规则编码是否一致就可以。分案组别、组员发生变化,需求主要是针对负责人员发生变动,进而调整之后,需要系统自动将案件分配给组别内的其他人。或者分案规则修改过绑定的分案组别,此时也需要重新分案。
因为分案用户记录中添加的是分案组别用户关系 ID,没有分案组别 ID 的冗余,而逻辑判断需要分案组别,所以多了一步,根据分案组别用户关系 ID 查询实际的组别组员关系表记录。
所以一开始的做的逻辑是先判断分案组别是否有变化,之后再判断组员是否还在分案组中。
- 案件已分案,匹配的分案规则未变,分案组别发生变化
- 案件已分案,匹配的分案规则未变,分案组别未变,组员发生变化
判断组员是否还在分案组中,需要多一次查询组别中的组员,想着是否可以优化。在看到前面增加了之前的分案用户的查询之后,想到可以根据分案用户是否存在,直接判断组员是否发生变化。因为分案用户如果发生变化,比如直接从组中去除,或者调动到其他组,都会删除组员记录,且是物理删。
新增逻辑:
//24.4.14 M3 以上案件家访默认跟2个月,若标记延长,则跟3个月
List<String> m3p = Arrays.asList("M3","M4","M5"...);
CaseCollectionGroupUser oldGroupUser = null; // 之前的分案用户
List<CaseCollectionGroupUser> newGroupUsers = null; // 新规则的分案用户
if (oldCaseInfoUser != null) { // 之前的分案用户记录
oldGroupUser = caseCollectionGroupUserService.selectCaseCollectionGroupUserById(oldCaseInfoUser.getCaseGroupUserId());
if (caseInfo.getCaseRuleId() == null
|| (!caseRule.getId().equals(caseInfo.getCaseRuleId())
&& m3p.contains(caseInfo.getAging())
&& oldCaseInfoUser != null
&& ((Objects.equals(oldCaseInfoUser.getMyDelay(), "1")
&& DateUtils.getDaysDifference(new Date(), oldCaseInfoUser.getDivisionDate()) > 90)
|| DateUtils.getDaysDifference(new Date(), oldCaseInfoUser.getDivisionDate()) > 60))
|| (caseRule.getId().equals(caseInfo.getCaseRuleId())
&& (oldGroupUser == null
|| !Objects.equals(oldGroupUser.getGroupId(), caseRule.getGroupId())))
) {
...
}
思考了一下,这个需求还有一个隐藏的前置条件,就是已分案,且分案规则或者组别、组员得发生变化,不然按照现有条件就不会重新分案,那么自然就不需要做这个逻辑了。问了提需求的业务,分案规则或者组别、组员得发生变化条件是优先于家访 2-3 月内不重新分案的,举个例子,如果在家访 2-3 个月内出现分案规则或者组别、组员得发生变化的情况,是需要优先按照后者满足条件,进行重新分案的。
罗列现有规则条件:
- 案件已分案,匹配的分案规则、分案组别、组员发生变化,家访 2-3 个月以内,不重新分案
- 案件从未分案
- 案件已分案,匹配的分案规则发生变化
- 案件已分案,匹配的分案规则未变,分案组别发生变化
- 案件已分案,匹配的分案规则未变,分案组别未变,组员发生变化
但第一条明显和后面的三条逻辑冲突了,且不满足分案规则或者组别、组员得发生变化的条件优先。
如果不考虑优先条件,按照逻辑或运算实例,将所有家访 2-3 个月以内的案件都排除掉,是可以实现的。但这样做,又会破坏原来想要的,只要分案规则或者组别、组员得发生变化,就重新分案的大前提。
所以,如果按照现有的条件去做,那么这个需求根本就不需要做,因为只要匹配的分案规则、分案组别、组员未变,就不会重新分案,家访 2-3 个月以内压根不需要考虑。