8

您的 .NET 源代码中有多少代码文档太多了?

一些背景:我继承了我在 SO 上发布的其他一些问题中谈到的大型代码库。该代码库的“特性”之一是 God Class,它是一个具有超过 3000 行代码的单个静态类,包含几十个静态方法。这是从Utilities.CalculateFYBasedOnMonth()Utilities.GetSharePointUserInfo()到的一切Utilities.IsUserIE6()。这都是不需要重写的好代码,只需重构为一组适当的库。我已经计划好了。

由于这些方法正在进入一个新的业务层,而我在这个项目中的角色是准备系统以供其他开发人员维护,我正在考虑可靠的代码文档。尽管这些方法都具有良好的内联注释,但它们并不都具有 XML 注释形式的良好(或任何)代码文档。使用 GhostDoc 和 Sandcastle(或 Document X)的组合,我可以创建一些非常漂亮的 HTML 文档并将其发布到 SharePoint,这将使开发人员无需浏览代码本身就可以更多地了解代码的作用。

随着代码中文档数量的增加,导航代码变得越困难。我开始怀疑 XML 注释是否会使代码更难维护,比方说,//comment每个方法都更简单。

这些示例来自 Document X 示例

        /// <summary>
        /// Adds a new %Customer:CustomersLibrary.Customer% to the collection.
        /// </summary>
        /// <returns>A new Customer instance that represents the new customer.</returns>
        /// <example>
        ///     The following example demonstrates adding a new customer to the customers
        ///     collection. 
        ///     <code lang="CS" title="Example">
        /// CustomersLibrary.Customer newCustomer = myCustomers.Add(CustomersLibrary.Title.Mr, "John", "J", "Smith");
        ///     </code>
        ///     <code lang="VB" title="Example">
        /// Dim newCustomer As CustomersLibrary.Customer = myCustomers.Add(CustomersLibrary.Title.Mr, "John", "J", "Smith")
        ///     </code>
        /// </example>
        /// <seealso cref="Remove">Remove Method</seealso>
        /// <param name="Title">The customers title.</param>
        /// <param name="FirstName">The customers first name.</param>
        /// <param name="MiddleInitial">The customers middle initial.</param>
        /// <param name="LastName">The customers last name.</param>
        public Customer Add(Title Title, string FirstName, string MiddleInitial, string LastName)
        {
            // create new customer instance
            Customer newCust = new Customer(Title, FirstName, MiddleInitial, LastName);

            // add to internal collection
            mItems.Add(newCust);

            // return ref to new customer instance
            return newCust;
        }

和:

    /// <summary>
    /// Returns the number of %Customer:CustomersLibrary.Customer% instances in the collection.
    /// </summary>
    /// <value>
    /// An Int value that specifies the number of Customer instances within the
    /// collection.
    /// </value>
    public int Count
    {
        get 
        {
            return mItems.Count;
        }
    }

所以我想问您:您是否使用 XML 注释来记录您的所有代码,目的是使用 NDoc (RIP) 或 Sandcastle 之类的东西?如果没有,您如何决定哪些获取文档,哪些不获取?像 API 之类的东西显然会有 doco,但是你要交给另一个团队来维护的代码库呢?

你觉得我应该怎么做?

4

14 回答 14

8

没有人提到您的代码不需要臃肿,XML 文档可以在另一个文件中:

/// <include file="Documentation/XML/YourClass.xml" path="//documentation/members[@name='YourClass']/*"/>

然后,您的 Add 方法不能在其上方包含任何额外的 XML/注释,或者如果您只喜欢摘要(因为它与单独的文件合并)。

它比您在 PHP/Javascript 中找到的 Javadoc 及其衍生格式的垃圾格式强大得多(尽管 Javadoc 为 XML 语法铺平了道路)。此外,可用的工具要好得多,帮助文档的默认外观更具可读性和更易于定制(我可以说,通过编写 doclet 并将该过程与 Sandcastle/DocProject/NDoc 进行比较)。

于 2009-02-18T10:35:38.123 回答
5

我认为这里问题的很大一部分是 MS 强加给我们的冗长而粗暴的 XML 文档语法(JavaDoc 也好不了多少)。如何格式化的问题在很大程度上与合适的程度无关。

对注释使用 XML 格式是可选的。您可以使用 DOxygen 或其他识别不同格式的工具。或者编写自己的文档提取器——做一份合理的工作并不像你想象的那么难,而且是一次很好的学习经历。

多少的问题更困难。如果您正在深入研究维护一些代码,我认为自我记录代码的想法很好。如果您只是客户,则无需阅读代码即可了解给定功能的工作原理。当然,很多信息都隐含在数据类型和名称中,但也有很多不是。例如,传入对对象的引用会告诉您预期的内容,但不会告诉您如何处理空引用。或者在 OP 的代码中,如何处理参数开头或结尾的任何空格。我相信应该记录的这类信息比通常公认的要多得多

对我来说,它需要自然语言文档来描述函数的用途以及函数的任何前置条件和后置条件、它的参数和返回值,这些是无法通过编程语言语法表达的

于 2008-11-13T21:22:42.497 回答
3

您在这里遇到了将维护新库的人和将使用新库的人之间的关键鸿沟。

如果我正在编写一个新的应用程序并将使用这些标准库,我应该得到一个稳定的库二进制文件并将它们简单地导入我的应用程序,而不是从某个位置复制源代码,如果代码可能会导致问题被修改。在这种情况下,除了方法名称和输入/输出参数之外,我将无法访问任何“自我记录”功能,如果我使用某种 IDE,即使这些功能也不会暴露没有打开自动完成功能。

