后端与系统架构图文讲义4063 字

阿里内部代码重构最佳实践

·全库 588 / 611

《阿里内部代码重构最佳实践》共 8 页、0.4 万字,通篇围绕 成本、场景、权限、评估 展开,归在「后端与系统架构」这一层。

覆盖成本场景权限评估日志ROI

适合给 AI 系统搭底座、要管得住的人

目录骨架(7 节)
  1. 重构代码,让开发效率倍增
  2. 3.2 提升可读性
  3. 四、思考总结
  4. 一、重构的定义
  5. 二、为什么要重构
  6. 三、重构实践
  7. 4.1 去除重复代码

原 PDF 已逐页还原成图,共 8 页,这里先放前 3 页,其中 2 页识别出了标题。右侧文字由 OCR 按版面重排,可能有个别错字,以图为准;点图可全屏放大。

本讲义目录 · 3 页
  1. 01重构代码,让开发效率倍增
  2. 02public Checkstorag…
  3. 033.2 提升可读性
011 / 3
第 1 页:重构代码,让开发效率倍增
第 1 页

重构代码,让开发效率倍增

一、重构的定义

在《重构:改善既有代码的设计》这本书中给出了重构的定义:对软件内部结构的一种调整,目的是在 不改变软件可观察前提下,提高其可理解性,降低其修改成本。每个人对重构有自己的理解,我理解的 重构:重构是一种在不改变代码本身执行效果的前提下,让代码变得更加整洁易懂的方式。代码不仅要 让机器能够实现预期的处理逻辑,更要能够面向开发人员简洁易懂,便于后期维护升级。

二、为什么要重构

书中的一句话印象很深刻,“减少重复代码,保证一种行为表述的逻辑只在一个地方出现,即使程序本身 的运行时间、逻辑不会有任何改变,但減少重复代码可以提高可读性,降低日后修改的难度,是优秀设 计的根本”。重构本身可能不会改变代码实际的执行逻辑,也不一定会对性能产生优化,为什么一定要对 代码的整洁度、可复用性如此执着?结合书中的答案以及工作中的体会,主要有以下几点: 2.1 提升开发效率 在日常研发过程中,首先需要理解已有代码,再在已有代码基础上进行功能迭代升级。在开发过程中, 大部分时间用于阅读已有代码,代码的可读性必然会影响开发效率。而在项目进度紧张的情况下,为保 证功能正常上线,经常会出现过程中的代码,可读性不强。如果没有后续重构优化,在项目完成一段时 间后,当初的开发同学都很难在短时间内从代码看出当初设计时主要的出发点和以及需要注意的点,后 续维护成本高。因此,通过重构增强代码的可读性,更便于后续维护升级,也有助于大部分问题通过 CodeReview 阶段得以发现、解决。

2.2 降低修改风险 代码的简洁程度越高、可读性越强,修改风险越低。在实际项目开发过程中,由于时间紧、工期赶,优 先保证功能正常,往往权衡之下决定先上线后续再重构,但随着时间的推移实际后续再进行修改的可能 性很低,暂且不谈后续重构本身的 ROI,对于蚂蚁这种极重视稳定性的公司,后续的修改无疑会带来可能 的风险,秉持着”上线稳定运行了那么久的代码,能不动尽量不要动”的思想,当初的临时版本很有可能就 是最终版本,长此以往,系统累积的临时代码、重复代码越来越多,降低了可读性,导致后续的维护成 本极高。因此,必要的重构短期看可能会增加额外成本投入,但长期来看重构可以降低修改风险。

三、重构实践

