likes
comments
collection
share

代码编写之优雅论道

作者站长头像
站长
· 阅读数 46

代码编写之优雅论道

前言

作为一位前端农民工,夜以继日的参加代代码搬砖工作也有一年了,渐渐地也意识到一些重复代码编写的痛苦,此贴记录自己利用近一年的代码编写,得出的一些心得。

这里我推荐自己最近在读的小册,通俗易懂的编程“套路“学。带你深入看似高深实则接地气的设计模式原理,在实际场景中内化设计模式的”道“与”术“。学会驾驭代码,而非被其奴役。

场景复现

假设你有一个业务场景,有一个关于商品的操作前端操作业务逻辑,主要涉及到对商品的各种操作,如编辑、查看详情、上传商品图片、删除、上架、成果下架等。这些操作会在前端界面中以不同的按钮或操作触发。

试想你会怎么处理这段业务代码?

需求拆解

首先让我们分析下需求:

这是一个商品,会存在其中以下展示属性:名称、简介、商品图片、存货、上架时间等,其中还要对对应商品有操作列。

首先要定义一个存在这些属性和操作的面板或者卡片,将操作列抽离成一个组件,定义存在的操作列数组。

每个商品都会存在它自己应该展示的操作按钮个数,将商品的操作列表作为一个组件,定义一下按钮的数组,然后点击对应的操作列,将其点击的item通过emit回传到父组件,此时父组件就知道了点击的的是哪个操作。

然后在父组件中通过emit过来的type去做对应的业务逻辑实现。

业务逻辑实现

简易实现思路:

首先按钮组件定义按钮数组列表

    operateList: [
          { type: 1, label: '编辑' },
          { type: 2, label: '详情' },
          { type: 3, label: '上传商品图片' },
          { type: 4, label: '删除' },
          { type: 5, label: '上架' },
          { type: 6, label: '下架' },
        ],

点击对应的item通过emit 将 {type:xx,label:xx} 传给父组件

以下就开始实现主要业务逻辑去进行逻辑分支。

逻辑分支写法一:

// 子组件emit的事件  
toOperation(item, cardData) {
      if (item.type === 1) {
        this.Edit(cardData);
      }else if (item.type === 2) {
        this.Info(cardData);
      } else if (item.type === 3) {
        this.uploadImage(cardData);
      } else if (item.type === 4) {
        this.del(cardData);
      } else if (item.type === 5) {
        this.put(cardData);
      }else if (item.type === 6) {
        this.takeDown(cardData);
      }
    },
  Edit(cardData) {
      api().then()
  },
  Info(cardData) {
       api().then()
  },
  uploadImage(cardData) {
       api().then()
  },
  del(cardData) {
       api().then()
  },
  put(cardData) {
       api().then()
  },
  takeDown(cardData) {
       api().then()
  },

逻辑分支写法二:

toOperation(item, cardData) {
  const operateList = [    { type: 1, label: '编辑', method: 'Edit' },    { type: 2, label: '详情', method: 'Info' },    { type: 3, label: '上传商品图片', method: 'uploadImage' },    { type: 4, label: '删除', method: 'del' },    { type: 5, label: '上架', method: 'put' },    { type: 6, label: '下架', method: 'takeDown' },  ];

  // 根据item.type匹配对应的method
  const matchedOperation = operateList.find(operation => operation.type === item.type);
  if (matchedOperation) {
    const methodName = matchedOperation.method;
    // 调用匹配到的method
    this[methodName](cardData);
  }
},
methods: {
  Edit(cardData) {
    this.compilationEdit(deitApi)
  },
  Info(cardData) {
    this.compilationEdit(infoApi)
  },
  uploadImage(cardData) {
    this.compilationEdit(uploadImageApi)
  },
  del(cardData) {
    this.compilationEdit(delApi)
  },
  put(cardData) {
     this.compilationEdit(putApi)
  },
  takeDown(cardData) {
     this.compilationEdit(takeDownApi)
  },

      
  // 在抽象出公共api调取方法
   publicApiCallback(api){
        api().then()  
  }
},

对比总结

通过以上代码的对比分析,逻辑分支代码一重复代码较多,且后续如果追加操作列,改动会比较多。

相反,观察逻辑分支代码二而言,拓展性相较于代码一好很多。

这种代码组织方式,融合了以下几种设计原则和模式的概念。

以上的代码组织方式遵循前端应用程序中常见的一种模式。虽然它并不严格对应于特定的设计模式,但它融合了几种设计原则和模式的概念:

  1. 关注点分离原则(SoC): 代码将不同的关注点分别放在不同的方法中。每个方法负责特定的操作或动作,这使得代码更易于理解和维护。
  2. 命令模式(松散应用): 类似于EditInfodel等方法,可以松散地与命令模式相关联。在这种模式中,可以将请求封装为一个对象,从而解耦请求的发送者和接收者,被调用时执行操作,并封装了执行这些操作所需的逻辑。
  3. 策略模式(松散应用): 类似于EditInfodel等方法,,类似于封装不同算法(方法)以执行各种操作的策略。可以在上下文中基于需要交替应用不同的策略,与策略模式有一定的相似之处。
  4. 单一职责原则(SRP): 每个方法似乎都有单一的职责,这使得代码更易于维护,并更易于理解。
  5. 开闭原则(OCP): 代码似乎对扩展开放,但对修改封闭。如果需要添加新的操作,可以简单地添加新的方法,而无需修改现有代码。
  6. 方法命名规范: 方法的命名遵循明确的约定,指示其目的,使开发人员更易于理解其功能。

归纳总结

对于业务逻辑代码的实现,可以多加思考,尽量编写出可拓展的代码。

转载自:https://juejin.cn/post/7270366030915158057
评论
请登录