所以在你上面的示例代码中,我认为它看起来很好。代码本身的内容并不太冗长,并且名称是自我记录的。另一方面,所有必要的摘要/参数数据都在那里,因此可以构建一个可靠的文档片段,让那些使用该库的人可以轻松获得所有关键信息。遗憾的是,XML 相当臃肿,但总的来说,我认为大多数开发人员可以轻松浏览所有摘要内容并查看方法中的实际代码。

于 2008-11-13T22:37:42.207 回答
1

杰夫在这里有一篇关于评论(或者我应该说,不是评论)的非常好的文章......

http://www.codinghorror.com/blog/archives/001150.html

我知道我似乎没有回答这个问题,但我认为代码应该尽可能自我记录是一个有效的观点。

于 2008-11-13T21:08:26.457 回答
1

我倾向于在自己的代码中记录所有公共方法;使用 GhostDoc 使这变得微不足道。为了减少编辑源代码时的混乱,我通常只是通过首先进入“大纲模式”来折叠注释(即使用 Visual Studio 的大纲 > 折叠到定义命令)。

我从未尝试过 Sandcastle,但我非常感谢 Intellisense 为我用 XML 注释的方法提供的舒适感。

于 2008-11-13T21:12:20.350 回答
1

我总是选择 XML / Javadoc 格式的注释,因为我喜欢能够以合理的格式(通常是 HTML)浏览 API 文档。

浏览实际源代码确实会成为一个问题,但我发现这通常是一个小问题,因为 Visual Studio 通常非常聪明地根据需要折叠 XML 注释。

于 2008-11-13T21:13:18.490 回答
1

不要重复自己。

  • 第一个示例应该有一个更好的方法名称并且根本没有注释。
  • 第二个例子不应该有评论。

第一个方法的名称应该反映分配了一个新对象。

如果该行为是整个框架中每个添加的标准行为,则应在更高级别记录,而不是在此方法 API 文档中。否则,请更改名称。

评论应该添加信息,而不是隐藏在噪音中。并且应该有注释,必要时在 XML 中。以及他们增加价值的地方。

我不想看到:名为 count 的方法的“返回计数”。

于 2008-11-13T21:26:25.657 回答
1

所有公共函数都必须让熟悉您的代码库的人清楚地理解,但不是在您的特定部分中,而不必深入研究代码。

如果您需要写一个简短的行来解释一个函数的作用,那么您很可能将您的函数/类命名得很差。在这种情况下,名称应该是不言自明的

如果它需要超过 1 个简短的句子来解释,那可能是一个很好的评论

如果它需要一个段落,那么除了可能不清楚的名称之外,您的函数可能做得太多了。

如果您确保它们是准确的,通常最好在评论方面犯错。不准确和/或无法维护的评论比没有评论更糟糕

所以应用这些规则:

在您的第一个示例中:“// 创建新客户实例”是多余的。代码非常清晰。其他评论很完美。他们阐明了代码的操作/结果是什么

在您的第二个示例中,评论是浪费精力并且难以阅读。您需要做的就是给函数一个正确的名称。不是那个模糊的“计数”。那是不好的命名。

于 2008-11-13T22:40:07.473 回答
1

我最近进行的一项研究表明,如果您在许多规范中都有重要的“指令”,例如,调用者必须执行 X(例如,“此方法执行 X,这意味着 Y 和 Z”),那么存在非常高的风险你的读者会错过指令。事实上,当他们看到一个长文档时,他们会跳过所有的阅读。

所以至少,分离重要的东西或使用标记(问我是否使用 Java)。

于 2008-11-13T22:41:21.497 回答
1

这完全取决于您的公司使用的标准,但对于我的工作人员,我们会在每个函数的顶部记录,就像在您的第二个示例中一样(顺便说一下,您可以在 Visual Studio 2008 中通过点击“/”键 3 次来执行此操作在任何子或函数顶部的一行中!!)。

第一个例子是矫枉过正,尤其是在每行注释的底部几行。但是,我认为函数头部的内容可能很有用,因为我们在这里经常使用它。从我从许多其他程序员那里可以看出,它似乎有点标准。

于 2008-11-14T00:43:24.540 回答
0

我已经看到建议不要评论自注释代码和方法重载的编码标准。虽然 YMMV,但这听起来像是摆脱“字段 _numberOfCars 是一个代表汽车数量的整数”类型的评论的好方法,这会导致过度杀伤。

于 2008-11-13T21:16:04.087 回答
0

用于生成文档的标题中的注释是一件好事。在代码中添加注释来解释你为什么要做你正在做的事情通常也是一件好事。加入多余的评论来解释你所做的并不是一件好事

于 2008-11-13T21:24:21.183 回答
0

你所展示的太多了。帮自己一个忙,删除它!

代码首先应该通过有意义的方法和参数名称进行自我记录。在您展示的示例中;

public Customer Add(Title Title, string FirstName, string MiddleInitial, string LastName) 对于正在发生的事情的意图是完全可以理解的,“计数”也是如此。

正如您所指出的,诸如此类的评论纯粹是围绕原本易于阅读的代码的噪音。大多数开发人员会更早地打开检查和使用代码,而不是堆积晦涩的自动生成的 API 文档。每次!

于 2008-11-13T21:30:43.883 回答
0

顺便说一句,根据“清洁代码”(一本好书,顺便说一句),应该避免在嵌入源代码的注释中使用 HTML/XML 标记。即使您的 IDE 可以在您悬停时创建漂亮的文档,但当您浏览源代码时,它会被认为太分散注意力且难以阅读。

于 2008-11-13T22:57:53.960 回答