前端重构感想

7,600 阅读5分钟

考拉PC前端重构之路

@(重构)[组件化|拆分]

代码重构是一个产品不断的功能迭代过程中,不可避免的一项工作。所谓重构,是在不改变程序的输入输出即保证现有功能的情况下,对内部实现进行优化和调整。 每个开发人员从业生涯中,或多或少的做过重构工作。小到重写一个功能函数、业务组件,大到重构一个复杂功能模块或整站重构。

重构是需要花费一定成本和精力的,尤其是一个有各种历史遗留问题(用的老旧框架或工具)、又糅杂了各种业务逻辑(有些功能逻辑连需求方都未必清楚)、且可读性及维护性都很差的重要功能模块,比如考拉的下单页,不动,每次功能迭代的时候都有想撞墙的心,大动,又是不小的工作量,且有一定的风险。当然长痛不如短痛,长远来看,重构势在必行。

why 重构

  • 设计不合理or全无设计 :原来的实现方式不合理,或者全无模块拆分、组件提取意识的开发模式,纯粹的业务逻辑堆叠式开发,会导致功能无法重用,代码冗余,不利于维护。
  • 页面结构与功能实现耦合 :脚本文件中夹杂着各种html结构,表现和行为不分离,导致代码可读性和维护性大大下降。(我不会告诉你旧版考拉下单页的入口脚本有2000多行,cry~)。
  • 代码难以理解 :页面没有清晰的入口函数,函数调用关系混乱,无论改bug还是迭代新功能,面对难以理解的代码,开发效率低下。
  • 代码引起性能问题:不合理的实现方式或者大量无用冗余的代码,引起了明显性能问题的,需要即时重构优化。
  • 框架or类库更新:前端的技术框架日新月异,在选择或者淘汰不合适项目的第三方库的时候,也涉及到重构工作。

when 重构

重构工作其实是随时都可进行的。当你觉得代码可读性变差、重用性及可维护性降低时,都应该有意识的去做重构。在大部分的项目中,以下将是重构的合理时间点:

  • 功能迭代时:当添加一个功能时,发现原有的设计无法满足新需求,可以考虑重构;在设计功能组件的时候,可以为未来可能的需求预留接口;
  • 修复bug的时候:bug产生之后,需要思考是否是不合理的编码导致的问题而不单单是以解决bug算完事(当然线上重大bug自然以即时修复为第一要务),可以借助修复bug的契机,把业务逻辑整理清晰,必要时可以找后端配合改接口;
  • code Review阶段:此阶段距离提测时间往往较近,但如果是明显不合理的实现思路,宁愿delay也要重新设计实现;如果前期思考充分,一般不会出现此类情况,大部分是在给其他人review的时候,发现不可理解、可读性差,这也是需要进一步修改重写的。

当然在需求紧急的时候,是不适合做重构的。


do重构

以考拉下单页重构为例。

但凡重构,必须要对已有业务逻辑有较充分的了解,评估重构的影响面及可能的风险, 列出基本功能点(也可作为QA的测试回归点),保证重构后不要有功能遗漏,不改变现有功能。

如何了解已有业务逻辑?

  • 跑线上流程;(有些特殊逻辑,模拟困难)
  • 对照现有的交互稿;(不断的功能迭代,可能找不到完整的交互稿)
  • 读懂已有代码;(全面了解业务逻辑最好的方法,但是耗时)
  • 询问之前的开发者;(如已离职,查找是否有交接文档之类)

功能模块拆分

在对业务逻辑有充分了解之后,可以进行功能拆分,把可重用的、功能独立的业务逻辑作为组件或公用模板提取,同时需要考虑组件之间的相互影响。拆分之后,可以多人并行开发,约定好外部调用组件的接口即可。
以下是下单页的功能模块拆分:

enter image description here
enter image description here

根据同步字段orderType,来确定是普通商品订单还是账号充值订单,并初始化对应的组件;根据同步信息,异步获取下单信息(含商品信息及结算信息);如果是普通商品订单,服务端会根据用户所选地址进行拆单,返回拆单后的商品和结算信息。按功能拆分后,组件及组件的嵌套关系如下:

enter image description here
enter image description here

下单页目录结构:

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

重构从来不是一次性行为,是我们需要不断进行的工作。多人维护以及不断的功能迭代之后,代码多多少少都会有优化的空间,所以在你看到不合理或任何值得重构的地方时,行动起来吧,去优化,不要等到重构的成本更大时再进行,因为那会更痛,不要问我怎么知道。