取消
显示结果 
搜索替代 
您的意思是: 
cancel
1251
查看次数
0
有帮助
0
评论
julianchen
Spotlight
Spotlight
第4部分:重写代码
通过上述部分,您应该已经制定出了计划、选取了相应任务、编写出了测试,那么是否现在就可以开始打开某个文件、修正变量名称并清理代码了呢?为了确保重构的顺利进行,我建议您先熟悉一些基本的概念。
下面,我将向您介绍一些在代码重构过程中的常见错误和化繁为简的技巧。
识别自动化的可能性
您很可能会碰到需要移动并梳理到正确的位置的大量文件。例如,我曾经在重构一个应用时发现其Redux的actions、reducers、和selectors都分属于自己单独的文件夹,而我需要将它们按照模块(例如appActions.js、appReducer.js和appSelectors.js)进行分类。因此,我需要运行一条git mv的命令,将 /actions/app.js移动到/redux/app/appActions.js,并且对于/reducers/app.js和/selectors/app.js要执行相同的操作。由于该应用项目中有11个模块,因此我必须输入33次git mv命令。另外,我还需要再运行150次git mv,以将React的容器和组件放置到正确的文件夹位置。
因此,面对如此“崩溃”的任务,我并没有手动地逐条输入命令,而是使用JavaScript和Node.js编写了一个脚本来实现:
const fs = require('fs');
const path = require('path');
const chalk = require('chalk');
const sh = require('shelljs');
const _ = require('lodash');
const sourcePath = path.resolve(process.cwd(), 'src');
// This is the new /src/redux folder that getscreated:
const reduxPath = path.resolve(sourcePath, 'redux');
// I used "entities" instead of"modules", but they represent the same thing:
const entities = [
'app',
'projects',
'schedules',
'users',
];
const createReduxFolders = () => {
if(!fs.existsSync(reduxPath)) fs.mkdirSync(reduxPath);
// Code to create entities folders in /src/redux...
};
// Executes a `git mv` command (I omitted someadditional code that validates
// if the file already exists for brevity).
const gitMoveFile = (sourcePath, targetPath) => {
console.log(chalk.cyan(`Moving ${sourcePath} to ${targetPath}`));
const command = `git mv ${sourcePath} ${targetPath}`;
sh.exec(command);
console.log(chalk.green('Move successful.'));
};
const moveReduxFiles = () => {
entities.forEach(entity => {
['actions', 'reducers', 'selectors'].forEach(reduxType => {
// Get the file associated with the specifiedentity for the specified reduxType,
// so the first file might be /src/actions/app.js:
const sourceFile = path.resolve(sourcePath, reduxType, `${entity}.js`);
if(fs.existsSync(sourceFile)) {
// Capitalize the reduxType to append to the filename (e.g. appActions.js):
const fileSuffix = _.capitalize(reduxType);
// Build the path to the target file, so this wouldbe /src/redux/app/appActions.js:
const targetPath = `${reduxPath}/${entity}`;
const targetFile = `${targetPath}/${entity}${fileSuffix}.js`;
// Execute a `git mv` command for the file:
gitMoveFile(sourceFile, targetFile);
}
});
});
};
moveReduxFiles();

您既可以通过脚本来自动迁移文件的路径,也可以通过脚本来直接修改路径的名称。当然,您需要注意投入产出比,不要花费了20小时去编写一个脚本,却只是节省了1个小时手动工作量。由于大多数代码库、及其结构都相对独特,因此一般您编写脚本的复用性都不高。
持续提交
您所重构的应用程序越多、时间越长,就越难以记住和追踪那些在不同文件里的细微修改。而对于各种文件的累计且大量更改,势必给您应用测试来带来失败的风险。因此,无论代码的修改量大或小、多或少,请记得予以持续提交。以某次应用重构为例,我就进行了1,747次提交,涉及到659个文件中的76,080行代码,总体占用的存储空间为10MB。
另外,在多次且持续的提交过程中,您可以通过限制每一次更改的内容和文件的数量,以便您能够随时按需“跳回”到某一个可靠的“保存点”。
抵御“分心”
请暂时避免清理那些手头任务范围之外的代码,这也是代码重构过程中最困难的方面之一。假设您遇到了一个使用Object.assign()的selector,而您的后续任务之一便是更新代码,使用类似spread syntax新的ESNext功能(请参考https://developer.mozilla.org/en ... ators/Spread_syntax)。那么请不要偏离当前的任务走向,哪怕只是对该代码进行微不足道的改变,都不要放在现在进行。我的经验是:在相应的代码处添加了一条// REFACTOR: Fix this later的注释,然后继续自己的当前任务。
有关拉取请求的方法论
有时候,您花费了大量的时间去清理一部分代码库,而难以后退到过去的某个时间点,或无法对修改后的代码质量进行评估。那么拉取请求往往就能够帮助您和同事来评审这些修改,以确定是否有益于代码的优化。
· 当您在提交拉取请求时,请在摘要处给予尽可能详细的描述。如果您使用的是GitHub,那么新的拉取请求会伴随着一个模板。您可以在其中填写相应的标题、总体描述、重要章节的变更列表等各种审评人员所关注的信息。
· 您需要注意的一个指标是:与拉取请求相关的代码更改数量。请尽量限制更改的代码行数在500行左右。由于Jest快照文件的添加会使得拉取请求动辄添加数千行,因此请务必在摘要中包含与之相关的注释。
· 如果您无法控制改变的数量,那么就请尽量降低其复杂性。
· 如果您只是对重要的声明语句进行重新排序的话,只要此类更改并不太复杂,超过2,000行的代码量还是可以接受的。
· 请将同类变更尽量限定在同一次拉取请求之中。
· 您可以大胆地在注释中写上“本次并未做逻辑上的修改”,以节约审阅者的理解时间。

写在最后
上面我们从代码重构项目的实施角度,向您提供了:尽可能自动化、持续提交、抵御“分心”、以及善用拉取请求等方面的建议。如果您还想深入了解代码重构的更多信息,请参考如下的资源链接:
· 重构:改进现有代码的设计(https://martinfowler.com/books/refactoring.html
· 清理代码:敏捷软件的工艺手册(https://www.amazon.com/Clean-Cod ... nship/dp/0132350882

【原标题】 Effective Refactoring (作者: Mike Rourke)
原文链接:https://dzone.com/articles/effec ... king-the-right-ques

入门指南

使用上面的搜索栏输入关键字、短语或问题,搜索问题的答案。

我们希望您在这里的旅程尽可能顺利,因此这里有一些链接可以帮助您快速熟悉思科社区:









快捷链接