考拉PC前端重构之路
@(重构)[组件化|拆分]
代码重构是一个产品不断的功能迭代过程中,不可避免的一项工作。所谓
重构
,是在不改变程序的输入输出即保证现有功能的情况下,对内部实现进行优化和调整。 每个开发人员从业生涯中,或多或少的做过重构工作。小到重写一个功能函数、业务组件,大到重构一个复杂功能模块或整站重构。
重构是需要花费一定成本和精力的,尤其是一个有各种历史遗留问题(用的老旧框架或工具)、又糅杂了各种业务逻辑(有些功能逻辑连需求方都未必清楚)、且可读性及维护性都很差的重要功能模块,比如考拉的下单页,不动,每次功能迭代的时候都有想撞墙的心,大动,又是不小的工作量,且有一定的风险。当然长痛不如短痛,长远来看,重构势在必行。
why 重构
- 设计不合理or全无设计 :原来的实现方式不合理,或者全无模块拆分、组件提取意识的开发模式,纯粹的业务逻辑堆叠式开发,会导致功能无法重用,代码冗余,不利于维护。
- 页面结构与功能实现耦合 :脚本文件中夹杂着各种html结构,表现和行为不分离,导致代码可读性和维护性大大下降。(我不会告诉你旧版考拉下单页的入口脚本有2000多行,cry~)。
- 代码难以理解 :页面没有清晰的入口函数,函数调用关系混乱,无论改bug还是迭代新功能,面对难以理解的代码,开发效率低下。
- 代码引起性能问题:不合理的实现方式或者大量无用冗余的代码,引起了明显性能问题的,需要即时重构优化。
- 框架or类库更新:前端的技术框架日新月异,在选择或者淘汰不合适项目的第三方库的时候,也涉及到重构工作。
when 重构
重构工作其实是随时都可进行的。当你觉得代码可读性变差、重用性及可维护性降低时,都应该有意识的去做重构。在大部分的项目中,以下将是重构的合理时间点:
- 功能迭代时:当添加一个功能时,发现原有的设计无法满足新需求,可以考虑重构;在设计功能组件的时候,可以为未来可能的需求预留接口;
- 修复bug的时候:bug产生之后,需要思考是否是不合理的编码导致的问题而不单单是以解决bug算完事(当然线上重大bug自然以即时修复为第一要务),可以借助修复bug的契机,把业务逻辑整理清晰,必要时可以找后端配合改接口;
- code Review阶段:此阶段距离提测时间往往较近,但如果是明显不合理的实现思路,宁愿delay也要重新设计实现;如果前期思考充分,一般不会出现此类情况,大部分是在给其他人review的时候,发现不可理解、可读性差,这也是需要进一步修改重写的。
当然在需求紧急的时候,是不适合做重构的。
do重构
以考拉下单页重构为例。
但凡重构,必须要对已有业务逻辑有较充分的了解,评估重构的影响面及可能的风险, 列出基本功能点(也可作为QA的测试回归点),保证重构后不要有功能遗漏,不改变现有功能。
如何了解已有业务逻辑?
- 跑线上流程;(有些特殊逻辑,模拟困难)
- 对照现有的交互稿;(不断的功能迭代,可能找不到完整的交互稿)
- 读懂已有代码;(全面了解业务逻辑最好的方法,但是耗时)
- 询问之前的开发者;(如已离职,查找是否有交接文档之类)
功能模块拆分
在对业务逻辑有充分了解之后,可以进行功能拆分,把可重用的、功能独立的业务逻辑作为组件或公用模板提取,同时需要考虑组件之间的相互影响。拆分之后,可以多人并行开发,约定好外部调用组件的接口即可。
以下是下单页的功能模块拆分:
![enter image description here](http://www.mk2048.com/web_upload/blog_imgs/10/https___user-gold-cdn-xitu-io_2017_10_13_fe8d4d1b72024d08dbc0bcd4b3c07ce6.gif)
根据同步字段orderType,来确定是普通商品订单还是账号充值订单,并初始化对应的组件;根据同步信息,异步获取下单信息(含商品信息及结算信息);如果是普通商品订单,服务端会根据用户所选地址进行拆单,返回拆单后的商品和结算信息。按功能拆分后,组件及组件的嵌套关系如下:
![enter image description here](http://www.mk2048.com/web_upload/blog_imgs/10/https___user-gold-cdn-xitu-io_2017_10_13_c3fd29994e3f7bb6b7e28a9629f0b173.gif)
下单页目录结构:
javascript
|——components
| |——address/address.js //地址控件
| |——checkcode/checkcode.js //验证码控件
|——page/order
| |——order_confirm.js //入口脚本
| |——components
| | |——confirmGoods.js html //确认商品信息
| | |——settlement.js html //结算信息
| | |——exchangeCoupon.js html //兑换优惠券
| | |——rechargeInfo.js html //账号充值
| | |——invoiceInfo.js html //发票信息
| | |——invoice.js html //设置发票
| | |——bean.html //考拉豆抵扣
| | |——feeList.html //运费税费列表
| | |——gift.html //赠品信息
| | |——useCoupon.js html //使用优惠券
| | |——submitCB.js //提交回调
| |——widget
| | |——popCoupon.js //弹窗领券
after 重构
- 入口明确,调用关系清晰,查找方便
- 功能实现与结构不耦合,可读性增强
- 组件化后,有利于功能重用
- 提升了编码体验,维护及功能迭代不再感觉煎熬o(^▽^)o
last
重构从来不是一次性行为,是我们需要不断进行的工作。多人维护以及不断的功能迭代之后,代码多多少少都会有优化的空间,所以在你看到不合理或任何值得重构的地方时,行动起来吧,去优化,不要等到重构的成本更大时再进行,因为那会更痛,不要问我怎么知道。
更多专业前端知识,请上 【猿2048】www.mk2048.com