C/C++ 和 C# 代码重构:让机器代劳





0/5 (0投票)
对 Visual Assist X 中的代码重构工具的评测 - 作者:John Krajewski,Pandemic Studios 高级 AI 程序员。
这是我们CodeProject赞助商的展示评论。这些评论旨在为您提供我们认为对开发人员有用且有价值的产品和服务信息。
引言
我面试开发岗位的候选人时,总会问一个我喜欢的面试题:“你为什么不喜欢你使用的编程语言?”一个好的候选人会从他/她对工作流程和效率的理解出发,语言如何促进或阻碍创建高质量代码的能力,以及(也许更重要的是)在代码增长过程中如何维护代码。
对我来说,答案毫不犹豫:我最讨厌大多数现代语言的地方是编写代码时必须忍受的乏味;那些磨灭了我应该用来创建实际设计和功能的宝贵时间的心智的琐碎任务。你知道那种感觉:更改定义时更新声明,重命名变量或函数名在所有使用它的地方,将一个大的函数分解成小的函数——为什么我们还在执行这些琐碎的任务?现在是 2006 年了!我可能还没有我的飞行汽车,但至少我可以要求那个每秒钟运行三十亿次的机器在我输入文本时能伸出援手。
因此,你可以想象当我得知最新的 Visual Assist X 版本引入了代码重构功能时,我是多么兴奋——这是来自 Whole Tomato Software 的插件,几乎适用于所有 Microsoft IDE。终于,有人能在我编写代码时利用我的处理器了,背后运行着一个复杂的解析引擎,无缝地检查我的代码,将曾经繁琐且易出错的杂活变成自动化的过程。让我们来看看 C/C++ 和 C# 中可用的重构功能。(我的示例是用 C++ 编写的,但重构在 C# 中也同样有效。)
保持代码整洁
你认为阻碍代码整洁的最大障碍是什么?最大的罪魁祸首之一绝对是臃肿、庞大的函数,长达数百行,几乎无法辨认。将这类函数重构为适当的层次结构是一项耗时且令人沮丧的任务,许多开发人员会屈服于添加“再加一行”的诱惑,然后让下一个人去处理。
提取方法
提取方法工具可以几乎无痛地分解这些大型函数——只需选择要提取的代码块,给它命名,点击按钮,你就完成了:新函数已被实现,定义在头文件中,并且该代码块已从原始函数中移除并替换为对新函数的调用。更重要的是,在代码块外部声明并在代码块内部使用的任何局部变量都会作为参数传递!我第一次看到这个时,感觉就像变魔术一样。让我们来看一个例子。
这是函数中一个用于执行各种操作的代码片段,非常适合分解成更小的部分
如果我们想将所有数据处理移到一个单独的函数中,我们可以通过选择文本,将其悬停,然后使用 Visual Assist X 弹出的上下文相关下拉框来轻松实现。
选择此项(或直接使用快捷键)会弹出一个对话框,你可以在其中选择名称,正如你所见,Visual Assist X 已经完成了剩下的工作。函数签名已经写好,传入了所需的变量(保留 const,对于较大的类型则通过指针传递)。
点击“OK”即可创建函数
……并在其原位置添加了对新函数的调用
能够只进行代码的粗略编写,而让机器完成其余的工作,这真是一种令人欣慰的感觉,只需选中它,将其提取到一个单独的函数中,然后重复。这就像有一个小弟为你做脏活。这个功能甚至足够灵活,可以从单行代码中提取更改——让我们将比较操作从 `for
`-循环中移出,放到它自己的函数中。
注意它如何根据用法来识别返回类型
……并自动正确地插入
有了这个工具,可以将大量代码块在几秒钟内重构成多层级结构,几乎没有借口不创建干净、封装的函数,并在它们增长时保持这种质量。
不过,如果你和我一样,可能对机器操纵你的代码的想法持怀疑态度;它真的能正确识别一切吗?当然,机器无法读懂你的心思,但在绝大多数情况下,它能按照我的意图识别出新函数的签名(而且在过程中产生的错误肯定比我手动操作的少得多!)。如果你给这个功能输入了错误的值,或者它没有按照你的预期工作,整个操作都可以轻松撤销(CPP 和头文件都会恢复,只需按一次 Ctrl-Z),并且你可以使用导航命令向前和向后导航,直观地审查它所做的更改。
你可能已经注意到,这些提取的函数都创建在头文件中——Visual Assist X 可以轻松纠正这一点,这引出了它提供的下一组功能(我认为是我最喜欢的重构工具),用于操作定义和声明。(当然,与头文件相关的重构不适用于 C#。)
保持代码同步
提高效率最简单的方法之一就是减少花在重复任务上的时间。不幸的是,C++(以及大多数现代语言)要求你将代码的各个部分保持匹配状态——定义必须始终与在单独文件中进行的声明匹配,成员必须通过“get”和“set”函数进行封装,等等。
这些要求从技术角度赋予了语言相当大的能力,但对开发人员来说,结果是他/她反复编写相同的文本。除了浪费时间,这是引入错误最简单的方法之一。Visual Assist X 重构工具的创建者显然意识到了这些问题,并认真考虑了如何最好地简化这种已有几十年的工作流程。
将实现移至源文件
这个功能是我个人最喜欢处理的一个代码“痛点”:不必要的内联函数(定义在头文件中,仅仅是因为原始作者太懒,不愿意将其放入 CPP 文件中)
只需一个命令即可同时修复头文件和 CPP 文件
这个功能非常适合设置一个简单的热键,因为 Visual Assist X 默认将生成的函数(由“提取方法”和其他功能创建)放在头文件中,如果你愿意,可以将其移至 CPP 文件。
创建实现和创建声明
如果你不是在移动现有函数,而是创建全新的函数,那么这里还有另一个工具。无论你是喜欢在头文件中创建函数,然后将其复制到 CPP 文件,还是反之亦然,Visual Assist X 都能满足你的需求,并使用相应的命令填充缺失的部分。
封装字段
另一个常见的任务,也是代码整洁的基石,是用“Get”和“Set”块封装成员变量。Visual Assist X 也为这个问题提供了解决方案
一个特别好的地方是,它为函数名创建的文本可以使用其 Autotext 功能进行自定义
在这里,我更改了“封装字段”调用期间创建的函数的名称,以使用我习惯的 Get 和 Set 标准。该系统足够灵活,你可以添加更多行来执行你的应用程序所需的自定义操作(例如,添加一个“RegisterForScript
”函数来操作该变量)。这就像一个自动替换功能——它会为你提供符号名称,并允许你按照自己的意愿排列它们。
AutoText 本身就是一个很棒的功能,与他们其他的工具集成得很好,它允许你快速创建常用的代码块,并且可以按照你想要的精确风格(也可以针对特定语言)。
添加成员和添加类似成员
在使用 Visual Assist X 后,你会意识到当你不必离开文件和位置去将声明代码放到别处时,效率会提高多少。假设我正在编写一个函数,并决定一个类需要另一个成员变量或函数——Visual Assist X 允许我在不中断当前工作的情况下添加它。
此时会在头文件中创建一个存根,允许我立即开始填充它,或者返回到原来的位置继续我的工作
如果你的光标位于现有方法或成员变量上,你会看到“添加类似成员”命令,它的功能与“添加成员”完全相同,但它通过从你光标下的成员签名开始,从而更加 streamlined。
正是这些小小的补充,让整个 Visual Assist X 界面感觉如此 polished 和 tuned,以适应你的工作方式,而不是迫使你改变你的代码创建风格以适应它的工作方式。
保持代码可理解性(对他人和自己)
任何参与过大型项目的人都知道,代码很少一次性就写完;相反,它就像一个活的实体,必须随着新功能的添加和需求的改变而变化和适应。随着这种情况不可避免地发生,代码的名称和文档也常常不幸地与代码实际功能脱节,这通常是因为执行这些更改的任务太繁琐而令人不快,以至于被忽视。以下功能可以自动化保持函数文档和符号名称(本身也属于一种文档形式)最新化的过程。
重命名
Visual Assist X 可以重命名几乎任何类型的符号:方法、字段、类、变量和方法参数。重命名也可以从符号的任何实例开始,而不仅仅是从声明开始
在这里,我们将 `Data` 类重命名为一个更具描述性的名称。
在更改任何代码之前,Visual Assist X 会弹出一个对话框,显示它检测到的符号的所有引用,允许你确认所有更改后再进行。而且,如果你以后决定不进行更改,整个操作都可以通过一次“撤销”来撤销(它会修复所有受影响的文件)。
更改签名
一个类似的功能允许你重命名与函数相关的各种标识符
在函数上调用此功能会更改参数类型、函数名和参数名,并在函数使用的地方自动更新它们。在这里,我们将 `CompareStatus` 的成员重命名为更具描述性的名称,并且它们在函数中使用的地方也得到了更新。
你也可以更改参数类型、返回类型和函数限定符(例如 `const
`),但你必须手动更新这些更改。
查找引用
查找引用工具本质上是一个更智能的“在文件中查找”——它会查找你引用的符号,并以基于上下文的搜索方式输出所有找到的位置(所以它不会匹配其他具有相同名称的符号)。
它将结果显示在一个可以像任何其他 IDE 窗口一样停靠的窗口中
上面窗口中的图标特别有用——红色箭头表示符号被赋值的位置,绿色表示被引用的位置,蓝色块表示定义的位置(例如,当你查找修改某个变量的代码时,这对于快速浏览非常有用)。如果一行中有多个条目,它们会被列出多次,用“-->”表示行内的位置。还有一个“全部高亮”功能,它会用不同的颜色高亮显示源窗口中的符号,用于赋值的符号。
此工具比“在文件中查找”更具上下文敏感性和更深入的分析,而且速度也更快。
文档化方法
也许代码整洁最重要的一点是清晰、一致的文档。有一个方便的工具可以帮助自动化这个过程,你可以从函数定义中调用它
此功能将在你的函数上方创建一个标准化的注释块,使用关于你正在文档化的类和函数的特定上下文数据
与 Visual Assist X 为你生成代码的所有功能一样,样式可以在其 Autotext 工具中进行自定义
Visual Assist X 从上下文中识别出的各种数据以特殊字符串的形式暴露出来,你可以在这里输入(他们的文档中列出了更多可用字符串)。
一种新的编码方法
我使用 Visual Assist X 已经很多年了,我在这里描述的代码重构工具只是一个庞大工具集的一部分,该工具集与过去几年中所有版本的 Microsoft IDE 集成。仅凭这些功能就足以让该产品具有价值,它们涵盖了多种增强你引用、查看和导航代码方式的方法。然而,重构工具代表了一个新的方向——终于有了创建代码的工具——这是一个巨大的进步,考虑到他们支持的语言和环境数量,以及在此基础上适应不同个人在每种环境中使用的编码风格,这无疑是一个艰难的挑战。
Visual Assist X 的创建者专注于编程工作流程中的一组核心任务,在各种编码风格下提供了非常扎实的解决方案,而且他们做得非常好——该产品最令人印象深刻的是它的集成有多么 seamless,以及所有功能在每种情况、每种环境和每种语言中的表现有多么 polished。这是幸运的——我不会接受一个要为我编写代码的应用程序提供低于此标准的任何东西。
当然,仍然有增长的空间,我可以想到更多可以自动化的事情,以及更多自定义生成内容的方式,然后是那个终极目标:他们能否让他们的工具智能到在我编写代码的同时,在后台自动执行所有这些重构?也许,这已经在地平线上了。但让我们一步一步来,我已经对这一步印象深刻了。
了解更多关于 Visual Assist X 的功能。