关于如何将单函数屎山代码行数由120+优化到30+前言 原因:测试提了一个BUG,而当我去解决这个BUG的时,定位到了一
前言
原因:测试提了一个BUG,而当我去解决这个BUG的时,定位到了一个函数
源码如下
function judgeAllEmployee(status: number) {
let flag = false;
let count = 0;
this.dispatchList = [];
if (this.noDispatch) {
for (
let i = 0;
i <
(status === 1 ? this.dataList.length : this.transferDataList.length);
i++
) {
let item = status === 1 ? this.dataList[i] : this.transferDataList[i];
if (status === 2) {
this.dispatchList[i] = {
isa_order_plan_id: item.isa_order_plan_id,
responsible_employee_id: item.responsible_employee_id,
assistant_id: item.assistant_id,
updateEnable: item.updateEnable,
};
} else {
this.dispatchList[i] = {
isa_order_plan_id: item.isa_order_plan_id,
responsible_employee_id: item.responsible_employee_id,
assistant_id: item.assistant_id,
};
}
if (!!item.children && item.children.length > 0) {
this.dispatchList[i].children = [];
for (let j = 0; j < item.children.length; j++) {
let data = item.children[j];
if (data.responsible_employee_id != 0) {
count++;
}
if (status === 2) {
this.dispatchList[i].children[j] = {
isa_order_plan_id: data.isa_order_plan_id,
responsible_employee_id: data.responsible_employee_id,
assistant_id: data.assistant_id,
updateEnable: data.updateEnable,
};
} else {
this.dispatchList[i].children[j] = {
isa_order_plan_id: data.isa_order_plan_id,
responsible_employee_id: data.responsible_employee_id,
assistant_id: data.assistant_id,
};
}
}
} else {
if (item.responsible_employee_id != 0) {
count++;
}
}
}
console.log("已编辑数量" + count);
if (count > 0) {
flag = true;
} else {
flag = false;
}
} else {
for (let i = 0; i < this.dataList.length; i++) {
let item = this.dataList[i];
if (status === 2) {
this.dispatchList[i] = {
isa_order_plan_id: item.isa_order_plan_id,
responsible_employee_id: item.responsible_employee_id,
assistant_id: item.assistant_id,
updateEnable: item.updateEnable,
};
} else {
this.dispatchList[i] = {
isa_order_plan_id: item.isa_order_plan_id,
responsible_employee_id: item.responsible_employee_id,
assistant_id: item.assistant_id,
};
}
if (!!item.children && item.children.length > 0) {
this.dispatchList[i].children = [];
for (let j = 0; j < item.children.length; j++) {
let data = item.children[j];
if (
data.responsible_employee_id != 0 &&
(!data.distributed_by || data.distributed_by == 0)
) {
count++;
}
if (status === 2) {
this.dispatchList[i].children[j] = {
isa_order_plan_id: data.isa_order_plan_id,
responsible_employee_id: data.responsible_employee_id,
assistant_id: data.assistant_id,
updateEnable: data.updateEnable,
};
} else {
this.dispatchList[i].children[j] = {
isa_order_plan_id: data.isa_order_plan_id,
responsible_employee_id: data.responsible_employee_id,
assistant_id: data.assistant_id,
};
}
}
} else {
if (
item.responsible_employee_id != 0 &&
(!item.distributed_by || item.distributed_by == 0)
) {
count++;
}
}
}
console.log("已编辑数量" + count);
if (count > 0) {
flag = true;
} else {
flag = false;
}
}
return flag;
}
该函数的作者早已不见人影,而这个BUG涉及到这个函数的处理,我愣是看了10分钟。觉得这段代码最大的特色就是人和代码有一个能跑的就行
,现在人跑了
。
tips
:我一直本着有需求才执行,倘若这块内容没有问题,想必我肯定是不会去动的。因为轻易的变更原来的内容,是大忌,可能隔两个月,八百里开外客户现场出现了问题,然后追溯一番和你有关系,那就是好心办坏事了。
目标
- 注意代码优化而不是业务优化,保证业务没有变更,仅对代码进行优化
- 代码优化后,再对问题进行定位
第一版
先进行无关业务并且保证不影响原来的功能情况下,进行函数解耦 观察发现屎山中针对xxxx进行了多次相同的处理
this.dispatchList[i].children[j] = {
isa_order_plan_id: data.isa_order_plan_id,
responsible_employee_id: data.responsible_employee_id,
assistant_id: data.assistant_id,
};
而这块的处理也很容易理解,就是根据status,是否增加updateEnable
字段
那么我们剥离出一个公共函数getDispatchItem
处理
function getDispatchItem(item, status) {
return {
isa_order_plan_id: item.isa_order_plan_id,
responsible_employee_id: item.responsible_employee_id,
assistant_id: item.assistant_id,
...(status === 2 && { updateEnable: item.updateEnable })
};
}
然后将这个函数在屎山中替换达到
函数行数由126
->82
function judgeAllEmployee(status: number) {
let flag = false;
let count = 0;
this.dispatchList = [];
if (this.noDispatch) {
for (
let i = 0;
i <
(status === 1 ? this.dataList.length : this.transferDataList.length);
i++
) {
let item = status === 1 ? this.dataList[i] : this.transferDataList[i];
this.dispatchList[i] = getDispatchItem(item, status)
if (!!item.children && item.children.length > 0) {
this.dispatchList[i].children = [];
for (let j = 0; j < item.children.length; j++) {
let data = item.children[j];
if (data.responsible_employee_id != 0) {
count++;
}
this.dispatchList[i].children[j] = getDispatchItem(data, status)
}
} else {
if (item.responsible_employee_id != 0) {
count++;
}
}
}
console.log("已编辑数量" + count);
if (count > 0) {
flag = true;
} else {
flag = false;
}
} else {
for (let i = 0; i < this.dataList.length; i++) {
let item = this.dataList[i];
this.dispatchList[i] = getDispatchItem(item, status)
if (!!item.children && item.children.length > 0) {
this.dispatchList[i].children = [];
for (let j = 0; j < item.children.length; j++) {
let data = item.children[j];
if (
data.responsible_employee_id != 0 &&
(!data.distributed_by || data.distributed_by == 0)
) {
count++;
}
this.dispatchList[i].children[j] = getDispatchItem(data, status)
}
} else {
if (
item.responsible_employee_id != 0 &&
(!item.distributed_by || item.distributed_by == 0)
) {
count++;
}
}
}
console.log("已编辑数量" + count);
if (count > 0) {
flag = true;
} else {
flag = false;
}
}
return flag;
}
function getDispatchItem(item, status) {
return {
isa_order_plan_id: item.isa_order_plan_id,
responsible_employee_id: item.responsible_employee_id,
assistant_id: item.assistant_id,
...(status === 2 && { updateEnable: item.updateEnable })
};
}
第二版
发现“屎山”中存在两处类似的代码
if (!!item.children && item.children.length > 0) {
this.dispatchList[i].children = [];
for (let j = 0; j < item.children.length; j++) {
let data = item.children[j];
if (data.responsible_employee_id != 0) {
count++;
}
this.dispatchList[i].children[j] = getDispatchItem(data, status);
}
} else {
if (item.responsible_employee_id != 0) {
count++;
}
}
if (!!item.children && item.children.length > 0) {
this.dispatchList[i].children = [];
for (let j = 0; j < item.children.length; j++) {
let data = item.children[j];
if (
data.responsible_employee_id != 0 &&
(!data.distributed_by || data.distributed_by == 0)
) {
count++;
}
this.dispatchList[i].children[j] = getDispatchItem(data, status);
}
} else {
if (
item.responsible_employee_id != 0 &&
(!item.distributed_by || item.distributed_by == 0)
) {
count++;
}
}
这块代码的作用是判断子项是否处于派工状态
针对这段代码进行提取公共函数并优化
因为这个函数中大量使用到了临时变量count、this.dispatchList剥离出来的话,入参会很多所以结合在函数内部进行修改
修改完如下,82
->56
function judgeAllEmployee(status: number) {
let flag = false;
let count = 0;
this.dispatchList = [];
const processChildren = (parent, parentIndex) => {
if (!!parent.children && parent.children.length > 0) {
this.dispatchList[parentIndex].children = parent.children.map((child, childIndex) => {
if (child.responsible_employee_id != 0) count++;
return this.getDispatchItem(child, status);
});
} else if (parent.responsible_employee_id != 0 && !parent.distributed_by) {
count++;
}
};
if (this.noDispatch) {
for (
let i = 0;
i <
(status === 1 ? this.dataList.length : this.transferDataList.length);
i++
) {
let item = status === 1 ? this.dataList[i] : this.transferDataList[i];
this.dispatchList[i] = getDispatchItem(item, status)
processChildren(item, i)
}
console.log("已编辑数量" + count);
if (count > 0) {
flag = true;
} else {
flag = false;
}
} else {
for (let i = 0; i < this.dataList.length; i++) {
let item = this.dataList[i];
this.dispatchList[i] = getDispatchItem(item, status)
processChildren(item, i)
}
console.log("已编辑数量" + count);
if (count > 0) {
flag = true;
} else {
flag = false;
}
}
return flag;
}
function getDispatchItem(item, status) {
return {
isa_order_plan_id: item.isa_order_plan_id,
responsible_employee_id: item.responsible_employee_id,
assistant_id: item.assistant_id,
...(status === 2 && { updateEnable: item.updateEnable })
};
}
第三版(最终版)
现在针对代码复用已经更改好了,再仔细看一下细节的内容
- 发现
flag
和count
的冲突。(变量作用相同,重复声明) - 大量使用
for循环,而不是forEach
;(尽量使用更简洁的语法) - 关于循环的数组,要根据
noDispatch&&status
进行判断(判断冗余) 那么直接优化为
const list = status === 1 ? this.dataList : this.transferDataList;
最终版,由最开始的126
->30+
judgeAllEmployee(status) {
let count = 0;
this.dispatchList = [];
const list = status === 1 ? this.dataList : this.transferDataList;
const processChildren = (parent, parentIndex) => {
if (!!parent.children && parent.children.length > 0) {
this.dispatchList[parentIndex].children = parent.children.map((child, childIndex) => {
if (child.responsible_employee_id != 0) count++;
return this.getDispatchItem(child, status);
});
} else if (parent.responsible_employee_id != 0 && !parent.distributed_by) {
count++;
}
};
if (this.noDispatch) {
list.forEach((item, index) => {
this.dispatchList[index] = this.getDispatchItem(item, status);
processChildren(item, index);
});
} else {
this.dataList.forEach((item, index) => {
this.dispatchList[index] = this.getDispatchItem(item, status);
processChildren(item, index);
});
}
console.log("已编辑数量: " + count);
return count > 0;
}
getDispatchItem(item, status) {
return {
isa_order_plan_id: item.isa_order_plan_id,
responsible_employee_id: item.responsible_employee_id,
assistant_id: item.assistant_id,
...(status === 2 && { updateEnable: item.updateEnable })
};
}
后续优化点
当前基于不更改原函数的逻辑情况下,已经优化完成,但仍有继续优化的点。
- 这个函数并没有执行
单一原则
,关于这点还可以继续优化,根据这个函数名称可以判断作者的本意应该是判断状态,而不是组装数据。 - 在函数内部直接赋值全局变量
this.dispatchList
的数据,倘若这个数据出现问题,这个定位将十分痛苦。 - 关于注释,因为避免业务泄漏,我就全删掉了(你要认真读,也能理解)
总结
所幸这只是涉及到一个函数的更改,更多情况下,倘若业务足够复杂,那简直不敢想象。针对这块“屎山”优化也是因为只是单个函数
,我还能够熟悉这块业务
功能。所以当真的遇到更复杂的情况下,还是得思考一下。
而关于代码优化的思路,更变相于Code Review。
转载自:https://juejin.cn/post/7418895124527153171