这一篇,来聊聊混乱的if、else是怎么来的,怎么和他们说再见,以及写的一个工具函数atcon。
一、代码是怎样混乱的
最简单的一个需求:根据活动改变二维码
qrcode = 'img_a';
// 活动二
if (activity === 2) {
qrcode = 'img_b';
// 活动三
} else if (activity === 3) {
qrcode = 'img_c';
// 活动四
} else if (activity === 4) {
qrcode = 'img_d';
// 活动五
} else if (activity === 5) {
qrcode = 'img_e';
// 活动六
} else if (activity === 6) {
qrcode = 'img_f';
}
嗯,这个逻辑看起来还是挺简单的。这时候,我们增加一个变量notice,因为需要根据活动改变文案,而且只在某些特殊情况变更,于是它可能变成了这样子:
qrcode = 'img_a';
notice = '文案一';
// 活动二
if (activity === 2) {
qrcode = 'img_b';
// 活动三
} else if (activity === 3) {
qrcode = 'img_c';
notice = '文案三';
// 活动四
} else if (activity === 4) {
qrcode = 'img_d';
// 活动五
} else if (activity === 5) {
qrcode = 'img_e';
notice = '文案五';
// 活动六
} else if (activity === 6) {
qrcode = 'img_f';
}
看起来也没什么。但是这时候,产品跑来说,活动下线了,二维码需要做区分。于是代码可能又变成了这样子:
qrcode = 'img_a';
notice = '文案零';
// 活动二
if (activity === 2) {
qrcode = 'img_b';
if (isEnd) {
qrcode = 'img_h';
}
// 活动三
} else if (activity === 3) {
qrcode = 'img_c';
notice = '文案三';
if (isEnd) {
qrcode = 'img_i';
}
// 活动四
} else if (activity === 4) {
qrcode = 'img_d';
if (isEnd) {
qrcode = 'img_j';
}
// 活动五
} else if (activity === 5) {
qrcode = 'img_e';
notice = '文案五';
if (isEnd) {
qrcode = 'img_k';
}
// 活动六
} else if (activity === 6) {
qrcode = 'img_f';
if (isEnd) {
qrcode = 'img_l';
}
}
if (isEnd) {
notice = '下线了';
}
是不是开始有点懵逼了?Hold on,隔了几天,产品又跑来跟我们说,活动三、四、五效果不是特别好,我们准备改一版样式,做下ABTEST看看效果。
这意味着我们的代码里又要增加一个变量,于是我们只能说,卧槽。
二、如何改造
或者说,如何在一开始给自己留好后路。
我们先从第1步重新开始,如果用对象保存这些关联,是不是就会简单很多呢。
imgMap = {
'2': 'img_b',
'3': 'img_c',
'4': 'img_d',
'5': 'img_e',
'6': 'img_f'
};
qrcode = imgMap[activity] || 'img_a';
第2步,增加的notice,其实和qrcode没有任何关联。
noticeMap = {
'3': '文案三',
'5': '文案五'
};
notice = noticeMap[activity] || '文案零';
活动下线区分,我们稍稍改变下结构好了,几分钟的事。
imgMap = {
online: {
'2': 'img_b',
// .....etc.
},
offline: {
'2': 'img_h',
// .....etc.
}
};
var noticeMap = {
online: {
'3': '文案三',
'5': '文案五'
},
offline: '下线了'
};
qrcode = imgMap[isEnd ? 'offline' : 'online'][activity] || 'img_a';
if (isEnd) {
notice = noticeMap.offline;
} else {
notice = noticeMap.online[activity] || '文案零';
}
上面,我们的编码方式,整体还是挺不错的,每种状态都差不多能对应一个结果。
但是,有没有发现,我们在notice的处理上,又开始写if、else了。
这里先不提,我们继续下面一步。
如果只是对在线的活动二、三做abtest,并改变里面的二维码和图片,我们该怎么做呢?
如果采用上面imgMap一一对应的关系,数据结构就变成了这样子:
imgMap = {
online: {
'2': {
a: 'img_b',
b: 'img_o'
},
'3': {
a: 'img_b',
b: 'img_p'
},
'4': {
a: 'img_c',
d: 'img_c'
},
// .....etc.
},
offline: {
'2': {
a: 'img_h',
b: 'img_h'
},
'3': {
a: 'img_b',
b: 'img_b'
},
'4': {
a: 'img_c',
d: 'img_c'
},
// .....etc.
}
};
有没有发现,为了保证我们可以一次性访问到具体对应的值,我们做了非常多重复配置。
我们当然不希望进行重复配置,而是希望处理的结构可以像这样简单:
var noticeMap = {
online: {
‘2’: {
a: ‘abtest文案二’
},
‘3’: {
a: ‘abtest文案三’,
b: ‘文案三’
},
‘5’: ‘文案五’
},
offline: ‘下线了’
};
但是我们怎么提取对应的值,又如何避免提取的过程不会出错呢。
像上面notice一样,我们只能写if、else判断代码,外加循环判断对应属性的值是否存在,好像又要重走以前的老路。
三、使用 atcon
atcon就是用来解决这个问题,封装了属性值提取、reduce循环判断等处理,让大家可以拥有清晰美妙的结构的同时,也能非常方便地提取对应条件分支的值。
使用方式:
imgMap = {
online: {
'2': {
a: 'img_b',
b: 'img_o'
},
'3': {
a: 'img_b',
b: 'img_p'
},
'4': 'img_c',
'5': 'img_d',
'6': 'img_e'
},
offline: {
'2': 'img_h',
'3': 'img_i',
'4': 'img_j',
'5': 'img_k',
'6': 'img_l'
},
__DEFAULT__: 'img_a'
};
noticeMap = {
online: {
'2': {
a: 'abtest文案二'
},
'3': {
a: 'abtest文案三',
b: '文案三'
},
'5': '文案五'
},
offline: '下线了'
__DEFAULT__: '文案零'
};
isImg = img => img.search(/\.(png|jpg)$/) !== -1;
isString = str => Object.prototype.toString.call(str) === '[object String]';
qrcode = atcon(imgMap, [isEnd ? 'offline' : 'online', activity, isAbtest ? 'a' : 'b'], isImg);
notice = atcon(noticeMap, [isEnd ? 'offline' : 'online', activity, isAbtest ? 'a' : 'b'], isString);
atcon将我们一开始的默认值,也通过__DEFAULT__的提取,做了指定。因此,复杂的分支判断,只要先通过细致设想的结构,然后与atcon完美地结合起来,就可以开始和if else说再见了。
四、结构变更
如果这时候,需要把所有abtest的a,文案全部改成一样的,而下线的文案保持跟上线的文案一致,我们甚至能够直接改变noticeMap结构。
noticeMap = {
b: {
'3': '文案三',
'5': '文案五'
},
a: '一样的ABTEST文案',
__DEFAULT__: '文案零'
};
notice = atcon(noticeMap, [isAbtest ? 'a' : 'b', activity], isString);
我们改变思路、结构的同时,改变atcon第二个数组参数的数组项位置和数量,就达到了调整复杂if else逻辑的目的。
五、最后
我们不改逻辑,基本不改代码,我们只改配置。
从现在起,告别混乱的if else。
具体见:atcon
思路来源
- 编码 隐匿在计算机软硬件背后的语言 —— 用符号代替语言
- JavaScript设计模式与开发实践 —— 策略模式、职责链模式
- milan-hwj
本文对你有帮助?欢迎扫码加入前端学习小组微信群:
