写程序这么精简真的好吗?

2019-08-30 09:36:07 +08:00
 wsy190

我有一个同事写代码特别精简。。如:

public OutVoGlobal list(BatteryOrderDTO dto, UserInfo user) {

return new OutVoGlobal(EnumRetCode.SUCCESS).setData(orderMapper.list(dto.setBelong(user.getUserNo())));

}

之后这段代码有一些问题,让我来修改这段代码。。我就觉得这段代码的可读性特别的差。昨天和他讨论了一下,他觉得代码行数多影响阅读,他这样他看起来很舒服。以下是我加了判断后的:

public OutVoGlobal list(BatteryOrderDTO dto, UserInfo user) {

    OutVoGlobal outVoGlobal=new OutVoGlobal(EnumRetCode.SUCCESS);
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    if(!StringUtils.isEmpty(dto.getStartTime())){
        try {
            sdf.parse(dto.getStartTime());
            dto.setStartTime(dto.getStartTime()+" 00:00:00");
        } catch (ParseException e) {
            dto.setStartTime("");
        }
    }
    if(!StringUtils.isEmpty(dto.getEndTime())){
        try {
            sdf.parse(dto.getEndTime());
            dto.setEndTime(dto.getEndTime()+" 23:59:59");
        } catch (ParseException e) {
            dto.setEndTime("");
        }
    }
    dto.setBelong(user.getUserNo());
    PageHelper.startPage(dto.getPageNo(), dto.getPageSize());
    List<BatteryOrder> list=orderMapper.list(dto);
    outVoGlobal.setData(list);
    return outVoGlobal;

}

如果没有改动的话这段代码我一定会这么写:

public OutVoGlobal list(BatteryOrderDTO dto, UserInfo user) {

    OutVoGlobal outVoGlobal=new OutVoGlobal(EnumRetCode.SUCCESS);
    dto.setBelong(user.getUserNo());
    PageHelper.startPage(dto.getPageNo(), dto.getPageSize());
    List<BatteryOrder> list=orderMapper.list(dto);
    outVoGlobal.setData(list);
    return outVoGlobal;
}

确实是代码增加了很多行,但是我觉得这样写当我要进行断点调试的时候会很舒服。而且当别人要改我代码的时候也能一目了然。。 然后他说如果你要加上面的新需求的话可以这么写

