与 Patrick Smacchia 谈.NET 的代码分析

阅读数:1332 2008 年 4 月 29 日

话题:.NET重构语言 & 开发架构文化 & 方法

Patrick Smacchia 是 Visual C# 的 MVP,拥有超过 15 年的软件开发经验。他是《Practical .NET 2 and C# 2》一书的作者,该书通过真实的项目经验来阐释.NET 平台。他的专业为数学与计算机科学,毕业后,他在多个领域从事过软件开发,包括在 Société Générale 开发股票交易系统,在 Amadeus 开发航空售票预订系统,以及在 Alcatel 开发卫星基站。目前他是 NDepend 工具的首席程序员。

Rob Bazinet (RB): NDepend 是什么?

Patrick Smacchia (PS): NDepend 是为.NET 开发人员以及架构师开发的工具。代码库是那么的错综复杂,而 NDepend 工具则能够帮助人们从源代码中获取相关的信息。例如,NDepend 能够判断你的代码库是否正确分层;获知从最近版本发布后所做的修改;或者评估某些关键任务的代码质量,如果这些事情通过传统工具来完成,可能会耗费数个小时甚至数天的时间。

RB: 是什么使你产生开发 NDepend 的念头?

PS: 5 年前,我为一个巨大而又混乱的代码库提供咨询。而在同时,我正在阅读一本优秀的书籍,Robert C Martin 所著的《敏捷软件开发——原则,模式与实践》 。本书描述了一些非常酷的评估代码库组件构成的度量标准。

正是在那个时候,我从 C++ 转向了.NET。我所偏爱的其中一个特性是 System.Reflection,它比 C++ 的 RTTI 更加的引人注目。顺理成章的,我开始基于反射开发了一个小巧的工具,它能够针对这个巨大而又混乱的代码库去验证 Martin 所说的度量。然后,我将该工具发布为开源软件(OSS),由于它的功能能够满足许多需求,因而越来越受到人们的欢迎。基于此,我认识到如果该工具能够支持某些可视化以及查询的功能,那么对于我们处理代码复杂性而言,其效率就能再上一个台阶。

RB: NDepend 对于我的编码工作以及 / 或者开发生命周期能够提供怎样的帮助呢?

PS: NDepend 对多种任务都提供了很大的帮助,包括重构、代码评审、代码质量检查与增强、设计缺陷检查、代码侦测、代码浏览以及构建过程原则的实施。

NDepend 对于代码重构非常有用,因为它能够展现组件、命名空间、类……之间的依赖关系,呈现的方式是一个依赖关系矩阵图以及一些由“框框和箭头”组成的图形。

NDepend 支持超过 60 条编码准则,用于评估代码质量:

NDepend 分析过程可以被集成到 MSBuild 或者 NAnt 构建过程中。每次执行分析之后都会给出一个关于构建过程健康度的报告。

通过使用代码查询语言(Code Query Language,CQL,一种能够提供代码结构查询的语言),开发人员能够对他们的代码库提出各种问题:

  • 哪些类实现了 IDisposable 接口?

    SELECT TYPES WHERE IsClass AND Implements "System.IDisposable"
  • 哪些公共方法能够被声明为 private?

    SELECT METHODS WHERE IsPublic AND CouldBePrivate
  • 哪些方法分配了特定的字段?

    SELECT METHODS WHERE IsDirectlyWriting "MyNamespace.MyClass.m_Field"
  • 哪些复杂的方法没有足够的注释?

    SELECT METHODS WHERE CyclomaticComplexity > 15 AND PercentageComment < 20

CQL 语言还能够用来定义某些原则对每次构建进行检查。如果与原则冲突,用户就能够从报告中知晓。NDepend 提供了 50 多条预先定义的原则,同时还允许用户自定义符合系统要求的原则,例如:

  • 静态字段不能被命名为 m_XXX(自定义的命名规范):

    WARN IF Count > 0 IN SELECT FIELDS WHERE NameLike "^m_" AND IsStatic
  • 我不想让我的用户界面层直接依赖于 DataBase 层:

    WARN IF Count > 0 IN SELECT NAMESPACES WHERE IsDirectlyUsing "DataLayer" AND NameIs "UILayer"
  • MyAssembly 和 MyAssembly2 的方法不能超过 30 行代码:

    WARN IF Count > 0 IN SELECT METHODS OUT OF ASSEMBLIES "MyAssembly1", "MyAssembly2" WHERE NbLinesOfCode > 30

NDepend 可以比较代码库的两个版本。当我们即将发布一个新版本,以及需要进行冒烟测试,和对修改内容进行代码评审时,这一功能特性就格外的行之有效。此处,同样借助了 CQL 语言以探测版本之间的区别。例如,显示两个版本中被修改过的方法,需要编写:

  • SELECT METHODS WHERE CodeWasChanged

