如何组织优雅的代码结构:流程、步骤与函数封装

经常能看到一个方法需要滚动多屏,从开始一直写到结束完全没有封装的代码。不只新手会这样写,一些工作多年的人写业务代码也是这样。他们只在乎能否实现功能,完全不去考虑代码的结构是否优雅,是否容易维护和扩展。

流程、步骤与代码结构

业务代码主要是要梳理清楚流程、清楚每一步都做什么,然后把这些步骤串起来就是完整的代码,之后的扩展也是在这个流程的某一步上扩展。

但很多代码并不能清晰的表达出有哪些主要步骤,或者仅仅靠注释来标明。导致要维护之前的代码需要花很长时间通读之前全部代码才能知道如何扩展。这样的代码结构是不优雅的。理想中的代码结构是应该能清晰反映业务流程的。

代码如何拆分和封装

一个项目应该合理的划分目录,每个目录下合理的划分文件,每个文件有若干类和函数,每个类合理的划分方法,每个方法合理的划分步骤,把一些步骤封装成单独的方法。

每个步骤的方法可能是同步的也可能是异步的,如果是同步的,只需要顺序调用和返回就可以了,如果是异步的,需要使用回调函数、promise等方式,当然也可以借助async和await实现类似同步代码的写法。

每一个功能的实现都需要组合多个步骤的方法,然后每一个大的步骤的实现又可以拆分成一些小的步骤,他们的关系如下图所示,通过合理的拆分和封装,再复杂的逻辑也不会特别混乱。

当然,页面拆分成多个组件、功能拆分成多个项目、项目拆分多个目录都是这样的,通过封装,实现代码的层次化,使得代码的组织结构能清晰的反映逻辑结构。

一个具体的栗子

举个栗子:

需要在点击Tab的时候去执行动画,动画的执行需要先获取tab的left和width,然后生成动画数据和setData,于是我进行了这样的拆分。

handleTabItemTap是处理tab点击的handler,tab切换需要执行一个动画,于是封装了executeAnimation这个方法,然后动画执行又分为获取尺寸、生成动画数据、setData这几步,于是我相应的封装了getLeftAndWidth、generateAnimationData这两个具体步骤的方法。然后在executeAnimation组合实现具体步骤的方法,实现整个功能。逻辑流程从executeAnimation里能很清晰的看出来。

代码如下:

  handleTabItemTap(event) {//处理Tab的tap事件
      const activeIndex = event.target.dataset.index
      const id = event.target.dataset.id

      if(activeIndex === this.data.activeIndex) return

      this.setData({
        activeIndex
      })

      this.triggerEvent('activeIndexChange', id)

      this.executeAnimcation(activeIndex)
    },
    executeAnimcation(activeIndex) {//执行动画
      this.getLeftAndWidth(activeIndex).then(dimension => {
        const indicatorAnamationData = this.generateAnimationData(dimension.left, dimension.width, dimension.firstTabLeft)
        this.setData({
          indicatorAnamationData
        })
      })
    },
    getLeftAndWidth(activeIndex) {//获取Tab的left和width
      return new Promise(resolve => {
        if(this.tabsWidth.length) {
          const currentTabWidth = this.tabsWidth[activeIndex]
          const currentTabLeft = this.tabsLeft[activeIndex]
          resolve({
            width: currentTabWidth,
            left: currentTabLeft,
            firstTabLeft: this.tabsLeft[0]
          })
        }else{
          getRect(this, '.tabs__nav', true).then(res => {
            this.tabsWidth = res.map(item => item.width)
            this.tabsLeft = res.map(item => item.left)
            resolve({
              width: this.tabsWidth[activeIndex],
              left: this.tabsLeft[activeIndex],
              firstTabLeft: this.tabsLeft[0]
            })
          })
        }
      })
    },
    generateAnimationData(left, width, preLeft = 0) {//生成动画相关的数据
      const animation = wx.createAnimation({
        duration: 200,
        timingFunction: 'ease',
      })
      const animationDatas = [
        {
          width: width,
          left: left - preLeft
        }
      ]
      animationDatas.forEach(item => {
        const width = item.width
        const left = item.left
        animation.translateX(left).width(width).step()
      })
      return animation.export()
    }
  }

在需要扩展的时候,只需要找到某一个步骤的某个方法,进行修改就可以了,并不需要读完全部的代码。

其实这就和我之前写的如何写出自我解释性很强的代码一样,通过合理的划分层次和封装、通过合理的命名。使得代码结构就能清晰反映逻辑结构,并不需要靠注释。

总结

理想情况下,代码的组织结构是能清晰反映逻辑结构的,通过合理的拆分和封装、通过合理的命名,使得代码层次特别清晰,扩展的时候不需要读完全部的代码,只需要找到对应的步骤进行修改就可以了。

每一个步骤可能是同步的也可能是异步的,对于异步的代码,可以使用promise进行封装,甚至可以结合async和await来实现同步的写法来书写异步代码。但不管同步还是异步,步骤之间的关系,整个流程的结构都应该通过拆分和封装来使之清晰明了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,284评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,115评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,614评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,671评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,699评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,562评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,309评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,223评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,668评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,859评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,981评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,705评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,310评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,904评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,023评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,146评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,933评论 2 355

推荐阅读更多精彩内容