public OutVoGlobal list(BatteryOrderDTO dto, UserInfo user) {

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    if(!StringUtils.isEmpty(dto.getStartTime())){
        try {
            sdf.parse(dto.getStartTime());
            dto.setStartTime(dto.getStartTime()+" 00:00:00");
        } catch (ParseException e) {
            dto.setStartTime("");
        }
    }
    if(!StringUtils.isEmpty(dto.getEndTime())){
        try {
            sdf.parse(dto.getEndTime());
            dto.setEndTime(dto.getEndTime()+" 23:59:59");
        } catch (ParseException e) {
            dto.setEndTime("");
        }
    }
   return new OutVoGlobal(EnumRetCode.SUCCESS).setData(orderMapper.list(dto.setBelong(user.getUserNo()))
}

我一想,这么写也可以呢。但是我还是觉得他最后那个 return 看起来太麻烦了,我又没有理由反驳他。 其实在写代码的过程中我发现他有好多的习惯我都不习惯。比如说我一般都是这么写:

OutVoGlobal outVoGlobal=new OutVoGlobal(EnumRetCode.SUCCESS);

…… if(StringUtils.isEmpty(XXX)){

outVoGlobal.setCode("1000");
outVoGlobal.setInfo(XXX+"不能为空");
// return outVoGlobal.setCode("1000").setInfo(XXX+"不能为空");
return outVoGlobal;

} if(StringUtils.isEmpty(SSSS)){

outVoGlobal.setCode("1000");
outVoGlobal.setInfo(SSS+"不能为空");
return outVoGlobal;

} …… return outVoGlobal;

如果我也用了插件的话我会这么写

OutVoGlobal outVoGlobal=new OutVoGlobal(EnumRetCode.SUCCESS);

…… if(StringUtils.isEmpty(XXX)){

return outVoGlobal.setCode("1000").setInfo(XXX+"不能为空");

} if(StringUtils.isEmpty(SSSS)){

 return outVoGlobal.setCode("1000").setInfo(SSS+"不能为空");

} …… return outVoGlobal;

他如果写的话会这么写:(加了 @Accessors(chain = true)的前提下)

…… if(StringUtils.isEmpty(XXX)){

return new OutVoGlobal().setInfo(XXX+"不能为空").setCode("1000");

} if(StringUtils.isEmpty(SSSS)){

 return new OutVoGlobal().setInfo(SSS+"不能为空").setCode("1000");

} …… return new OutVoGlobal(EnumRetCode.SUCCESS);

大家觉得是先把这个变量在开始的时候声明了好还是在用到的时候直接返回好呢?

然后还有别的:

if (userData == null) return outError(outVo, EnumRetCode.NO_REGISTER, "未查询到用户信息, userNo -->{}", user.getUserNo()); else if (!userData.getPwd().equals(pwd = encrypt(user.getUserNo(), user.getPwd())))

        return outError(outVo, EnumRetCode.ERROR_PWD, "密码错误, userNo -->{} | pwdData -->{} | pwdInput -->{}", user.getUserNo(), userData.getPwd(), pwd);

else if (!StringUtils.isEmpty(userData.getOpenId()) && !openid.equals(userData.getOpenId())) // 删除上一个用户信息

        redisUtil.delMapKey(param.getUserKey() + userData.getOpenId(), "userInfo", "null");

这种。。。if 和 else if 他后面都跟了一行,之后 他就省去了{} 他特别喜欢这么写代码。可是我每次看都要自己看一下才知道他是怎么做的。。虽然说他只写了一行,但是我看的时候还是会脑补成我写的那样。。

if (!"0000".equals(TokenUtil.verify(outVo, tokenMap).getCode()))

        return outVo;

他还喜欢把变量声明写在一行上。。

String openid = (String) tokenMap.get("openid"),userMapKey;

这样的代码我找 userMapKey 就很懵逼。。

再贴一段代码: if (userMap == null || userMap.get("userInfo") == null) {

        // 获取已绑定的用户信息
        if ((user = userInfoDao.getByOpenId(openid)) == null) return null;

        redisUtil.saveMapSecond(userMapKey, "userInfo", JSONObject.toJSONString(user), appParam.getCacheTime());

    } else

        user = JSONObject.parseObject(userMap.get("userInfo").toString(), UserInfo.class);

反正我是看不习惯。。。大家觉得呢。这么写是好还是不好呢。。

20349 次点击
所在节点    程序员
149 条回复
v2qwsdcv
2019-08-30 13:50:45 +08:00
笑死我了,您怕是别用 java8 的 steam 了。
ThomasZ
2019-08-30 13:51:19 +08:00
又不是再搞那个最短代码比赛,这样写没有可读性,没有可调试性,单纯炫技不好
519718366
2019-08-30 13:51:35 +08:00
他这一行,到时候 npe 了,天知道是哪个对象 null 了....亲生感受
他要是牛逼,敢保证不会 npe,那你能怎么办,忍着呗,出了 bug,不要给你查就行
yiyi11
2019-08-30 13:52:18 +08:00
个人倾向链式分行,我是分行狂魔,看到链式调用哪怕只有 2 个很短的函数连着都要每个点起一行,而且点必须对齐。
yiyi11
2019-08-30 13:53:31 +08:00
sql 同理,只有 2 个字段的语句也必须一行一个字段。
STRRL
2019-08-30 13:54:10 +08:00
大家说到 NPE 的问题,建议使用 JSR 305 中提到的 @NonNul l 和 @CheckForNull 解决
iblessyou
2019-08-30 13:55:55 +08:00
看了一遍还没人从这个角度提过:

某些公司有代码统计的,这时注释和换行都能给你加代码量,你的写法可以加分。。。
zkqiang
2019-08-30 14:00:29 +08:00
虽然为了精简,嵌套太多,确实不容易看懂
但是一味的追求所谓“可读性”,反而导致代码冗长,一排重复的变量名,那不又是另一个极端?
xpfd
2019-08-30 14:01:13 +08:00
一年后让他再看这段代码 他会骂 这哪个傻逼写的 就不能写的简单点吗? 非要转那么多弯
Rwing
2019-08-30 14:05:09 +08:00
```
public OutVoGlobal list(BatteryOrderDTO dto, UserInfo user) {

var outVoGlobal=new OutVoGlobal(EnumRetCode.SUCCESS);
var sdf = new SimpleDateFormat("yyyy-MM-dd");
if(!StringUtils.isEmpty(dto.StartTime)){
try {
sdf.parse(dto.StartTime);
dto.StartTime = dto.StartTime+" 00:00:00";
} catch (ParseException e) {
dto.StartTime = "";
}
}
if(!StringUtils.isEmpty(dto.EndTime)){
try {
sdf.parse(dto.EndTime);
dto.EndTime = dto.EndTime+" 23:59:59";
} catch (ParseException e) {
dto.EndTime = "";
}
}
dto.Belong = user.UserNo;
PageHelper.startPage(dto.PageNo, dto.PageSize);
List<BatteryOrder> list = orderMapper.list(dto);
outVoGlobal.Data = list;
return outVoGlobal;

}
```

有没有舒服点?
blindie
2019-08-30 14:10:27 +08:00
链式调用这么长不点号对齐写锤子啊,分分钟某个节点看漏
Aixtuz
2019-08-30 14:16:12 +08:00
凡事有度,过犹不及。
Takamine
2019-08-30 14:35:45 +08:00
只要是过了 code review 的,说明是符合团队风格的代码,不要慌。:doge:
broadliyn
2019-08-30 14:37:25 +08:00
@wysnylc
这里的 SimpleDateFormat 并没有竞态问题,为什么不能用??
阿里规范是让你不要在线程不安全的情况下使用 SDF,而不是让你在并发环境下不要用 SDF。
你也是半桶水。
BigDogWang
2019-08-30 14:38:50 +08:00
你们都在这扯个啥,这不是链式不链式的问题,这是链式套链式啊,看的人恶心
whp1473
2019-08-30 14:46:54 +08:00
一、不赞同
1.String openid = (String) tokenMap.get("openid"),userMapKey;❌
2.省略{} if、else 不分行❌
二、争议
return new OutVoGlobal(EnumRetCode.SUCCESS).setData(orderMapper.list(dto.setBelong(user.getUserNo()))); ❌
这种类似风格,写的好很推崇,但写的差很容易写出屎一样的代码。我见过有 100 多行的链式,你读到后面就忘了前面,后来那个写的人也不知道了,哈哈。我觉得原则上支持链式,但是你要拆分的力度适中,5 个左右不超过 10 并且语义明了。
Java 中流式写法更适合数据处理。常用的实例:
widgets.stream()
.filter(b -> b.getColor() == RED)
.sorted((x,y) -> x.getWeight() - y.getWeight())
.mapToInt(Widget::getWeight)
.summaryStatistics();
或者
numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());
你可以看到数据从第一行,到最后一行语义就是逻辑,是由顺序的。
三、分析
return new OutVoGlobal(EnumRetCode.SUCCESS).setData(orderMapper.list(dto.setBelong(user.getUserNo())));
写的问题在哪里,我们分析一下:
执行顺序:创建 OutVoGlobal 返回值——>setData 设置数据——>orderMapper.list 执行——>dto.setBelong 封装 userNo,同时要获取 userNo
在我们眼里的顺序是怎样的,获取 userNo ——>封装——>执行 list ——>封装返回 OutVoGlobal。可以看出它实际上需要逆着思维的顺序,user.getUserNo()这部分如果嵌套过多甚至你需要不断找。所以这种风格有点像用但是没用好的感觉。
四、改造
OrderParamBuilder.Builder().setUserNo(user.getUserNo()).build().list(orderMapper).ifNull(EnumRetCode.ERROR).else(EnumRetCode.SUCCESS);
或者
orderMapper.list(OrderParamBuilder.Builder().setUserNo(user.getUserNo()).build()).****
rainymorn
2019-08-30 14:54:35 +08:00
不喜欢分行,能写到一行的绝不写到多行
多行不利于阅读
freebird1994
2019-08-30 14:56:02 +08:00
链式不链式是一回事。入参不做校验么?一堆异常不给你抛?还是在 controller 层做了校验呢?
其实现在的 java 代码风格越来越偏向链式编程了。我也喜欢用
wsy190
2019-08-30 14:58:00 +08:00
@freebird1994 确实是,controller 层做了 try catch..
wsy190
2019-08-30 14:59:24 +08:00
@whp1473 非常感谢,受益匪浅。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://ex.noerr.eu.org/t/596413

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX