代码精进之路-函数

69410434bc950c31937765f10513260e.png

编写好函数是编写好代码的基础,一个系统容易腐化的部分正是函数。

不解决函数的复杂性,就很难解决系统的复杂性。

虽然函数不像面向对象技术那么复杂,但要写好函数也不是一键容易的事情。

好的函数能大大降低阅读代码的困难度,提升代码的可读性。

一、封装判断

如果没有上下文,if和while语句中的布尔逻辑和代码块就难以理解,如果把解释条件意图作为函数抽离出来,用函数名把判断条件的语义线性化的表达出来,就能立即提升代码的可读性和可理解性。例如下面的简单代码,通过抽取checkJob和fillDefaultValue函数使代码的可读性大大提高,将来增加新的逻辑越多,这种好处越明显:

@Override
    public void createJob(JobDto job) {
        //参数合法性校验
        checkJob(job);
        //填充默认值
        fillDefaultValue(job);
        //持久化
        edfOperationDbGateway.createJob(job);
    }


    private void checkJob(JobDto job) {
        List<SysDataSourceDto> shardingDbInfo = edfSystemDbGateway.listShardingDbInfo();
        boolean fromMatch = shardingDbInfo.stream().anyMatch((ds) -> {
            return job.getFromDatabaseDbkey().equalsIgnoreCase(ds.getDbkey());
        });
        if (!fromMatch) {
            throw new RuntimeException("源库dbkey"+job.getFromDatabaseDbkey()+"不存在");
        }


        boolean toMatch = shardingDbInfo.stream().anyMatch((ds) -> {
            return job.getToDatabaseDbkey().equalsIgnoreCase(ds.getDbkey());
        });
        if (!toMatch) {
            throw new RuntimeException("目标dbkey"+job.getToDatabaseDbkey()+"不存在");
        }
    }
    
    private void fillDefaultValue(JobDto job) {
            job.setJobId(UUIDUtil.getUUID());
            job.setJobStatus(ConstantUtil.status_ready_not);
            job.setCreateTime(LocalDateTime.now().toString());
    }

二、函数参数

最理想的参数数量使零,其次是一元函数,再次是二元函数,尽量避免三元函数。当然这不是绝对的,有足够理由的时候也可以使用三元函数,避免教条主义。

总体来说,参数越少,越容易理解,函数越容易使用和测试。

如果函数需要3个以上参数,一般情况下就可以考虑将参数封装成类了。

三、短小的函数

显然短小的函数更易于理解和维护。

大部分情况下,你只需要把长方法改成多个短方法,代码的可读性就能大大提高,前面也说过了,分解后的短方法就显性化的解释了这段代码的含义,一目了然。

函数的代码行数多长才算合适呢?

没有绝对值,但最好不超过20行。

如果你的团队坚持这个标准,代码可读性将大大提高。

四、职责单一

一个方法只做一件事情,这是单一职责原则SRP,大家都知道。

五、精简辅助代码

优化判空代码、优化缓存代码、通过注解优雅降级、异常处理

六、组合函数模式

组合函数模式是一个成本低、容易上手、实用,对代码可读性和可维护性起到立竿见影效果的编程原则。

组合函数要求所有公有函数(public)读起来像一本书的目录,而这些目录的真正实现细节全部位于私有函数中。

最典型的例子可以是Spring的 AbstractApplicationContext的refresh函数,通过10多个子函数,将复杂的过程清晰的展示了出来。

七、SLAP 抽象层次一致性原则

SLAP是和组合函数模式密切相关的一个原则。组合函数要求将大函数拆分成多个小函数,而SLAP就是用来指导如何拆分更合理更优雅的,它要求函数体内的内容必须要在同一个抽象层次上。这就相当于一本书的一级目录二级目录三级目录 再同一个抽象层次上,如果一级目录和三级目录编排在了同一个函数体内,就会显得逻辑凌乱,难以理解。

当你的代码满足组合函数模式和SLAP时,你的代码就构筑了一个完美的金字塔,自上而下富有层次感,易读好理解。

八、函数式编程

函数式编程和面向对象编程并没有本质上的区别。在函数式编程中,函数不仅可以调用函数,而且还可以作为参数被其它函数调用。它和传递对象的唯一区别就是只有方法(函数)没有属性(数据),更深层次理解是传递的只有指令没有数据(老吕说的)

函数式的风格可以让代码更加整洁(见解)优雅。

例子:

实现 String 转换 Integer的功能。

1)经典类实现
Function<String,Integer>  strToIntClass = new StrToIntClass();
public    static  class  StrToIntClass implements  Function  <String,Integer> {
        @Override
        public  Integer  apply(String s){
           return  Integer.parseInt(s);
         }
}


2)匿名类实现


Function<String,Integer>  strToIntClass =   new  Function  <String,Integer> {
       @Override
        public  Integer  apply(String s){
           return  Integer.parseInt(s);
         }
}


3)Lamda 实现


Function<String,Integer>  strToIntClass = s->  Integer.parseInt(s);


4)方法引用实现


Function<String,Integer>  strToIntClass =  Integer::parseInt;

8b43eec4c7ac8b2225bdee47a8a81a8c.png

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吕哥架构

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值