我需要根据某些条件在实体中设置数据.
我用下面的数据来设置
if (StringUtils.isNotBlank(customerVO.getGender())) {
mstCustomer.setGender(customerVO.getGender());
}
if (StringUtils.isNotBlank(customerVO.getBirthDate())) {
mstCustomer.setDob(DateUtils.getUtilDate(customerVO.getBirthDate()));
}
if (StringUtils.isNotBlank(customerVO.getAdd1())) {
mstCustomer.setAddress1(customerVO.getAdd1());
}
if (StringUtils.isNotBlank(customerVO.getAdd2())) {
mstCustomer.setAddress2(customerVO.getAdd2());
}
if (StringUtils.isNotBlank(customerVO.getAdd3())) {
mstCustomer.setAddress3(customerVO.getAdd3());
}
if (StringUtils.isNotBlank(customerVO.getPincode())) {
mstCustomer.setPinCode(customerVO.getPincode());
}
if (StringUtils.isNotBlank(customerVO.getStateName())) {
MstState state = mstStateRepository.findByName(customerVO.getStateName());
mstCustomer.setMstState(state);
}
if (StringUtils.isNotBlank(customerVO.getCity())) {
MstCity city = mstCityRepository.findByName(customerVO.getCity());
mstCustomer.setMstCity(city);
}
if (StringUtils.isNotBlank(customerVO.getIdentificationType())) {
mstCustomer.setIdentificationType(customerVO.getIdentificationType());
}
if (StringUtils.isNotBlank(customerVO.getIdentificationData())) {
mstCustomer.setIdentificationData(customerVO.getIdentificationData());
}
MstStatus mstStatus = mstStatusRepository.findOne(MstStatusEnum.CUST_ACTIVE.getStatusCode());
if (mstStatus != null) {
mstCustomer.setMstStatus(mstStatus);
}
if (!StringUtils.isBlank(customerVO.getMaritalStatus())) {
mstCustomer.setMaritalStatus(customerVO.getMaritalStatus());
}
if (StringUtils.isBlank(customerVO.getWeddingAnniversary())) {
mstCustomer.setWeddingAnniversary(DateUtils.getDateFromString(customerVO.getWeddingAnniversary()));
}
if (StringUtils.isNotBlank(customerVO.getMotherTongue())) {
mstCustomer.setMotherTongue(customerVO.getMotherTongue());
}
if (StringUtils.isNotBlank(customerVO.getFamilySize())) {
mstCustomer.setFamilySize(Integer.valueOf(customerVO.getFamilySize()));
}
if (StringUtils.isNotBlank(customerVO.getAdultsSize())) {
mstCustomer.setAdultsSize(Integer.valueOf(customerVO.getAdultsSize()));
}
if (StringUtils.isNotBlank(customerVO.getNoOfKids())) {
mstCustomer.setNoOfKids(Integer.valueOf(customerVO.getNoOfKids()));
}
if (StringUtils.isNotBlank(customerVO.getChilddob1())) {
mstCustomer.setChilddob1(DateUtils.getDateFromString(customerVO.getChilddob1()));
}
if (StringUtils.isNotBlank(customerVO.getChilddob2())) {
mstCustomer.setChilddob2(DateUtils.getDateFromString(customerVO.getChilddob2()));
}
if (StringUtils.isNotBlank(customerVO.getProfession())) {
mstCustomer.setProfession(customerVO.getProfession());
}
Run Code Online (Sandbox Code Playgroud)
但是声纳抛出这个例外: Refactor this method to reduce its Cognitive Complexity from 27 to the 15 allowed.
请建议重构上述代码的最佳方法是什么.
Dic*_*ici 19
使用lambdas似乎很可行:
private void setIfNotBlank(String value, Consumer<String> setter) {
setConditionally(value, setter, StringUtils::isNotBlank);
}
// if you don't need non-string arguments you can inline this method
private <T> void setConditionally(T value, Consumer<T> setter, Predicate<T> shouldSet) {
if (shouldSet.test(value)) setter.accept(value);
}
Run Code Online (Sandbox Code Playgroud)
然后,
if (StringUtils.isNotBlank(customerVO.getBirthDate())) {
mstCustomer.setDob(DateUtils.getUtilDate(customerVO.getBirthDate()));
}
if (StringUtils.isNotBlank(customerVO.getCity())) {
MstCity city = mstCityRepository.findByName(customerVO.getCity());
mstCustomer.setMstCity(city);
}
Run Code Online (Sandbox Code Playgroud)
会成为
setIfNotBlank(customerVO.getBirthDate(), birthDate -> mstCustomer.setDob(DateUtils.getUtilDate(birthDate)));
setIfNotBlank(customerVO.getCity(), cityName -> {
MstCity city = mstCityRepository.findByName(cityName);
mstCustomer.setMstCity(city);
});
Run Code Online (Sandbox Code Playgroud)
Joh*_*ica 16
这非常适合Optional.首先,创建一个帮助方法将每个可能空白的字段转换为Optional<String>.
Optional<String> optional(String value) {
return StringUtils.isNotBlank(value)
? Optional.of(value)
: Optional.empty();
}
Run Code Online (Sandbox Code Playgroud)
然后,像这样重写代码:
optional(customerVO.getGender()) .ifPresent(mstCustomer::setGender);
optional(customerVO.getBirthDate()).map(DateUtils::getUtilDate)
.ifPresent(mstCustomer::setDob);
optional(customerVO.getAdd1()) .ifPresent(mstCustomer::setAddress1);
optional(customerVO.getAdd2()) .ifPresent(mstCustomer::setAddress2);
optional(customerVO.getAdd3()) .ifPresent(mstCustomer::setAddress3);
optional(customerVO.getPincode()) .ifPresent(mstCustomer::setPinCode);
optional(customerVO.getStateName()).map(mstStateRepository::findByName)
.ifPresent(mstCustomer::setMstState);
optional(customerVO.getCity()) .map(mstCityRepository::findByName)
.ifPresent(mstCustomer::setMstCity);
optional(customerVO.getIdentificationType()).ifPresent(mstCustomer::setIdentificationType);
optional(customerVO.getIdentificationData()).ifPresent(mstCustomer::setIdentificationData);
Optional.of(MstStatusEnum.CUST_ACTIVE.getStatusCode())
.map(mstStatusRepository::findOne)
.ifPresent(mstCustomer::setMstStatus);
optional(customerVO.getMaritalStatus()) .ifPresent(mstCustomer::setMaritalStatus);
optional(customerVO.getWeddingAnniversary()).map(DateUtils::getDateFromString)
.ifPresent(mstCustomer::setWeddingAnniversary);
optional(customerVO.getMotherTongue()).ifPresent(mstCustomer::setMotherTongue);
optional(customerVO.getFamilySize()) .map(Integer::valueOf).ifPresent(mstCustomer::setFamilySize);
optional(customerVO.getAdultsSize()) .map(Integer::valueOf).ifPresent(mstCustomer::setAdultsSize);
optional(customerVO.getNoOfKids()) .map(Integer::valueOf).ifPresent(mstCustomer::setNoOfKids);
optional(customerVO.getChilddob1()) .map(DateUtils::getDateFromString).ifPresent(mstCustomer::setChilddob1);
optional(customerVO.getChilddob2()) .map(DateUtils::getDateFromString).ifPresent(mstCustomer::setChilddob2);
optional(customerVO.getProfession()) .ifPresent(mstCustomer::setProfession);
Run Code Online (Sandbox Code Playgroud)
ifPresent仅当字段为非空时才调用命名函数.map有助于将值从一种类型转换为另一种类型.请注意这有助于使逻辑变平,以便映射与设置分离.
在我看来,这段代码从根本上无法改进.就其本质而言,它是乏味和重复的.它将一个对象的属性转换为另一个对象的属性,而Java根本不提供简短明了的表达方式.
考虑其他答案:他们将原始代码的单个if语句转换为另一个语句,而不是20 if秒,最终会有20 个optional()调用或20个setIfNotBlank()调用 - 但代码的主要问题是有20个长,类似在一个方法中,你仍然以20个长而相似的陈述结束,因此它们没有太大的改进.
您可以转向反射:发明一些注释并用它们注释类customerVO和mstCustomer对象,然后在"对于第一个对象上的每个注释,在第二个对象上找到相应的注释,执行赋值"的静脉中重写此方法. .但现在有20个长长的,相似的if陈述,你有40个长而相似的注释,而且它们分为两个不同的文件.更糟糕的是,如果你选择这样做,试着只注释其中一个类而不是两个类:那么你最终只会有20个注释,所以事情就像以前一样糟糕.
您可以转向代码生成:发明一些简单的属性描述格式(或找到现有的格式),编写一个小工具来获取此描述并生成类customerVO和mstCustomer对象的代码.现在,不再是20个长期,类似的if陈述,你有20个希望简短,可能不是那么相似的属性描述,只有你知道的语言和构建链中的其他工具.
正如你所看到的,你无法逃避写出20个长期无聊的相似外观.
所以我的答案是:不要重构它.将此代码customerVO以及mstCustomer对象的类标记为已连接,并确保始终同步更改它们.这并不意味着为它编写一些单元测试 - 虽然你也应该这样做 - 这意味着建立一个程序.这不再是技术问题:这是一个人的问题.告诉其他开发人员这段代码; 在此代码中写下评论"别忘了检查其他部分"; 使用代码中这些部分的更改来检查提交.您不能依靠自动化工具来保持此代码的正确性,因此您和您的同事必须记住手动执行此操作.
解决这个问题的最简单方法,可以通过为所有这些任务编写setter来实现.
喜欢:
private void setGender(GenderObject customerVO){
if (StringUtils.isNotBlank(customerVO.getGender())) {
this.setGender(customerVO.getGender());
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2291 次 |
| 最近记录: |