[看故事学技术]南柯一梦后我决定看看800多个bug
在原来的幻想中,国庆黄金周一定是带着三两好友,四处游山玩水。然而一个电话打破了我所有的幻想,本来已经已经收拾妥当,就准备第二天一早就出发嗨,晚上正准备休息的时候,我们组长打来钉钉电话,组长说:“xxx, 上面有一个紧急项目,国庆能不能加班支持下不,差不多二三天的样子”。
事情原委
由于整个互联网的环境不景气,所以在二三线的大部分公司或者是员工都略显艰难。我们公司大部分业务都是外包出去的并且大部分项目都是都是政府项目,基本靠政府养活,一些项目的钱也没有结算给外包,所以导致国庆加班的时候叫外包加班叫不动,然后就把这些项目丢给了我们。原本以为会是很简单的事情,但是由于自己的疏忽出了不少问题(懈怠了)。 连从三号忙到六号,总算是把接口对完了,按照以往的经验应该先自测一番再提测,但时间不允许,自己也很自信的把项目打包了出去。
南柯一梦
连续几天的加班之后,已经很困了,连洗漱都没有,就一头倒在了床上。 “呼呼呼”,秋风吹打着我白嫩的脸庞,双手撑着脑袋瘫靠山顶核桃树下,旁边放着一筐猪草,望着山底下层层叠叠的房屋。然而我却无法欣赏这种孤寂的美景,我眼里只有一间小楼房,正目不转睛的盯着它,因为那是我们班花家的房子,尽管我们什么都没有发生,但我依旧对未来的生活充满着憧憬,我脑子全是她,”她在干嘛呢,我要是视力再好一点,说不定就能看到她了“。我就这样思念着,在各种憧憬下的驱使下我决定我要勇敢一次,我跑到父母的窗前拿起我爸的发胶,喷一下就把头发往后撸,一连喷了十几下(像一个炸毛的刺猬),自信满满的想着:“小样我这还不迷死你”,然后穿起我的小学校服,就从山上溜达到了班花家的门口,迈着自信的小步伐,走过去,看了下窗子里没有她的身影,然后又走回来。来来回回好几趟,我自信心都没了。心里想着完了她肯定不喜欢我,连我这么帅的身影都没有注意到。 恍惚间我来到了教室,她正给我递来一个本子,无意间我的手碰到她的小手,冰冰凉凉的感觉让我脸直接红到耳根,她轻轻缩了下了,我又轻轻碰上去,就这样本子掉在地上,我的心也掉在了地上。 沉默了半晌之后,我回到来到初中上学那条小路上,手上拿着上课与暗恋对象互相传递的纸条,睁眼想看清但是却一直看不清,只是嘴里一直嘿嘿嘿的笑,终于我来到她的楼下,斜眼看着三楼窗户的情况,今天没拉窗帘应该是起床了。真希望她出现在窗户边注视着我,然而她没有出现只是在我转头确认她在不在的时候,她猛的拉上窗帘。看到这一幕不知道为什么我感觉生气、绝望并心态在路边站了许久。到了中午实在受气不过,直接发了条短信给她:你就那么讨厌我吗?半睡半醒难过彷徨间我看到那张微胖齐刘海的轮廓,似乎渐行渐远。 “叮叮叮”,原来是一场梦啊。心里默念对不起,居然敢瞒着女友梦到别的女人。
如何优化好代码,减少bug
bug满天飞
外包的项目看到就头皮发麻了,但是自己贡献的也不少啊,四五十个bug全是自己写的。什么时候开始不严谨的呢。可能是疫情期间闲了一个月让自己变懒了,懒得优化懒得自测,加上产品反复修改,就形成恶性循环。此后疼定思疼决定记录下那些优化点,形成文档尽力减少自己的bug量。
优化之代码结构
有关判断的优化
// 优化前
if (type ==== "1" || type === "100" || type === 1000) {
setName()
}
// 优化后
["1", "100", 1000].includes(type) ? setName() : ""
// 优化前
if (type === "a") {
name = "张三"
} else if (type === "b") {
name = "张三1"
} else if (type === "c") {
name = "张三2"
} else if (type === "d") {
name = "张三3"
}
// 优化后
let arr = { a: "张三", b: "张三1", c: "张三2", d: "张三3" }
name = type? arr[type] : ""
// 优化前
if (a && a.b && a.b.c && a.b.c.length) {}
//优化后
if ( a?.b?.c?.length) {}
// 优化前
if ( type !== null || type !== undefined || type !== '') {
name = type
}
//优化后
let name = type || "“
有关循环的优化
// 1.普通for循环使用forEach map代替
// 优化前
for (let i = 0; i < arr.length; i++) {
arr[i] = xxx
}
// 优化后
arr.forEach(e => { e = xxx })
// 查找下标使用findIndex 感觉这个平时用得比较多
// 优化前
for (let i = 0; i < arr.length; i++) {
if (arr[i].key === "nisi") {
setName(i)
}
}
// 优化后
let i = arr.findIndex(e => e.key === "nisi")
setName(i)
// 利用reduce累加/累乘
let sum = add([1, 2, 3, 4, 5])
function add(...vals) {
return vals.reduce((t, v) => t + v, 0)
}
// 数组成员特性分组 reduce能做的挺多 这里参照
// https://juejin.cn/post/6844904063729926152#heading-16
function Group(arr = [], key) {
return key ?
arr.reduce((t, v) => (!t[v[key]] && (t[v[key]] = []),
t[v[key]].push(v), t), {}) : {};
}
const arr = [{ area: "GZ", name: "YZW", age: 27 },{ area: "GZ", name: "TYJ", age: 25 },{ area: "SZ", name: "AAA", age: 23 },{ area: "FS", name: "BBB", age: 21 },{ area: "SZ", name: "CCC", age: 19 }];
// 以地区area作为分组依据
Group(arr, "area"); // { GZ: Array(2), SZ: Array(2), FS: Array(1) }
其他的一些代码优化以及一些需要主要的点
// 多个this.xxx 使用时可以使用解构
const { a, b, c } = this
// 多个异步函数优化
async name (){
let a = await one()
let b = await two(a)
let c = await other(b)
}
// new Set 无法对数组内的引用对象去重 可以使用
import _ from 'lodash';
let objects = [{ 'a': 1, 'b': 2 }, { 'a': 2, 'b': 1 }, { 'a': 1, 'b': 2 }]
_.uniqWith(objects, _.isEqual);
使用forEach时需要注意的点
- forEach 只能改变数组内的引用类型
- forEach 不支持链式操作
let arr = [1, 2, 3]
arr.forEach(e => e = e + 1)
console.log(arr)
// 结果[1, 2, 3]
//不支持
arr.forEach().filter()
//支持
arr.filter().forEach()
使用map需要注意的点
- map不改变原数组
- map必须要return,才能正常赋值
页面、数据结构与代码优化
接手屎山
拿到外包uniapp项目一瞬间我和同事是绝望的,当时产品说:“外包已经写了一些页面的,你们改改就能用了”。我们试着改了一些,然而大量的耦合代码,以及修改时需要大量搜索变量,赘余的代码写法让我们很是绝望,且上面的代码只是冰山一角。
我们决定重写吧,这样不至于后期bug很难去修改。
重构代码
左边的图是个大的填写表单,分四个大模块,有些模块有延伸的子表单(都是填报的子表单),每一个表单都有单独的接口,并且拥有大量的工资计算已经下拉框。 由于我们接到紧急需要所有导致一开始的思路出了问题,我们对这个表单做以下拆
- 每个表单作为一个子组件
- 每个接口单独在子组件里提交修改
- 主表单独修改
form: {},
form1: {},
form1: {},
form2: {},
form3: {},
当写完大部分数据就隐约意识到不太对劲,没错虽然后端接口是分开的,但是产品要求的是一起提交包括所有的接口,当时为了追求方便,就把所有子组件数据api全部传到父组件去提交,导致很多组件之间很多数据交互,就容易出现缺陷。
- 这样所有的校验也得提交到总表校验
- 所有的异步提交到总表校验
- 组件间交付复杂
后续决定再重构一下代码
- 每个子组件作为主表单的一部分,
- 这样验证就不能提交到总表
- 接口也可以在校验后找到相应的表提交
- 兄弟组件间也不会有大量的数据流动
form: {
form1: {},
form1: {},
form2: {},
form3: {},
}
开发时如何兼顾细节
如果说我们要开发如上表单,该如何下手(个人意见):
- 确定好需求,以及和后端商量清楚数据结构。每种数据对应的表单项验证规则不同,展示形式不同。而确定好需求,是为了把控那些可变项,如某些字段的新增或者扩展
- 确定自己已经理解需求,能完整的叙述整个逻辑流程,能将整个代码数据流通的逻辑走一遍(这样就能保证各个组件间数据耦合性不高)
- 开始开发样式,先画整体的块,然后写局部时样式一次性处理好,不要留到后面慢慢改,开发完要注意分辨率的影响
- 确定整体组件、数据结构的拆分,数据的流通。
- 模拟数据开始处理业务逻辑,在处理局部块时一点要写完一块测试一块,保证后面不会因局部而引起整体的不确定性
- 对于表单提报的数据项要注意规则的上下限
- 对接口,对数据的失败成功做不同判断
- 整体性自测
自测点
- 文字信息自测包括长度限制
- 样式兼容性
- 浏览器或者手机兼容性
- 基本的crud
- 不同块之间的交互测试
- 整体风格等测试
总结
- 写代码时要考虑好数据全局与局部的关系
- 合理拆分组件不要过细
- 重复组件一定要拆分,不然一次改动就要改变多个地方
- 合理的运用lodash这些库
- 减少数据流动
转载自:https://juejin.cn/post/7156047798423519268