.net注释之旅[原创]
本文将带你经历一次关于.net注释的奇妙旅程。
我们写程序的时候,有一个很重要的程序质量指标就是代码注释,甚至有些项目明确规定注释不得少于多少,以及定下一系列的注释规范,注释超过代码的数量。事实上,段程序里面如果出现了过多的注释,往往说明该段代码的质量存在一定问题,往往是代码写的过于复杂,功能全都搅到了一起,这种情况下程序往往是需要评审和重构的。但是本文并不打算讨论程序里应该写多少代码多少注释,何时需要重构,以及应该如何做,我只想分享一下我开发时的一些小经验,准确的说是关于注释的一些小经验。
作.net开发的程序员,大概都会对一个辅助工具很熟悉:GhostDoc。你可以在这里找到它http://www.roland-weigelt.de/ghostdoc/,在安装好和你的IDE对应的GhostDoc之后,我们就可以用GhostDoc为我们的程序代码自动添加注释了。
在一个方法或属性命名比较规范的话,你就可以用GhostDoc为你的代码生成完善的注释了。举例:
下面代码
public bool IsReady
{
get;
set;
}
一个Bool属性,我们用GhostDoc为该属性生成自动注释,所得到的注释代码大致如下(由于对GhostDoc的设置可能不同,得到的自动注释也会不同)
/// <summary>
/// Gets or sets a value indicating whether this instance is ready.
/// </summary>
/// <value><c>true</c> if this instance is ready; otherwise, <c>false</c>.</value>
但是本文并不打算深入介绍如何使用GhostDoc,关于如何使用GhostDoc的文章,你可以在网上搜到很详尽的介绍文章。
我说想要说的是另一个话题:当我们用Visual Studio 编程的时候,当你把鼠标悬停在一个.net Framework提供的类或方法上面时,就会显示出一段关于该元素的描述性的ToolTip,由于你装的开发环境的不同,这段文本也许是中文的,也许是英文的,如下图:
为什么有时候是英文的,有时候又是中文的呢?我们要讨论的是这段文本的来龙去脉。通过右键菜单的“转到定义”,就会打开string的元数据,我们看到下面一段代码
//
// 摘要:
// Replaces the format item in a specified System.String with the text equivalent
// of the value of a specified System.Object instance.
//
// 参数:
// format:
// A composite format string.
//
// 参数:
//
// arg0:
// An System.Object to format.
//
// 返回结果:
// A copy of format in which the first format item has been replaced by the
// System.String equivalent of arg0.
//
// 异常:
// System.ArgumentNullException:
// format is null.
//
// System.FormatException:
// The format item in format is invalid.-or- The number indicating an argument
// to format is less than zero, or greater than or equal to the number of specified
// objects to format.
public static string Format( string format, object arg0 );
是不是很奇怪:为什么注释里面又有中文,又有英文?这是微软的Bug吗?其实不然,Format方法的注释文档并没有和代码保存在一起,而是保存在别的地方,而你看到的注释也不是原生的注释,而是实时生成的,OK,我们接下来道出其中的奥妙。
首先找到mscorlib.dll的位置,因为string的实现就在该dll里面,该dll大概就在如下目录
X:"WINDOWS"Microsoft.NET"Framework"v2.0.****"
注释在哪里呢?是不是在类库的il代码里面?但是当我们通过工具打开dll的时候,并没有在里面发现想要的注释信息,同时,假如说注释保存在类库的il代码里面,如果我们已经实现英文版本的注释,现在随着市场的扩展,我们需要推向日本市场,要实现日文版本的注释,岂不是要修改代码中的注释和dll,是不是代价太高了?答案就是注释不再dll里面。
在该目录下同时还有如下目录:en, zh-cn,zh-chs等,在其下一定可以找到如下文件:mscorlib.xml。打开该xml文件,找到如下代码
<member name="M:System.String.Format(System.String,System.Object)">
<summary>Replaces the format item in a specified <see cref="T:System.String" /> with the text equivalent of the value of a specified <see cref="T:System.Object" /> instance.</summary>
<returns>A copy of <paramref name="format" /> in which the first format item has been replaced by the <see cref="T:System.String" /> equivalent of <paramref name="arg0" />.</returns>
<param name="format">A composite format string. </param>
<param name="arg0">An <see cref="T:System.Object" /> to format. </param>
<exception cref="T:System.ArgumentNullException">
<paramref name="format" /> is null. </exception>
<exception cref="T:System.FormatException">The format item in <paramref name="format" /> is invalid.-or- The number indicating an argument to format is less than zero, or greater than or equal to the number of specified objects to format. </exception>
<filterpriority>1</filterpriority>
</member>
聪明的你一定已经看出来了,上面的注释其实就是从该xml片段中提取出来的。看到这里,也许你会想:我们岂不是也可以轻易实现多语言版本的注释?
OK,我们可以继续我们的实验,但是,现在我们还缺一样东西:xml文件,这个xml文件从何而来呢?答案是从项目中来。这么说也许有些玩笑的意思,但是确实如此。打开一个注释完备的项目(你可以建一个小的测试项目,最好是类库,只需一个类,一个公开方法,片段代码如下)
/// <summary>
/// MyHelloClass注释测试
/// </summary>
public class MyHelloClass
{
/// <summary>
/// Says the hello.
/// </summary>
/// <param name="msg">The MSG.</param>
public void SayHello( string msg )
{
}
}
打开项目的属性页的“生成”标签,勾选“输出”下面的“XML文档文件”,在该选项后面自动会生成一个XML文件保存路径,你可以修改该路径,但我们不打算这么做。保存项目文件并编译项目,在项目输出目录就会出现我们需要的XML文件了。我们的历程已经过了大半,接下来的就比较轻松了。下面是我的XML文件
<?xml version="1.0"?>
<doc>
<assembly>
<name>ClassLibrary1</name>
</assembly>
<members>
<member name="T:ClassLibrary1.MyHelloClass">
<summary>
MyHelloClass注释测试
</summary>
</member>
<member name="M:ClassLibrary1.MyHelloClass.SayHello(System.String)">
<summary>
Says the hello.
</summary>
<param name="msg">The MSG.</param>
</member>
</members>
</doc>
你只需要修改该文件中对应的文本就可以实现多语言注释了,同时,也许你已经想到,只要把不同语言版本的xml注释文件放到相应的目录下,如“en”、“zh-cn”等就可以实现同一套类库英文开发环境看到的注释是英文,中文开发环境看到的注释是中文。至此,该旅程也到了终点,希望你可以从中获益。
总结:程序的一个很重要质量指标就是注释,.net Framework还有第三方插件为我们提供了非常强大的注释支持,使得我们可以方便的为我们的程序库提供多语言注释,不考软件的虑其他方面的质量标准,通过实现多语言注释可以使得用户更容易掌握我们类库。
美中不足的是,可以看得出,生成XML注释文档是相当规范的,应该有一个注释文档编辑器让我们可以更直接的编辑注释文档而不是通过查找XML文件中的tag来定位我们想要编辑的节点并修改相应内容,这样很容易错误的修改掉某一个tag而产生错误。编辑器应该是有的也许是我不知道而已,如果有谁知道有哪些好用的注释文档编辑器可以推荐一下来着。
另:本文以C#为程序开发语言,并未对其他语言进行测试,但我想道理应该都是相通的。