|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionThrough many years of enterprise level software development and consulting, I became critically aware of the importance of good source code documentation, and several years ago when I began working with the first release of Visual Studio .NET beta 1 and found C# provided built-in support for inline XML code documentation, I was thrilled. After forming my own professional services consulting company, it was even more important to me that my customers be able to support, maintain and extend any software that my company produces on their behalf, and solid, thorough source documentation is one of the steps that can be taken to assist in achieving this. In all releases of Visual Studio .NET, only C# offers built-in support for inline XML code documentation; however, there are several free and third party add-ins that can be obtained to implement the same inline source XML documentation currently offered by C#.NET in C++, VB.NET and J#. The good news for you non-C# developers is Microsoft has included the same inline XML code documentation support for all .NET languages in Visual Studio .NET 2005. Although Visual Studio .NET provides a built-in facility to produce code documentation reports, I prefer to use the open source NDoc tool, so I will not go into details about how to produce .htm reports using Visual Studio, but I will demonstrate how to produce integrated, searchable and indexed source documentation for your source by using C#, Visual Studio .NET 2003 and NDoc. Article Goals
Please provide a rating / vote before leaving this articleThis is the only way authors get any type of credit for their work they freely share with everyone. It's sad to see articles that have helped over 100,000 people and fewer than 200 bother to vote or provide a rating. C# built-in featuresThere are three types of comment identifiers used to document C# source code:
// This is a single line remark or comment
/*
* This is line 1 of a comment block
* This is line 2 of the comment block
*/
/// <summary>
/// This is a sample summary comment
/// using the ‘summary’ xml tag.
/// </summary>
public void GetLoginAttempts( string userId ) { … }
C# offers several XML tags that can be placed directly within your source files to document the code, and Microsoft documents these tags very nicely in Visual Studio .NET help files. Once the developer has documented her source using the XML tags, she can use NDoc to produce integrated .chm files that contain the source documentation. Although the description above and in the article may use the term ‘comment’, the XML tags are used to produce external source documentation. This differs from traditional code comments in that the realized documentation can be distributed as API (Application Programmer’s Interface) documentation. Before discussing NDoc and how to produce .chm files, let’s first examine how to instrument C# source code with the XML tags and discuss some of the available XML documentation tags in more detail. XML documentation tagsThe XML documentation tags are used to document classes and their high level characteristics such as, constructors, finalizers, methods, properties, fields, delegates, enums, events and other characteristics. Visual Studio .NET recognizes the Figure 1 illustrates a standard method before and after the developer instructs Visual Studio to insert the XML tags by typing // Figure 1
// Before:
public bool StringIsValid( string validateMe ) { … }
// After the developer types 3 slashes (///)
// above the method signature:
/// <summary>
///
/// </summary>
/// <param name="validateMe"></param>
/// <returns></returns>
public bool StringIsValid( string validateMe ) { … }
Now that you know how to prompt Visual Studio .NET to insert the XML tags, let’s discuss some of the common tags and their usage. Since the tags are XML, they need to be ‘well formed’. At least in the sense you need to be sure to provide the proper closing marker and use single or double quotes as required. In the table below, when indications are given that clicking on links will show or display other information, I am referring to links in the produced .chm documentation files not within Visual Studio .NET. Conversely, when I mention IntelliSense or the client, the information will be displayed in Visual Studio .NET. Please note, I have not covered every XML tag supported by C# and Visual Studio .NET in this article, but rather the most commonly used tags.
Now that you’re armed with the most common tags, let’s discuss the source documentation. Documenting your codeDocumenting source code should be a standard part of the development process. If you get in the habit of documenting your source as you write it, you will find that you can produce fully documented code much faster than if you write code and try and go back and instrument it with documentation at a later time. I have found, if I document the code as I write it, it takes about 50% less time to document it than if I try and go back and document it later. If you are not used to fully documenting your source, you will have to get used to the fact that your .cs files will be longer which will cause you to scroll more; however, one trick that I've found is to make use of .NET’s Although I will not address it in this article, you can write your XML documentation in an external file and use the I try to ensure I provide documentation for all types and their members in my source. Although the particular implementation dictates the tags used, I try to provide at least the following XML tags for the related types (I document all members regardless of their scope or access modifier):
Figure 2 illustrates a short class documented with all the XML tags that have been discussed in this article. // Figure 2
namespace Mike.Elliott.Articles.XML.Documentation
{
using System;
/// <summary>
/// The <c>DocumentationSample</c> type
/// demonstrates code comments.
/// </summary>
/// <remarks>
/// <para>
/// The <c>DocumentationSample</c> type
/// provides no real functionality;
/// however, it does provide examples of
/// using the most common, built in
/// <c>C#</c> xml documentation tags.
/// </para>
/// <para>
/// <c>DocumentationSample</c> types are not
/// safe for concurrent access by
/// multiple threads.
/// </para>
/// </remarks>
public class DocumentationSample
{
/// <summary>
/// Initializes a new instance of a
/// <c>DocumentationSample</c> type.
/// </summary>
/// <example>The following is an example of initializing a
/// <c>DocumentationSample</c> type:
/// <code>
/// // Create the type.
/// DocumentationSample ds = new DocumentationSample();
///
/// if ( null == ds )
/// return;
///
/// return ds.MyMethod( “someString” );
/// </code>
/// </example>
public DocumentationSample() { … }
/// <summary>Causes something happen.</summary>
/// <param name="someValue">
/// A <see cref="String"/> type representing a value.
/// </param>
/// <exception cref="ArgumentNullException">
/// if <paramref name="someValue"/> is <c>null</c>.
/// </exception>
/// <exception cref="ArgumentException">
/// if <paramref name="someValue"/> is <c>empty</c>.
/// </exception>
/// <returns><paramref name="someValue"/>
/// as passed in.</returns>
public string MyMethod( string someValue )
{
if ( null == someValue )
throw new ArgumentNullException( "Your message." );
if ( 0 >= someValue.Length )
throw new ArgumentException( "Your message." );
return someValue;
}
}
Now let’s break down the source. Breaking it downLet’s look at the code snippets and the way the XML documentation is used. Each XML tag listed in the tag usage table provided earlier in this article is covered. Figure 3 illustrates the use of // Figure 3
/// <summary>The <c>DocumentationSample</c> type
/// demonstrates code comments.</summary>
/// <remarks>
/// <para>
/// The <c>DocumentationSample</c> type
/// provides no real functionality;
/// however, it does provide examples of
/// using the most common, built in
/// <c>C#</c> code comment xml tags.
/// </para>
/// <para><c>DocumentationSample</c> types are not
/// safe for access by concurrent threads.</para>
/// </remarks>
public class DocumentationSample { … }
Figure 4 illustrates the use of // Figure 4
/// <summary>
/// Initializes a new instance of a
/// <c>DocumentationSample</c> type.
/// </summary>
/// <example>The following is an example of initializing
/// an <c>DocumentationSample</c> type:
/// <code>
/// // Create the type.
/// DocumentationSample ds = new DocumentationSample;
///
/// if ( null == ds )
/// return;
///
/// return ds.DoSomething( 5 );
/// </code>
/// </example>
public DocumentationSample() { … }
Figure 5 illustrates the use of // Figure 5
/// <summary>Causes something happen.</summary>
/// <param name="someValue">A <see cref="String"/>
/// type representing some value.</param>
/// <exception cref="ArgumentNullException">
/// if <paramref name="someValue"/> is <c>null</c>.
/// </exception>
/// <exception cref="ArgumentException">
/// if <paramref name="someValue"/> is <c>empty</c>.
/// </exception>
/// <returns><paramref name="someValue"/> as passed in.
/// </returns>
public string MyMethod( string someValue )
{
if ( null == someValue )
throw new ArgumentNullException( "Your message." );
if ( 0 >= someValue.Length )
throw new ArgumentException( "Your message." );
return someValue;
}
Once your source is documented, you need to generate the XML documentation file used to produce the Visual Studio .NET documentation reports or NDoc help files. Producing the XML documentation fileVisual Studio .NET parses the .cs files to produce the XML documentation file; however, there are a couple of configurations and steps we need to take to make this happen. We must tell Visual Studio to produce the XML file, what to name the file, and where to create the file. To do this, in the Solution Explorer, right click the project and select Properties. This will bring up the project’s property pages (see figure 6).
Figure 6 In the project’s property pages, select the Build option under the Configuration Properties section. There are two properties you need to be concerned about on this page. First is the "Output Path" property which tells the compiler where to write the XML documentation file (I typically leave the path set to the bin/Debug directory because it makes using NDoc a little easier). Next, is the "XML Documentation File" property which will be the name of your XML documentation file (see figure 7). Click Apply and then OK to close the project’s property pages.
Figure 7 The last step in producing the XML documentation file is to build the project. Once you build the project, navigate to the directory you set as the "Output Path" for the documentation file, and you will see the .xml file (in my case the bin/Debug directory). If you open the XML file in a browser or Notepad, you will see that the XML documentation compiler has stripped out the XML documentation to produce the file. This also means that you can create your own XML stylesheets (XSLT) to format the documentation any way you want. <?xml version="1.0"?>
<doc>
<assembly>
<name>DocumentationSample</name>
</assembly>
<members>
<member name="T:Mike.Elliott.Articles.XML.
Documentation.DocumentationSample">
<summary>
The <c>DocumentationSample</c>
type demonstrates code comments.
</summary>
<remarks>
<para>
The <c>DocumentationSample</c> type
provides no real functionality;
however, it does provide examples of using the
most common, built in
<c>C#</c> code comment xml tags.
</para>
<para>
<c>DocumentationSample</c> types are not safe
for access by concurrent threads.
</para>
</remarks>
</member>
<member name="M:Mike.Elliott.Articles.XML.
Documentation.DocumentationSample.#ctor">
<summary>
Initializes a new instance of a
<c>DocumentationSample</c> type.
</summary>
<example>The following is an example of initializing an
<c>DocumentationSample</c> type:
<code>
// Create the type.
DocumentationSample ds = new DocumentationSample;
if ( null == ds )
return;
return ds.DoSomething( 5 );
</code>
</example>
</member>
<member name="M:Mike.Elliott.Articles.XML.
Documentation.DocumentationSample.MyMethod(System.String)">
<summary>Causes to happen.</summary>
<param name="someValue">
A <see cref="T:System.String"/> type representing some value.
</param>
<exception cref="T:System.ArgumentNullException">
if <paramref name="someValue"/> is <c>null</c>.
</exception>
<exception cref="T:System.ArgumentException">
if <paramref name="someValue"/> is <c>empty</c>.
</exception>
<returns><paramref name="someValue"/> as passed in.</returns>
</member>
</members>
</doc>
Almost thereNow that you have the XML documentation file, you are ready to build the actual help files or API documentation. For this task, we are going to use NDoc. NDoc is an extensible open source code documentation generation tool for .NET developers. You can download a free fully functional copy of NDoc from SourceForge.net or NDoc (many thanks to SourceForge and the developers who contributed to the NDoc utility). Once NDoc is installed, open up the GUI so that we can build our long awaited help files. Building the help filesThere are numerous configurations you can set within NDoc that dictate the content and format of the help files. I'll only cover a few here, but the contributing authors of NDoc did a wonderful job of documenting the options. When you click in one of the property boxes, a description of the property is displayed at the bottom of the GUI (see figure 8).
Figure 8 First, we need to add the .NET assembly(s) we want to include in the documentation. Notice we have the option to include as many assemblies as we want. This gives you the ability to create a fully integrated help file system for your entire system or organization. If your organization requires all C# development to be completely documented with the XML tags, you could add the production of the integrated help files to your standard build process. Remember, earlier in the article I indicated that I typically leave the Visual Studio project’s "Output Path" set to bin\Debug because it made working with NDoc a little easier? Click the Add button on NDoc and navigate to the Assembly file name and select the .exe or .dll assembly (see figure 9).
Figure 9 If you leave the "Output Path" pointing to bin\Debug, NDoc will automatically find the XML documentation file and populate the XML Doc Filename textbox. If you have changed the "Output Path", navigate to the XML documentation file to set the XML Doc Filename, and click OK. Without going too deep into the NDoc properties, when validating the contents of your help files, one helpful thing you can do is navigate NDoc’s UI (user interface) to the "Show Missing Documentation" section and set each property to
Figure 10 OK, let’s set a few properties and build our help files. The first property we want to set is the documentation type. I really like the MSDN format, so we’ll accept it as the default. Next, under the "Documentation Main Settings" area, we need to change the Lastly, change That’s it for the basic properties, so all we have to do now is build the help files and take a look at them. To build the files, click the build icon on the toolbar or select Build from the Documentation menu. Once NDoc has completed the build process, open the help files by clicking View Icon on the toolbar or select View from the Documentation menu (see figure 11).
Figure 11 Documenting NamespacesAdditionally, I would like to discuss how to document the namespaces to which your classes belong. Visual Studio .NET and C# do not provide a mechanism to document namespaces because namespaces are simple, logical containers for developers to organize and structure their code. In other words, you can not document namespaces with the inline XML comment tags and expect them to be properly parsed into your .xml documentation file. There is, however, an easy way to provide a summary level description for namespaces through NDoc's GUI. If you noticed in figure 10 (two images above), you will see the Namespace Summaries button located on NDoc's GUI. When you click this button, a dialog will appear with a drop-down box containing each namespace NDoc found within your code (see figure 12).
Figure 12 Here are the steps to add a namespace summary to your documentation:
Customizing the Format of Your XML CommentsOne of the neat things about the realized documentation is they are HTML files. Think about that for a minute, this means you can use traditional HTML tags within your XML comments to achieve custom formatting. In fact, the XML tags listed in this article simply map to HTML transformations or CSS classes. For example, when you create a bullet list in your XML comments, the result produced by NDoc (or Visual Studio .NET's HTML reports) is the typical HTML //XML Comments in the source code
/// <remarks>
/// <list type="bullet">
/// <item><b>Bold</b>, <i>Italic</i>, <b><i>Bold-Italic</i></b></item>
/// <item>Superscript - 1<sup>st</sup></item>
/// <item>Subscript - 2<sub>nd</sub></item>
/// </list>
/// </remarks>
public void HTMLCommentMethod() { ... }
Parsed, transformed and resulting comment output <ul type="disc">
<li><b>Bold</b>, <i>Italic</i>, <b><i>Bold-Italic</i></b></li>
<li>Superscript - 1<sup>st</sup></li>
<li>Subscript - 2<sub>nd</sub></li>
</ul>
I'm sure you can see how easy it is to add Bold, Italic and other standard HTML formatting to your documentation, and you can see the various uses for it. Since the output is simply HTML files, there is nothing preventing us from using anchors with links to external sites or pages, adding inline JavaScript to open new windows or even "pop up" alerts. The following code illustrates a bullet list with Bold, Italic, an Anchor (<a>) whose /// <summary>
/// This method demonstrates comments using <c>HTML</c> tags
/// within the <c>XML</c> comments.
/// </summary>
/// <remarks>
/// <c>HTML tag examples:</c>
/// <list type="bullet">
/// <item><b>Bold</b>, <i>Italic</i>, <b><i>Bold-Italic</i></b></item>
/// <item>Superscript - 1<sup>st</sup></item>
/// <item>Subscript - 2<sub>nd</sub></item>
/// <item>Javascript Alert - <a href='#'
/// onclick='javascript: alert( "Wow, this is cool!" );'>Alert</a></item>
/// <item>New Window -
/// <a href="#" onclick='javascript: window.open(
/// "http://sourceforge.net/projects/ndoc/" );'>
/// New Window</a>
/// </item>
/// </list>
/// <hr>
/// Something else
/// </remarks>
public void HTMLCommentMethod() { ... }
Figure 13 displays the NDoc documentation for the above method.
One valuable use for anchors pointing to external sites would be to document research found on the internet that solved certain problems within your project or code. As an example, you could add a link to a site that documents a fix you implemented for a known security issue. TipsTo wrap up the article, I want to point out a few things that will make the C# XML documentation and NDoc integration really neat. A couple of things I particularly like about the produced help files are that they are in a standard .chm format and they provide the standard contents, index and search capability. Also, notice that, if you had selected MSDN as the documentation type, your help files will be integrated with the .NET Framework’s help files. Notice in figure 11, the Have you ever downloaded an open source .NET assembly that provided poor or no documentation? If the assembly was written in C#, and the developer used XML documentation tags, you can produce the API documentation yourself (I did this with the In Visual Studio .NET, once you configure your .NET project to produce an XML documentation file and if you build the project, you may see several warnings informing you of undocumented characteristics. Many a times you will have to use Rebuild instead of Build to get the XML file updated properly. Once I have validated the documentation, I will typically save the NDoc project and add the .ndoc project file to my solution and place it in source control along with the source (note, I only have the .ndoc project file and not all the produced files as they are very easy to recreate). SummaryBy using the C# inline XML documentation tags and NDoc, you can create comprehensive API documentation for your source. By adding several assemblies to the same NDoc project and integrating with the .NET Framework help files, you can truly produce a professional set of source documentation of which anyone would be proud of. History
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||