最后,NDepend 可以作为 Visual Studio 2005 以及 2008 的插件,也可以作为 Reflector 的插件,通过这些工具访问 NDepend 提供的功能特性。

RB: 若要使用 NDepend,应该怎么入门?推荐的学习途径是什么?

PS:首先,需要下载 NDepend,然后分析你的代码库。这些操作可以无缝地被执行,因为 VisualNDepend 的 UI 与 Visual Studio 的界面完全相同,甚至于界面效果更好。

一旦分析执行完毕,VisualNDepend 的 UI 就会通过几个面板来显示分析结果。此时,如果用户希望浏览依赖关系或软件度量,或者通过 CQL 语言查询代码库,以及比较分析结果等……都需要对此进行选择。无论内容的多少,每个功能特性都会提供一个专门的面板。同时还内嵌了一个“帮助”节,它包含了对 NDepend 的入门介绍。一些视频广播还具有链接。它们为用户演示了如何执行每个特定的任务。最后,我们的网站还提供了一些高级文档,例如完整的 CQL 规格说明书。

一旦用户掌握了每个功能特性,就能够统一地使用它们完成对代码库的评审与修正。

RB: NDepend 能够工作在.NET Framework 3.5 下吗?3.0 呢?

PS: 可以,新的 NDepend 2.6 版本的 Visual Studio 插件可以工作在 Visual Studio 2008 下。而且,NDepend 也能够分析.NET 3.5 和 3.0 的程序集。

RB: NDepend 是针对.NET 语言的产品;你是否有计划开发针对其他平台的产品?是否有计划增加对动态代码库的分析?

PS: 是的。NDepend 采用 C# 进行编码,但是在我们的代码中只有 5% 是专门针对于.NET 代码分析的。这意味着 95% 的代码与要分析代码的平台是抽象隔离的。正是基于这种背景,目前就有一家公司octo technology 正在开发能够分析 Java 代码的 NDepend 版本。octo technology 是一家法国的咨询公司,专注于软件与信息系统的架构设计,它汇聚了大量的 Java 和.NET 专家。Octo 的.NET 咨询师喜欢使用 NDepend,而 Java 咨询师也希望能够获得同样的工具。我们决定对此进行合作。

XDepend 项目(NDepend 的 Java 版本)的 beta 版会在 2008 的第 1 个季度推出。

RB: 对于初学者而言,使用 NDepend 进行代码分析看起来非常复杂;你对此有什么好的建议或者指导吗?

PS: 在 VisualNDepend 的 UI 中内嵌了一个帮助节,包含了一些入门级介绍以及具有链接的视频广播。在www.ndepend.com/GettingStarted.aspx中可以获得一些大约 3 分钟长度的视频广播,内容是对 NDepend 的入门讲解。还有一些视频广播则介绍了在主页上推荐的主要用例场景。若要进一步学习,我们还提供了一些文档,例如完整的 CQL 规格说明,对所有度量的描述文档,Scott Hanselman、Stuart Celarier 和Patrick Caulwell共同发表的总结文档的 PDF:NDepend metric placemats ,同时,在我们网站的 documentation 部分还提供了更多的内容。此外,我还会定期地更新博客(http://codebetter.com/blogs/patricksmacchia/default.aspx),并在那里阐述了 NDepend 的高级用法。

RB: 你们是否为软件团队提供培训,使得他们能够快速上手,并熟练地进行运用?

PS: 有时候我们会走访一些订阅了企业许可证以及希望获得特殊培训的客户。即使培训并非我们的主要工作,我们也要持续开展。与用户的直接联系会为我们提供更多的信息。功能特性的完善与用户的反馈是分不开的。

RB: 你认为 NDepend 最强或者说最好的功能特性是什么?而原因又在于什么?

PS: 这个问题很难回答,事实上,我们大量地使用了 NDepend 来规范 NDepend 的编码。我每天都在亲自使用度量去浏览依赖关系,确保体系架构保持清晰。我们拥有超过 400 条 CQL 原则,这些原则能够帮助我们持续不变地关注代码质量。我也为 NDepend 的比较特性所深深地吸引。我通常会使用它去评审发生改变的代码。我相信变化往往就是噩梦的开始。

所谓“一份耕耘,一份收获”,这种方式能够极大地改善我们的开发过程,使得我们能够以一种持续的节奏发布新的版本。更多的内容可以在我们的 发布笔记中找到。

RB: 今天,我们非常感谢 Patrick 牺牲宝贵的时间,指导我们了解了关于 NDepend 的知识。

有关 NDepend 的更多内容可以在NDepend 的网站上找到。读者可以通过 Patrick 的博客了解更多 Patrick 的信息。

查看英文原文Talking .NET Code Analysis with Patrick Smacchia