代码编写之优雅论道
代码编写之优雅论道
前言
作为一位前端农民工,夜以继日的参加代代码搬砖工作也有一年了,渐渐地也意识到一些重复代码编写的痛苦,此贴记录自己利用近一年的代码编写,得出的一些心得。
这里我推荐自己最近在读的小册,通俗易懂的编程“套路“学。带你深入看似高深实则接地气的设计模式原理,在实际场景中内化设计模式的”道“与”术“。学会驾驭代码,而非被其奴役。
场景复现
假设你有一个业务场景,有一个关于商品的操作前端操作业务逻辑,主要涉及到对商品的各种操作,如编辑、查看详情、上传商品图片、删除、上架、成果下架等。这些操作会在前端界面中以不同的按钮或操作触发。
试想你会怎么处理这段业务代码?
需求拆解
首先让我们分析下需求:
这是一个商品,会存在其中以下展示属性:名称、简介、商品图片、存货、上架时间等,其中还要对对应商品有操作列。
首先要定义一个存在这些属性和操作的面板或者卡片,将操作列抽离成一个组件,定义存在的操作列数组。
每个商品都会存在它自己应该展示的操作按钮个数,将商品的操作列表作为一个组件,定义一下按钮的数组,然后点击对应的操作列,将其点击的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()
}
},
对比总结
通过以上代码的对比分析,逻辑分支代码一重复代码较多,且后续如果追加操作列,改动会比较多。
相反,观察逻辑分支代码二而言,拓展性相较于代码一好很多。
这种代码组织方式,融合了以下几种设计原则和模式的概念。
以上的代码组织方式遵循前端应用程序中常见的一种模式。虽然它并不严格对应于特定的设计模式,但它融合了几种设计原则和模式的概念:
- 关注点分离原则(SoC): 代码将不同的关注点分别放在不同的方法中。每个方法负责特定的操作或动作,这使得代码更易于理解和维护。
- 命令模式(松散应用): 类似于
Edit
、Info
、del
等方法,可以松散地与命令模式相关联。在这种模式中,可以将请求封装为一个对象,从而解耦请求的发送者和接收者,被调用时执行操作,并封装了执行这些操作所需的逻辑。 - 策略模式(松散应用): 类似于
Edit
、Info
、del
等方法,,类似于封装不同算法(方法)以执行各种操作的策略。可以在上下文中基于需要交替应用不同的策略,与策略模式有一定的相似之处。 - 单一职责原则(SRP): 每个方法似乎都有单一的职责,这使得代码更易于维护,并更易于理解。
- 开闭原则(OCP): 代码似乎对扩展开放,但对修改封闭。如果需要添加新的操作,可以简单地添加新的方法,而无需修改现有代码。
- 方法命名规范: 方法的命名遵循明确的约定,指示其目的,使开发人员更易于理解其功能。
归纳总结
对于业务逻辑代码的实现,可以多加思考,尽量编写出可拓展的代码。
转载自:https://juejin.cn/post/7270366030915158057