增加代码的通用性-解析配置文件

813 阅读3分钟

时间:2018年11月02日
比方说有这样一堆数据:

arr: [{
  id: '1',
  type: 'a',
  arr: [1, 2, 3, 4]
}, {
  id: '2',
  type: 'b',
  arr: [1, 2, 3, 4, 5]
}]

集合里面每个元素都有两个属性,一个是type,一个是arrarr是一个数组。
需求是先判断属性,不同属性对arr的长度有着不同的需求。这里我们规定type若是‘a’,arr的长度最多为4。type若是‘b’,arr的长度最多为6;两者的报错内容也并不相同。
我的本意是循环目标数组,之后先判断是否符合type,再判断arr是否符合条件,将不符合条件元素的id存到一个数组中,最后展示出来:

aError = [];
bError = [];
_.each(arr, (op) => {
  if (op.type === 'a') {
    if (op.arr.length > 4) {
      aError.push(op.id);
    }
  }
  if (op.type === 'b') {
    if (op.arr.length > 6) {
      bError.push(op.id);
    }
  }
})
if (aError) {
  const errMsg = `a的报错提示:${aError.join(',')}`;
}
if (bError) {
  const errMsg = `b的报错提示:${bError.join(',')}`;
}

写完之后自我感觉还是不错的,看上去挺清楚的,逻辑什么的也很简单,如果还有其他的再增加就好了。
问题是写完之后和同事讨论了一下,觉得代码的复用性太差,如果有新的条件会增加更多的代码,这种重复造轮子的操作感觉不是很好。所以商讨之后我们决定将条件写成一个配置文件,通过读取配置文件来解析条件,再进行判断。
那么配置文件需要什么内容呢?主要有三部分,type类型、最大arr数量,还有报错信息,所以我们决定了配置文件的格式:

limitRule = {
  a: {
    max: '4',
    errMsg: 'content'
  },
  b: {
    max: '6',
    errMsg: 'content'
  }
}

直接把type类型当做了配置元素的key,减少了一个属性。之后我们就要开始循环配置文件了。

let limitIds = {};
const limitErrMsg = [];
_.each(arr, (op) => {
  if (_.keys(limitRule).includes(op.type)) { //获取到配置文件中所有的类型,之后判断当前类型是否在配置文件中
    if (op.arr.length > limitRule[op.type].max) {
      if (limitIds[op.type]) {
        limitIds[op.type].push(op.id);  //如果已经有这个type就直接push
      } else {
        limitIds[op.type] = [op.id];  //如果没有这个type就新建数组
      }
    }
  }
})

这里的_.keylodash中获取对象key的方法。先判断下当前元素的type是否在配置文件中,如果在再进行下一步判断,判断当前元素数组的长度是不是大于配置文件中当前配置的max值。若是大于,再将当前元素的id放到limitIds对象中,如果limitIds中没有当前类型的数据,则新建一个,若是有则push进去。如此,我们得到的limitIds应该是这样的:

{
  a:[1, 3, 7],
  b: [7, 9, 10]
}

接下来我们处理下limitIds,得到报错信息:

_.mapObject(limitIds, (value, key) => {
  if (value) {
    limitErrMsg.push(`${limitRule[key].errMsg}${value.join(',')}`)
  }
})

如此我们就将所有的报错信息放到limitErrMsg中了,之后输出即可。整体方法是这样的:

//  配置文件
limitRule = {
  a: {
    max: '4',
    errMsg: 'content'
  },
  b: {
    max: '6',
    errMsg: 'content'
  }
};
//  新建存储信息的变量
let limitIds = {};
const limitErrMsg = [];
//  处理数据
_.each(arr, (op) => {
  if (_.keys(limitRule).includes(op.type)) { //获取到配置文件中所有的类型,之后判断当前类型是否在配置文件中
    if (op.arr.length > limitRule[op.type].max) {
      if (limitIds[op.type]) {
        limitIds[op.type].push(op.id);  //如果已经有这个type就直接push
      } else {
        limitIds[op.type] = [op.id];  //如果没有这个type就新建数组
      }
    }
  }
})
//  得到错误信息
_.mapObject(limitIds, (value, key) => {
  if (value) {
    limitErrMsg.push(`${limitRule[key].errMsg}${value.join(',')}`)
  }
})

如此就将不同的判断条件整合成了一个配置文件,之后若是还有类似的配置直接修改配置文件即可,简直不要太方便。