优化实战 第 32 期 - 利用函数组合提升代码可维护性

2,110 阅读2分钟

单个函数的作用和功能相对来说是比较单一的,都应遵循单一职责的设计。

但在解决实际问题时,往往需要多个函数进行嵌套使用,这样就很容易写出不利于维护的洋葱代码,导致其可读性和可扩展性变差

fn5(fn4(fn3(fn2(fn1(x)))))

先内后外,一层一层执行:fn1() -> fn2() -> fn3() -> fn4() -> fn5

函数组合

  • 设计思想

    组合多个函数,同时返回一个新的函数。调用时组合函数的顺序按照 从右向左 执行,右边函数调用后的返回结果作为左边函数的传入参数,严格保证函数的执行顺序

    遵循「多用组合,少用继承」的代码设计原则

  • 核心作用

    将嵌套执行的函数进行扁平化平铺,让代码逻辑更清晰,从而 提高代码的可读性和可扩展性

    把多个功能单一的函数进行组合,来共同完成一个复杂业务目标,体现了 分而治之,合而用之 的微服务思想

  • 应用场景

    将功能复杂的函数拆解成多个功能相对单一的函数,可以进行任意组合,使多个单一的功能函数实现策略化

    {
      test: /\.scss$/,
      use: ["style-loader", "css-loader", "sass-loader"]
    }
    

    经典应用场景:Webpackloader 的加载顺序也是 从右向左 通过函数组合实现的

    compose.jpeg

源码分析及强化

  • 优秀源码

    const compose = (...funcs) => {
      const len = funcs.length
      if (len === 0) {
        return arg => arg
      }
      if (len === 1) {
        return funcs[0]
      }
      return funcs.reduce((a, b) => (...args) => a(b(...args)))
    }
    

    把后一个函数的执行结果作为包裹着前面函数的空函数的参数,传入执行

  • 强化源码

    const compose = (...funcs) => {
      const len = funcs.length
      if (len === 0) {
        return arg => arg
      }
      if (len === 1) {
        return funcs[0]
      }
      return funcs.reduce((a, b) => async (...args) => a(await b(...args)))
    }
    

    由于优秀源码不支持异步函数,所以对其进行适配,以满足更多业务场景

    一起学习,加群交流看 沸点