3.1 减少重复代码 思前想后,重构例子的第一条,也是个人认为最重要的一条,就是减少重复代码。如果系统中重复代码 意味着增加修改风险:当需要修改重复代码中的某些功能,原本只应需要修改一个函数,但由于存在重 复代码,修改点就会由 1 处增加为多处,漏改、改错的风险大大增加。减少重复代码主要有两种方法,一 是及时删除代码迁移等操作形成的无流量的重复文件、重复代码;二是减少代码耦合程度,尽可能使用 单一功能、可复用的方法,坚持复用原则。 问题背景:在开发过程中,未对之前的代码进行提炼复用,存在重复代码。在开发时对于刚刚接触这部 分代码的同学增加了阅读成本,在修改重复的那部分代码时,存在漏改、多处改动不一致的风险。 public PhotoHomeInitRes photoHomeInit (){ if (!photobrm.inuserPhotowhitelist (Sessionutil.getuserId ())){ Loggerutil.info (LOGGER,"[ PhotoFacade ]用户暂无使用权限,userId=", Sessionutil.getuserIdO);

022 / 3
第 2 页
第 2 页

public Checkstorag…

throw new BizException (ResultEnum.NO_ACCESS_AUTH);

PhotoHomeInitRes res = new PhotoHomeInitResO; InnerRes innerRes = photoAppService.renderHomePage (); res.setSuccess (true); res.setTemplateInfoList (innerRes .getTemplateInfoList ());

return res;

public CheckstorageRes checkstorage (){ if C!photoprm.inuserPhotowhitelist (Sessionutil.getuserId ()){ Loggerutil.infoCLOGGER,"[ PhotoFacade ]用户暂无使用权限,userId=", Sessionutil.getuserIdO); throw new BizException (ResultEnum. NO_ACCESS_AUTH);

CheckStorageRes checkStorageRes = new CheckStorageResO;

checkStorageRes .setCanSave (photoAppService.checkPhotostorage (Sessionutil.getuser IdO)); checkStorageRes .setSuccess (true); return checkstorageRes;

public PhotoHomeInitRes photoHomeInitO {

photoAppservice.checkuserPhotowhitelist (Sessionutil.getuserId ()); PhotoHomeInitRes res = new PhotoHomeInitRes (; InnerRes innerRes = photoAppervice.renderHomePage (; res.setSuccess (true); res.setTemplateInfoList (innerRes .getTemplateInfoList ());

return res;

public CheckstorageRes checkstorage (){ photoAppservice.checkuserPhotowhitelist (Sessionutil.getuserIdO); CheckstorageRes checkstorageRes = new CheckstorageRes ();

checkStorageRes.setCanSave (photoAppService.checkPhotostorage (Sessionutil.getuser

checkstorageRes .setSuccess (true); return checkStorageRes;

public boolean checkuserPhotowhitelist (String userId){ if (!photoprm.openMainSwitchon (userid) !photoDrm.inuserPhotowhitelist (userId)){ Loggerutil.info (LOGGER,"[ PhotoFacade ]用户暂无使用权限,userId="

throw new BizException (ResultEnum.NO_ACCESS_AUTH);

return true;

033 / 3
第 3 页:3.2 提升可读性
第 3 页

3.2 提升可读性

我们在系统中或多或少都看到过未复用已有代码产生的重复代码或者已经无流量的代码,但对形成背景 不了解,出于稳定性考虑,不敢贸然清理,时间久了堆积越来越多。因此,我们在日常开发过程中,对 项目产生的无用代码、重复代码要及时清理,防止造成后面同学在看代码时的困惑,以及不够熟悉背景 的同学改动相关代码时漏改、错改的风险。

3.2.1 有效的注释 问题背景:业务代码缺乏有效注释,需要阅读代码细节才能了解业务流程,排查问题时效率较低。

List<String> vouchermarkList = Commonutil.batchfetchvoucherMark (voucherList); if (Collectionutil.isEmpty (voucherMarkList)){

return Stringutil.EMPTY_STRING;

BatchRecReasonRequest request request.setBizItemIds (voucherMarkList); Map<String,List<RecReasonDetailDTO>> recReasonDetailDTOMap = relationRecReasonFacadeclient. batchGetRecReason (request); 1f (Collectionutil.isEmpty (recReasonDetailDTOMap)){ return Stringutil.EMPTY_STRING;

(String voucherMark:recReasonDetailDTOMap.keyset ()){ for List<RecReasonDetailDTO> reasonDetailDTOS = recReasonDetaiTDTOMap.get (voucherMark); for (RecReasonDetailDTO recReasonDetailDTO :reasonDetailDTOS){ if (needupdateRecMaxcount (recReasonDetailDTO, RecReasonTypeEnum. FRIEND, recTypeList,friendRecMaxCount)){ friendRecText = recReasonDetailDTO.getRecommendText (); friendRecMaxCount = recReasonDetailDTO.getCount (); friendRecMaxCountDetailDTOs = reasonDetailDTOS; continue,

if (needupdateRecMaxCount (recReasonDetailDTO, RecReasonTypeEnum. LBS, recTypeList, 1bsRecMaxCount)){ 1bsRecText = recReasonDetailDTO.getRecommendText (); 1bsRecMaxCount = recReasonDetailDTO.getCount ();

return bulidRecText (friendRecMaxCountDetailDTOS,friendRecText, 1bsRecText);

重构方法:补充相应的业务注释,说明方法的核心思想和业务处理背景。

//1.生成对应的券标识,查推荐信息 List<String> voucherMarkList = Commonutil.batchfetchvoucherMark (voucherList); if (Collectionutil.isEmpty (voucherarkList)){ return Stringutil.EMPTY_STRING;

BatchRecReasonRequest request = new BatchRecReasonRequest (); request.setBizItemIds (voucherarkList);

= new BatchRecReasonRequestO;

资料里没有你的场景?

把你手上的数据和想解决的那个环节发上来,我们按具体情况回,不复述方法论。

发布需求