【问题标题】:Code documentation: How much is too much?代码文档:多少算太多?
【发布时间】:2010-09-22 05:52:08
【问题描述】:

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

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

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

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

这些例子是from the Document X sample:

        /// <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 cmets 记录所有代码,目的是使用 NDoc (RIP) 或 Sandcastle 之类的东西?如果没有,您如何决定哪些获取文档,哪些不获取?像 API 之类的东西显然会有 doco,但是你要交给另一个团队来维护的代码库呢?

你觉得我应该怎么做?

【问题讨论】:

  • 这篇文章的赞成/反对过山车令人着迷。

标签: .net sandcastle xml-comments code-documentation ndoc


【解决方案1】:

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

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

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

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

【讨论】:

    【解决方案2】:

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

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

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

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

    【讨论】:

    • 我同意。部分原因是我偶尔需要维护您多年前编写的代码,Jeff。 :O) 您编写的自然语言、彻底的 cmets 正是偶尔对我没有编写和更改的代码进行修改所需要的。良好的注释有助于避免意大利面条式代码,其中添加的代码片段不符合原始设计者的意图,然后导致问题。人们需要记住,一个组织在维护阶段将花费大约 2/3 的 SW 总生命周期成本。所以无论我们能做些什么来减少维护都是好的。
    【解决方案3】:

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

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

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

    【讨论】:

      【解决方案4】:

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

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

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

      【讨论】:

      • 是的,但问题不在于代码本身是否是自记录的,而在于从代码中生成外部文档的价值。因此,XML 评论系统。
      【解决方案5】:

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

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

      【讨论】:

      • Sandcastle 从您的 XML cmets 生成 MSDN 样式的文档(编译的帮助或 HTML)。顺便说一句,答案很好。谢谢。 :)
      【解决方案6】:

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

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

      【讨论】:

      • 我也是这么想的。不过,你在什么时候做得过火了?示例中的 Add() 方法是否矫枉过正?
      【解决方案7】:

      不要重复自己。

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

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

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

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

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

      【讨论】:

      • OP 中的代码仅用于说明目的。应该如何记录它的细节对于 XML cmets 是否会增加太多冗长的问题毫无意义。
      • 在示例中,它们添加了太多冗长
      • 在什么意义上?如果 Add() 方法是整个 API 的一部分,那么它不应该有良好的 MSDN 样式文档,这就是所有这些 XML cmets 的重点吗?你还建议怎么做?
      【解决方案8】:

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

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

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

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

      通常最好在 cmets 方面犯错如果你确定它们是准确的。不准确和/或不可维护的 cmets 比没有 cmets 更糟糕

      所以应用这些规则:

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

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

      【讨论】:

        【解决方案9】:

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

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

        【讨论】:

          【解决方案10】:

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

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

          【讨论】:

            【解决方案11】:

            我见过一些编码标准建议不要对自注释代码和方法重载进行注释。虽然是 YMMV,但听起来像是摆脱“字段 _numberOfCars 是一个表示汽车数量的整数”的好方法 - 导致矫枉过正的 cmets。

            【讨论】:

              【解决方案12】:

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

              【讨论】:

                【解决方案13】:

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

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

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

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

                【讨论】:

                • 我的问题的重点是确定 XML cmets 的值,以便生成外部文档,而不是注释代码本身。你的反应“啊太多了!”是问题的一部分,但我们如何在没有 cmets 的情况下创建好的 doco?
                • 我的意思是,XML cmets 没有任何价值......如果开发人员可以打开源代码,那么 9/10 他会。编写良好的代码应该构成“好的文档”的大部分。
                • 当我说“他”时,我的意思是“他”或“她”……我的错
                • 所以你不用MSDN文档?
                • 是的,我这样做了并且我发现 MSDN 非常令人沮丧,我会尽快访问 StackOverflow 之类的网站或直接进入 SDK 中的代码示例,我可以在其中查看实际代码...
                【解决方案14】:

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

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-02-28
                  • 2011-02-04
                  • 1970-01-01
                  • 2010-11-04
                  • 2010-09-27
                  • 2012-09-23
                  • 2012-01-20
                  相关资源
                  最近更新 更多