1.背景1.1重构问:什么是重构?重构是在不改变其可观察行为的情况下改进软件内部结构的过程。--《重构 - 改善既有代码的设计》问:为什么要重构?重构可以提高理解力并降低修改成本。--《重构 - 改善既有代码的设计》问:什么时候重构?(1)什么时候不应该重构?当没有价值、没有意义或投入产出比很低时。团队资源是有限的,有限的资源要尽可能用在有意义的事情上。从团队的角度考虑投入产出比,不要去碰那些只是处于维护状态的代码,比如不需要,不需要调整。代码中可能有很多坑。(2)什么时候应该重构?高昂的项目维护成本会影响项目调整。例如,性能优化时代码看起来很丑。如果不优雅,现有的设计和实现不利于扩展新功能时的重复工作。现有代码无法帮助您轻松添加新功能。打补丁遇到bug,很难排查逻辑。代码审查允许其他人审查代码以检查其是否可读。可理解性太强的代码没有注释,连我都无法快速理清代码逻辑。1.2如何重构(1)准备(基本功)建议多读多读经典书籍,重构圣经《重构 - 改善既有代码的设计》。从毕业第一年开始,几年时间已经读了4遍+,受益匪浅。每次复习,都能有所收获。我经常折腾和处理项目没有任何问题。(2)想清楚重构实践的要点(整体设计是设计出来的,不一定要文档化但需要想通)。协同规划(开发团队内部协作和重构分支与其他分支的整合,早期应用产品、测试、运维等外部资源),统筹规划。层层展开,抓大放小,由粗到细。用好“批处理”。一次只做一件事。不要重新发明轮子。当你觉得有什么难的时候,停下来想一想方法是不是错了,应该是什么样的。不断监控和审查你自己的思维方式。做好内外沟通,尤其是当项目不是一个人开发和维护的时候。注意提前与相关方(测试、运维)沟通(计划、主要时间节点、需要投入的资源、需要他们配合的事项)。2、社区C端的重构实践本次重构具有一定的复杂性。除了技术迁移和改造的成本外,涉及的几个仓库是不同的技术选型(框架&上层组件等),项目快速敏捷迭代,需要高并发和多人协同开发和维护的状态。2.1状态分析技术栈:仓库名称技术栈社区C端页码repoAReact+umi3目标仓库不需要统计repoBReact+umi35repoCvue2+vuex27项目端A/B/C三个仓库主动更新,各仓库涉及多个业务线开发,并行维护。按照2周1sprint、1周开发1周测试的迭代节奏进行,中间穿插hotfixes。V1主版本发布后,各仓库涉及的代码如下:repoA:A1+A1。+A2+A2.repoB:B1+B1。+B2+B2.repoC:C1+C1。+C2+C2..*表示hotfix2.2重构方案前端侧的总体思路:repoA比较新,是社区的主仓库。它集中了大部分C端页面,作为目标C端代码的目标仓库。RepoBtorepoA:RepoB和目标仓库的技术栈很接近,涉及5页,人肉迁移,过程中注意依赖的迁移。RepoCtorepoA:repoC与目标仓库差异较大,语言异构,上层框架和组件库差异较大,涉及页面较多。首先判断有效页面,将离线页面的死代码排除在迁移范围之外;具体细节下面会说到,取出要迁移的仓库中的前端路由配置,知道页面的总范围,在阿里云sls日志中查看最新的PV(通过两种查询方式查看),排除没有流量的页面。层层递进重构,前期抓大放小,费时费力容易出问题的框架语法转换(vuetoreact)应该使用脚本工具实现,维护整体文件级别和每个类转换中的结构和引用关系。详细的语法通过自定义脚本进行批处理(例如vue中使用的class的key和字符串形式的value转换为react中的className和变量形式的value)。为了保证迁移后的高效自测,需要保留对应的*.vue文件,将其作为一个doc文件,在整个迁移完成后将其删除,以提高迁移和测试的效率.请注意,修改后的lint规则会忽略对此类文件的检测。过程中将依赖文件一起搬入,“命名空间隔离”,注意维护整体目录结构的相对关系,整体迁移,不污染目标仓库已有文件,防止同名文件被覆盖姓名。通过以上三个步骤将各个仓库代码迁移到repoA后,同步三个仓库的最新更新。在从repoC到repoA的过程中(从V1切下来的分支),repoC还在更新代码,repoA也需要合并V1.、V2、V2。repoC中的代码(repoB也一样)。由于代码都在不同的存储库中,因此需要手动合并。Tips:V1.,V2,V2的多次提交。可以在repoC中合并为一个commit,所有更改的项目可以聚合到一个地方进行批量更新。repoA中SSR方案的研究和应用也是并行的。重构中新导入的页面要与SSR集成。2.3重构与集成实践2.3.1B仓库页面整理与迁移这部分迁移采用同构语言进行,涉及的页面数量较少,主要通过手工迁移。2.3.2仓库C页面整理及在线流量查询,剔除无用页面。确定三个代码仓库中路由声明的总范围。根据阿里云日志判断近3个月、2个月、1个月的PV。没有PV的页面被排除在要迁移的页面池之外。注1:阿里云SLS日志以上报数据为准,在上报统计过程中可能会丢失数据,所以结合两个查询条目进行判断排查。注2:对于1-2个PV的页面,可能是团队内部开发前期调研时产生的。访问者确定后,会释放产生PV的“测试”页面。确定最终的重构范围(27个过滤器中的13个)。从步骤1得到的totalscope中去掉步骤2中没有用户PV的页面。异构语言转换处理C仓库Vue2转换为A仓库React工具转换,这里主要使用vue-to-react。然而,这个工具有很多约束和限制。大约一半的代码转换成功,转换失败。情况需要自己写脚本实现。本来想把库的源码重新打包改造一下。看完实现,发现定制的成本比自己写脚本的成本还高,就放弃了(我接触Vue不到一个月),时间紧,没仔细研究。.提示:避免重新发明轮子。当执行繁琐和重复的动作时,可以考虑拥抱团队、社区和开源内部的轮子。如果您没有,请自己创建一个。ScriptconversionTransformation项目目录结构设计及文件映射过程//step1:保持整体目录结构的相对性不变。├──api│├──community.ts│├──h5community│├──...├──components├──pages│├──h5community││├──App││├──api││├──资产│├──组件│├──配置││├──过滤器││├──live.js││├──main.js││├──mixins.js││├──router││├──style││├──utils││└──views│├──community├──utils└──...//step2:foo.vue文件转换到foo/目录下,模板分别映射到jsx和less文件。├──api│├──community.ts│├──h5community│└──...├──组件│├──h5community│└──...├──配置│├──h5community.js│└──...├──pages│├──community...返回引用││├──index.scss││└──index.tsx//第一行自动插入对index.scss的引用│└──...└──工具├──h5community└──...分步转换1:文件级对于vue-to-react处理失败的页面,通过脚本生成页面模板文件。//转换前文件为foo.vue//转换后:.└──foo├──index.jsx├──index.local_js└──index.scss自定义脚本转换生成的文件内容结构为如下:stepbystep转换二:语法层面——htmllangVue文件的转换过程中有很多lang="pug"模板,可以通过工具https://pughtml转换成"jsx-like"模板。com/想想这个工具,如果找不到,请尝试在Google中使用不同的关键字,而不是手动执行)。//
