代码文档:多少是太多了?
-
08-07-2019 - |
题
.NET 源代码中有多少代码文档过多?
一些背景:我继承了一个大型代码库,我在我在这里发布的一些其他问题中讨论过它。该代码库的“功能”之一是 God Class,它是一个静态类,包含超过 3000 行代码,包含几十个静态方法。一切都是从 Utilities.CalculateFYBasedOnMonth()
到 Utilities.GetSharePointUserInfo()
到 Utilities.IsUserIE6()
. 。这都是很好的代码 不需要重写, ,只是重构为一组适当的库。我已经计划好了。
由于这些方法正在进入新的业务层,而我在这个项目中的角色是为其他开发人员维护系统做好准备,因此我正在考虑可靠的代码文档。虽然这些方法都有良好的内联注释,但它们并不都具有 XML 注释形式的良好(或任何)代码 doco。使用 GhostDoc 和 Sandcastle(或 Document X)的组合,我可以创建一些非常漂亮的 HTML 文档并将其发布到 SharePoint,这将使开发人员更多地了解代码的用途,而无需浏览代码本身。
随着代码中文档数量的增加,浏览代码变得更加困难。我开始怀疑 XML 注释是否会使代码比更简单的代码更难维护 //comment
会在每个方法上。
这些例子是 来自文档 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,但是如果你要移交给另一个团队来维护的代码库呢?
你觉得我应该怎么做?
解决方案
我认为问题的一个很好的部分是MS强加给我们的冗长和苛刻的XML文档语法(JavaDoc也没有好多少)。如何格式化它的问题在很大程度上取决于多少是合适的。
使用XML格式进行注释是可选的。您可以使用DOxygen或其他识别不同格式的工具。或者编写自己的文档提取器 - 这并不像你想象的那样难以做一份合理的工作并且是一种很好的学习经历。
有多难的问题。我认为自编文档代码的想法很好,如果你正在挖掘维护一些代码。如果您只是一个客户端,则不需要阅读代码来了解给定函数的工作原理。当然,大量信息隐含在数据类型和名称中,但有很多信息并非如此。例如,传入对象的引用会告诉您预期的内容,但不会告诉您如何处理空引用。或者在OP的代码中,如何处理参数开头或结尾的任何空格。我相信远这类信息应该记录得比通常认可的更多。
对我而言,它需要自然语言文档来描述函数的用途以及函数的前后条件,其参数和返回值,它们无法通过编程语言语法表达的
其他提示
没有人提到你的代码不需要膨胀,XML文档可以在另一个文件中:
/// <include file="Documentation/XML/YourClass.xml" path="//documentation/members[@name='YourClass']/*"/>
然后你的Add方法上面不能包含额外的XML /注释,或者你只是喜欢摘要(因为它与单独的文件合并)。
它比Javadoc和你在PHP / Javascript中找到的衍生物的垃圾格式强大得多(尽管Javadoc为XML语法铺平了道路)。此外,可用的工具要优越得多,帮助文档的默认外观更易读,也更容易定制(我可以说是通过编写doclet并将该过程与Sandcastle / DocProject / NDoc进行比较)。
在维护新库的那些和将要使用新库的那些库之间存在着重要的分歧。
如果我正在编写一个新的应用程序并将使用这些标准库,我应该得到一个稳定的库二进制文件,只需将它们导入我的应用程序,而不是从一个位置复制源代码并可能导致问题如果代码被修改。在这种情况下,我将无法访问任何<!>“自我记录<!>”;除了方法名称和输入/输出参数之外的其他功能,如果我使用某种没有启用自动完成功能的IDE,那么这些功能也不会公开。
所以在上面的示例代码中,我觉得它看起来很好。事情在代码本身中并不太冗长,而且名称是自我记录的。另一方面,所有必要的摘要/参数数据都在那里,以便可以构建一个可靠的文档片段,以允许那些使用库的人将所有关键信息放在指尖。可悲的是,XML相当臃肿,但大体上我认为大多数开发人员可以轻松浏览所有摘要内容并查看方法中的实际代码。
Jeff在这里发表了一篇关于评论(或者我应该说,不评论)的非常好的文章......
http://www.codinghorror.com/blog/archives/001150.html
我知道我似乎没有回答这个问题,但我认为代码应尽可能自我记录是有效的。
我倾向于在自己的代码中记录所有公共方法;使用GhostDoc使这个变得微不足道。为了减少编辑源代码时的混乱,我通常只是首先进入<!>“;大纲模式<!>”来折叠注释。 (即使用Visual Studio的大纲<!> gt;折叠到定义命令)。
我从未尝试过Sandcastle,但我非常感谢Intellisense为我所评论的方法提供的舒适感。
我总是选择XML / Javadoc格式的评论,因为我喜欢能够以合理的格式浏览API文档(通常是HTML)。
它确实成为浏览实际源代码的问题,但我发现这通常是一个小问题,因为Visual Studio通常非常聪明地根据需要折叠XML注释。
不要重复自己。
- 第一个示例应该有一个更好的方法名称并且根本没有注释。
- 第二个例子不应该有注释。
第一个方法的名称应该反映分配了一个新对象。
如果该行为在整个框架中对于每个添加都是标准的,则应该在更高级别上记录它,而不是在此方法 API 文档中。否则,请更改名称。
评论应该添加信息,而不是将其隐藏在噪音中。必要时在 XML 中应该有注释。以及它们增加价值的地方。
我不想看到:对于名为 count 的方法,“返回计数”。
熟悉您的代码库的人必须清楚地理解所有公共功能,但不必在您的特定部分,而不必深入研究代码。
如果你需要写一个简短的行来解释函数的作用,你可能很难命名你的函数/类。在这种情况下,名称应该是自我解释的
如果需要超过1个简短的句子来解释,这可能是一个很好的评论
如果它需要一个段落,除了可能不清楚的名字之外,你的功能可能做得太多了。
通常最好在评论方面犯错如果你确定它们是准确的。不准确和/或不可维护的评论比没有评论更糟糕
所以应用这些规则:
在您的第一个示例中:<!> quot; //创建新客户实例<!>是多余的。代码很清楚。其他评论是完美的。他们澄清了代码在运行的内容/结果是什么
在你的第二个例子中,评论是浪费精力并使其难以阅读。您需要做的就是为函数指定一个正确的名称。不是那个模糊的<!>“;计数<!>”;那是命名不好。
我最近进行的一项研究表明,如果你有重要的<!>“指令<!>”,例如,来电者必须做X <!>“;在很多规范中(例如,<!>;这个方法做X,这意味着Y和Z <!>“),你的读者很可能会错过这些指令。事实上,当他们看到很长的文档时,他们会跳过阅读它。
至少,将重要内容分开或使用标记(问我是否使用Java)。
这一切都取决于您的公司使用的标准,但对于我的工作人员,我们将文档记录在每个函数的顶部,如第二个示例中所示(通过点击<!>,您可以在Visual Studio 2008中执行此操作“; <!>”;键在任何子或函数顶部连续3次!!)。
第一个例子是矫枉过正,尤其是每行评论的底线。但是,我认为函数头部的内容可能很有用,因为我们在这里使用它很多。从许多其他程序员那里可以看出它似乎有点标准。
我见过编码标准建议不要评论自我评论代码和方法重载。虽然是YMMV,但这听起来像是远离<!>的好方法; Field _numberOfCars是一个整数,表示导致过度杀伤的汽车<!> - 类型注释的数量。
生成文档的标题中的注释是一件好事。在代码中添加注释来解释为什么你正在做你正在做的事情通常也是一件好事。用冗余的评论来解释你所做的并不是一件好事
你所展示的是远远不够。帮自己一个忙,然后将其删除!
代码应该首先通过有意义的方法和参数名称进行自我记录。在你展示的例子中;
公共客户添加(标题标题,字符串FirstName,字符串MiddleInitial,字符串LastName)完全可以理解正在发生的事情,就像'计数'一样。
正如您所指出的那样,对此进行评论纯粹是噪声围绕着其他易于阅读的代码。大多数开发人员将尽快开放检查和使用代码,而不是通过模糊的自动生成的API文档。每次!
顺便说一句,根据<!>“清洁代码<!>”; (一本好书,BTW),应该避免在源代码中嵌入的注释中使用HTML / XML标记。即使您的IDE可以在悬停时创建漂亮的文档,当您浏览源时,它也会被认为太分散注意力并且不可读。