Visual Studio .NET 中的编码标准和代码审查





0/5 (0投票)
2006年5月2日
16分钟阅读

54062
定义编码标准和建立代码审查流程可能既耗时又充满挑战。本文探讨了实现这些目标的技巧,重点在于创建实用的标准并在可能的情况下自动化代码审查。
这是我们CodeProject赞助商的展示评论。这些评论旨在为您提供我们认为对开发人员有用且有价值的产品和服务信息。
引言
在软件开发的学科中,很少有话题能比编码标准更能引起争议。讨论的范围从看似无伤大雅的主题,如格式化和注释实践,到带有宗教般狂热的辩论,如命名约定中使用匈牙利命名法。甚至有时还会争论是否需要编码标准。转向微软的 .NET 平台持续重新引发了这些辩论,因为这一转变为了公司提供了一个重新思考软件开发方式的机会。
作为 Standards Master 系列产品的首席开发者,我在过去几年里详细研究了编码标准,特别是它们与微软工具开发相关的方面。在本文中,我将探讨编码标准为何有用,它们应该包含(和不应该包含)什么,以及如何强制执行它们。尽管我会提供一些建议,但我的目的不是宣扬“答案”。相反,我的目标是引发思考,无论您的组织是拥有悠久、严格的编码标准历史,刚刚开始努力,还是尚未认识到它们的价值。我还会介绍 Standards Master 如何通过自动化代码审查来减轻代码审查的烦恼,使审查成为开发过程中持续、无痛的一部分。
标准的重要性
当编码标准得到正确定义、培训和执行时,它们可以显著降低拥有众多开发者的组织的软件开发成本。因此,至少,存在一个纯粹的经济理由来证明它们的合理性:标准可以使代码更易于维护,并提高组织内所有项目的代码可读性,这两者都可以降低开发成本。
编码标准还有助于代码的同质化。由多位作者编写的源代码中可能会出现细微(以及不那么细微)的不一致。尽管许多开发者可能不会直说,但他们不喜欢处理其他开发者编写的代码,因为他们总会发现一些他们会以不同方式编写的代码示例。开发者天生就有创造力,就像艺术家一样,每个人都将自己的风格带入媒介(即代码)中。因此,即使在同一个源文件中,编码风格也可能出现分歧——每个处理该文件的开发者都会留下自己的印记。通过编码标准实现源代码的同质化有助于减少某些开发者对“他们的”代码的强烈所有权以及对他人代码的厌恶。当处理遵循公认标准的代码时,开发者会感到自在,而不是想重新编写他们接触到的所有代码,使其更符合他们的个人品味。简而言之,标准有助于实现源代码是公共资产而非个人资产的概念。这也最终对开发成本产生了积极影响。
标准提供的连贯性还带来了不那么明显,但可能同样重要的好处。例如,遵循标准的通常代码错误更少,即使存在错误也更容易发现和修复。因此,实际上,拥有标准可以帮助提高代码质量。这是否意味着遵循编码标准编写的代码没有错误?当然不是,但一致性可以使错误更容易被发现——开发者在编码过程中更有可能自己发现错误。错误发现得越早,修复成本就越低。
尽管我仍然遇到一些认为编码标准是浪费时间的个人和组织,但根据我的经验,压倒性的共识是它们确实很有价值。真正的辩论在于它们应该包含什么以及如何采纳它们。关键在于确定编码标准在公司文化中的程度,以及管理者和开发者如何实现这种文化转变。
抵制编码标准
既然大多数组织都同意编码标准很有帮助,为什么不是每家公司都有呢?原因有很多,但大多数都归结为时间和金钱。启动创建编码标准的努力既耗时又昂贵。此外,标准的维护和执行会增加通常已经受限的预算的时间和成本。
对于项目制的开发公司来说,一些项目通常需要承担创建标准的成本。这意味着即使有强烈的基层支持来开发编码标准,组织也可能为了满足紧张的时间表和预算而放弃这项工作。然而,最终,“我们没有时间为这个项目制定编码标准”的论点是自我毁灭的,因为公司最终会发现它们没有时间不去制定。
还存在一些潜在的人格冲突阻碍采纳编码标准的努力。例如,编程更像是一门艺术而非科学:就像有些艺术家不喜欢被告知如何创作他们的艺术一样,有些开发者也不喜欢被告知如何编码。因此,开发者可能会抵触编码标准的某些方面,觉得它们过于死板。编程的这种艺术一面可能与营利性写代码的实际方面直接冲突。对许多开发者来说,创造代码的过程比最终产品更令人满意,因此可能会干扰创作过程(如标准)的事物被视为障碍。他们工作的公司可能持有相反的观点——最终产品是主要目标——开发者在创作过程中的个人享受是次要的。即使开发者不过分关注将开发视为艺术,他们仍然是习惯的生物,改变这些习惯可能很困难。
标准与最佳实践
在最小化编码标准的感知限制同时不降低其有效性的关键在于制定既允许艺术自由又提供一致性的标准。虽然我一直鼓励在创建编码标准时进行完全公开的讨论,但通过将每个主题归类为标准或最佳实践来引导讨论通常很有帮助。两者之间有一条微妙的界限,对于积极创建编码标准的组织来说,找到这条界限至关重要。这并不是说你们仍然不会有分歧,但这确实提供了一个方便的高层次分组。
我发现将标准视为明确的事物很有帮助。标准应该很少有例外,如果有的话。一旦定义了它们,就应该无须讨论地遵循。另一方面,最佳实践属于“通常处理这种情况的最佳方法,但也有您想做得不同的情况”的范畴。当需要上下文和开发者酌情决定如何处理情况时,您可以定义最佳实践,但定义一个标准要困难得多。此外,在审查时,您希望对未遵循最佳实践的情况进行讨论,但会发现争论标准违规(如缺少注释)是浪费大家的时间。
通过根据需要将编码的各个方面划分为标准或最佳实践,您将为整体编码标准打下良好的基础。请确保将这些内容放入文档中并与您的团队共享。
标准中有什么?
FlexiSoft Solutions 多年来一直积极帮助人们创建和执行编码标准。在此期间,我们审查了数十家公司的编码标准文档,并听取了客户关于什么有效、什么无效的大量推荐。我们将大部分反馈和经验融入了我们的标准执行工具系列 Standards Master。Standards Master 的每个版本都为定义编码标准提供了极大的灵活性,反映了我们在客户标准中发现的巨大差异。以下是您至少应考虑放入标准文档中的主题列表,以及在与团队探讨这些主题时可以预期的内容。
- 注释风格——在此区域,您应说明开发者何时应使用头部注释,所需的注释元素是什么,版权信息等。通常有两种观点:注释一切,或仅注释所需内容。XML 风格注释与传统花括号注释的主题,以及捕获修订历史记录注释的主题,通常也会引起一些讨论。
Standards Master 提供完整的注释功能,并支持任意数量的用户定义的注释模板(XML 风格或纯文本)。您还可以定义 Standards Master 要使用的可替换参数,以便在添加注释时提示开发者提供其他信息。
- 格式化风格——Visual Studio .NET IDE 会为您处理格式化(尤其是在 Visual Basic .NET 中),但格式化风格仍值得讨论,特别是如果您的某些开发者使用非标准编辑器。请务必涵盖缩进约定、间距约定、最大行长度和括号约定。这似乎是一个小主题,但我知道有些开发者在重新格式化彼此的代码上浪费了很多时间。在这种情况下,标准化的好处是显而易见的。
Standards Master 允许您将代码中的任何构造定义为开始或结束缩进级别的项,并修复所有间距问题。
- 命名约定——命名约定涵盖类、文件、变量、命名空间以及代码中的其他所有内容应如何命名。这个讨论可能会变得丑陋,尽管最近开发者似乎主要关心的是多大程度上遵循微软的 .NET 命名约定指南。在进行此讨论时,请记住微软的 .NET 约定不适用于局部变量和私有成员变量,因此未经修改或增强而采纳他们的约定会在您的标准中留下漏洞。而且,尽管微软已积极尝试说服人们不要使用匈牙利命名法(Pascal 风格的基名带有作用域、类型或其他修饰符),但他们自己在指南中并未完全放弃它,使得他们的标准有点不一致。我发现大多数公司都在微软的指南上添加一些匈牙利命名法的元素,以使其更清晰。这在 Visual Basic .NET 和 C# 中都如此。例如,作用域前缀(如 _m 或 m_ 用于类级别变量)和类型前缀(如 s 表示 String)非常普遍,尽管微软的约定并未提及它们。好消息是,您通常可以为私有构造定义任何您想要的内容,并且仍然与微软的建议保持一致。
Standards Master 的命名约定强制执行功能非常强大——它不仅能查找不符合您设置的标识符,还能自动为您修复它们。AutoCorrect 功能会在您键入时自动修复命名约定问题!
- 代码构造——这个宽泛的类别涵盖了从过时的语言构造到风格方面的所有内容。我建议采纳使代码更简单(特别是条件、循环和流程控制构造)且更易读的实践。您可能还想考虑为每文件类数、每方法行数、每类方法数、每标识符字符数等设置阈值。关于 `GoTo` 语句可接受使用的讨论可能会很激烈。
Standards Master 拥有数十种代码构造检查,可以根据您的需要进行配置。它还可以自动为您修复许多代码构造违规。
- 特定语言的标准——请记住,编码标准通常与特定语言相关。请务必为您的组织使用的所有语言采纳标准。
Standards Master 2.0 支持 Visual Basic 5 和 6。Standards Master 2004 和 Standards Master 2005 支持 Visual Basic .NET、C# 和 J#。所有特定语言的设置都可以独立更改。
当无法达成一致时怎么办
每一项建立和维护编码标准的努力都会在参与者之间产生相当多的分歧。我经常被问及如何处理相关方根本无法就编码标准达成一致,或者抵制定义编码标准的努力的情况。如果您是这项工作的负责人,请牢记以下几点:
从一开始,在创建标准时就与必须遵守标准的开发者合作。如果开发者觉得他们在创建标准中发挥了积极作用,他们将更有可能接受这些标准。
确保您正在创建的标准尽可能与公司文化保持一致。不要试图一夜之间改变一切:有时缓慢、稳定地采纳编码标准更容易被接受。
当无法达成一致时,学会挑选战斗。确定哪些标准真正重要,哪些不重要。为不重要的遗漏标准而失眠是不值得的。让您的开发者的创意得到发挥——不要过于死板。在一些相对不重要的标准上妥协可能会为强制执行更重要的标准铺平道路。
如果仍然存在分歧且无法达成妥协,找出异议是否真正由被告知如何编码的被压抑的怨恨或对代码审查的某种不明原因的恐惧引起。如果您的组织认真对待拥有和强制执行编码标准,那么这些开发者将需要克服这些问题。
万不得已时,可能需要管理层授权来解决特定问题。这最好作为最后的手段,但在极端情况下会有帮助。我曾见过一些开发者因不愿意遵循(甚至同意)标准而离职或被解雇。
请确保您有一个机制来处理标准建立后的修改。根据我的经验,标准委员会通常是个好主意,因为它允许开发者继续在标准过程中发挥积极作用。
通过代码审查强制执行标准
一旦您制定了编码标准,就应该将其文档化并对您的开发者进行培训。这是合规性的关键第一步。但是,您还需要建立某种审查流程来确保标准得到遵循。许多组织仅仅相信他们的开发者会遵循标准,而懒得制定审查政策。根据我的经验,这是一个错误:如果标准没有得到一致执行,人员变动和紧张的时间表通常会导致偷工减料。如果您没有代码审查政策,您可能根本就不需要考虑编码标准。
除了帮助确保开发者遵循您的标准外,代码审查还是传播和传播公司文化(也称为“我们在这里做事的方式”)的绝佳载体。利用这一点来帮助培训和提升初级开发者的技能。
代码审查也有其缺点。如果执行不当,它们可能会耗费时间和资源。而且,尽管目的是通过积极、建设性的批评来改进代码,但开发者也是人。有些人不善于接受(或给出)批评。这些问题通常可以通过制定明确定义的、经过培训的标准来避免,并专注于消除审查中个人和个性的技术(正如我们下面将看到的,自动化审查在这方面非常有效)。最重要的是,要强调代码审查是代码审查,而不是审人。尽管如此,代码审查仍然可能给初级开发者以及那些喜欢隐藏在代码复杂性中的人带来很多困扰。
代码审查技术
您可以使用两种技术来处理审查:面对面审查和自动化审查。它们结合使用效果最佳,但两者各自都有优势。让我们逐一来看。
面对面审查可用于验证开发者是否遵循您的标准,但最适合用于关注代码的逻辑和复杂性,而不是代码中更死板的方面。它们是审查最佳实践遵循情况的好方法。面对面审查通常分为三类。第一,同行评审,其中一名开发者审查另一名开发者的代码,这种方法很方便,但可能导致审查质量不一致。第二,小组审查,其中一些代码呈现给一群人进行审查(通常是整个团队),这种方法也很有效,因为有很多输入。然而,执行起来可能很耗时。第三,高级开发者审查,其中一两名高级程序员审查团队的代码,提供一致、有经验的反馈。当然,您仍然面临确定谁审查高级开发者代码的问题。您可以选择这三种方法中的任何一种或组合来处理您的面对面审查。
使用 Standards Master 的自动化审查非常有效,因为它们可以持续进行,从而在编码过程早期解决违规问题,然后在它们根植于代码之前。由于 Standards Master 直接作用于源代码,而不是通过编译程序集中的元数据,因此它会检查您选择的所有代码(包括局部变量)。该过程是迭代的:编写一些代码,通过其工具栏激活 Standards Master 来审查代码,修复发现的任何问题,然后重复。这意味着开发者在工作时审查自己的代码,并随着进行修复问题。为了使事情更加简单,Standards Master 可以自动修复它发现的许多问题。最终,这意味着代码是按标准编写的,而不是按标准调整的。
这种自动化审查消除了审查过程中的个人和个性,使其更容易被更广泛的开发者群体接受。此外,自动化审查有助于开发者学习标准,并以自己的节奏学习,而无需承担被另一位开发者告知一个非常简单的问题是错误的潜在尴尬。您可以通过使用 Standards Master 的命令行界面作为构建脚本的一部分来检查代码,进一步自动化审查过程。
Standards Master 是一个非常经济实惠、方便的工具,可以帮助组织执行其编码标准。单独使用它,可以减轻标准执行中的大量烦恼。然而,最好是与定期的同行和小组审查结合使用,以在最小的时间投入下获得最佳质量。有了这种组合,审查者就可以花更多时间专注于代码的内容和逻辑,因为 Standards Master 的自动化审查消除了检查标准“机械”方面(如注释、命名约定和代码构造)的需要。
结论
总而言之,编码标准可以显著降低您开发的软件成本,同时提高其质量。代码审查是强制执行标准、灌输公司文化和促进交叉培训的绝佳方式。尽管最初采纳和持续执行编码标准可能看起来令人生畏,但其回报非常值得付出努力。
版权所有 (c) 2006 FlexiSoft Solutions, Inc.