Sunday, August 24, 2008

XML Documentation

OK, that last post ended up as being a bit of a tease, so I'll jump right into things today. I write most of my comments using XML. Before the days of XML, I used to write "header comments" for all my major code blocks. Each of these header sections would contain a number of pre-defined elements. With the advent of XML and the inclusion of support for XML-style comments in Visual Studio, it became easy to create consistent, thorough documentation for each primary element of my code (by "primary element" I mean classes, properties, methods, and events).

Using XML comments in .NET code has several advantages.

  • XML's well-defined tags and the assistance of auto-complete make it easy to create consistent comment blocks.
  • Starting with Visual Studio 2005, XML Documentation Comments can be extracted from VB, C#, and C++ source code files. When you compile with the /doc parameter, the compiler will extract all XML tags from your source code and create an XML documentation file. You can instruct the compiler to extract these comments into an XML file. These comments can be used by NDoc and SandCastle to create HTML and chm help files.
  • Finally, these XML files can also be used to add IntelliSense in VisualStudio to your own classes.

  • I try to comment every class, method, property, and event. In order for the compiler to extract documentation, the code comments need to meet the following two conditions:

  • The comment must begin with ''' in VB files and /// in C# or C++ files.
  • The documentation to be extracted must be encased within XML tags.

  • While the compiler will accept any valid XML tags, I generally use a specific set of tags for each element that I'm commenting. In the remainder of this post I'll describe how I comment classes and properties. I'll finish my discussion of XML comments in the next post where I describe how I comment methods and events.

    At the very minimum, I use the <summary> tag to provide a short summary of the class. This summary describes what the class is and its use. A more detailed description goes in the <remarks> tag. Other tags I may use in a class comments block are <example> (usually used with the <code> tag), and <seealso> to add a See Also section to the documentation containing links to related classes. Finally, I add the non-standard tag <author> to all my class comment blocks.

    Here's an example:

    ''' <summary>
    ''' A simple class that represents a US mailing address.
    ''' </summary>
    ''' Keven Lehmann
    ''' <remarks>
    ''' <para>
    ''' This class contains properties for all of the elements in a common US
    ''' mailing address. It provides basic validation for state abbreviations
    ''' and ZIP code formats (basic and ZIP+4) but does not verify that the
    ''' address represents an actual US mailing address.
    ''' </para>
    ''' <para>
    ''' The following example demonstrates a typical use for this class:
    ''' </para>
    ''' <example>
    ''' <code>
    ''' Public Function GetSampleAddress() as String
    ''' Dim addr as USAddress = new USAddress()
    ''' addr.Recipient = "Keven Lehmann"
    ''' addr.Street = "101 Main St"
    ''' addr.City = "Somewhere"
    ''' addr.State = "MD"
    ''' addr.ZIP = "21212-1212"
    ''' Return addr.ToUspsString()
    ''' End Function
    ''' </code>
    ''' </example>
    ''' </remarks>
    Public Class USAddress
    End Class

    For properties, I always include the <summary> and <value> tags, although <value> often turns out to be a rehashing of the <summary>. If I feel there is anything about the property that needs extra clarification, I'll include that in a <remarks> tag. Other common tags I may use with a property are <example> for examples of use and <see> to refer to related functions from within the body of the documentation.

    Here is an example:

    ''' <summary>
    ''' Gets the <see cref="Person"></see>'s full name.
    ''' </summary>
    ''' <value>
    ''' The full name of the <b>Person</b>, comprising their
    ''' <see cref="FirstName"></see> and <see cref="LastName"></see>,
    ''' separated by a space.
    ''' </value>
    Public ReadOnly Property FullName() As String
    End Property

    That's it for right now. Next time I'll finish up XML comments by covering Method and Event comments.