Creating Documentation in .NET

    Open notebookHigh-quality documentation is an integral part of a successful software product. Creating a complete and understandable description of all the functions and capabilities of a program and a software component requires a lot of effort and patience. In this article, I will discuss some practical aspects of creating documentation for .NET components.

    Suppose that we have some .NET library ready for developers or almost ready (they are also end users). The library API is impeccable, the number of bugs is impressively small, and indeed it is not a library, but simply a storehouse of perfect code. The point is small - to explain to users how to work with this wonderful product.

    There are different approaches to writing documentation. Some teams prefer to start creating documentation at the start of product creation. Others postpone writing manuals to finish work. In some teams, documentation is written by special people who go from developer to developer and from manager to manager, accumulating knowledge about the product. Many small teams do not have such special people, which is why the documentation is often written by the developer or developers. Someone uses third-party tools like Help & Manual, in which, as in a real-life text editor, you can create a very complex layout and get documentation in a variety of formats at the output. Many people use a different approach, widely popularized recently - writing documentation directly in the program / library code.


    In my work I used both third-party tools and built-in ones. He began to write documentation both immediately and at the last moment. As a result, I decided for myself that it’s better to start writing documentation in the second half of the product creation, as the closer to completion, the more stable the API, the set of features, etc., which means that the documentation will have to be adjusted less often. Writing documentation directly in code also ultimately turned out to be more convenient than in third-party programs, although at first it seemed quite the opposite. This article is about how to write documentation directly in code.

    We describe API


    The C # and VB.NET compilers can recognize comments formatted in a special way (xml comments) and, if necessary, create an xml file that can then be used to create documentation. To take advantage of this opportunity, you need to describe all public classes and methods using xml comments. It looks something like this:
    /// 
    /// Gets the R component from ABGR value returned by 
    /// ReadRGBAImage.
    /// 

    /// The ABGR value.
    /// The R component from ABGR value.
    public static int GetR (int abgr)
    {
        return (abgr & 0xff);
    }

    By default, creating an xml file from comments is disabled. You need to enable it in the project properties on the Build tab.
    Enable Xml comments

    As a result, during compilation, in addition to the file of your assembly, an xml-file will be generated that contains all xml-comments from the code (including comments on non-public structures). This file itself is useful in that if you put it next to the assembly (your dll), this will allow the IntelliSense function in Visual Studio to display descriptions for the methods when the user types the code. Here is an example of how it would look for the GetR function shown above:
    image

    However, in most cases, the generated xml file contains comments on internal structures that users do not need or cannot see. Below I will write how to automatically clear the xml-file so that it contains only descriptions of public methods.

    I will not consider all the xml tags in detail, but just try to briefly describe the most commonly used ones.

    The summary tag is used to briefly describe the purpose of a class, interface, enum, methods and properties of a class or interface, and enumeration members. The param tag allows you to describe the parameter accepted by the function. This tag must be used for each accepted parameter. The returns tag is used to describe the return value of a function. Tagvalue is useful for describing a value that takes and / or returns some property. In a sense, the value tag is an analogue of the returns tag.
    /// 
    /// Gets the font ascent.
    /// 

    /// The font ascent.
    /// Ascent is the maximum height above the baseline reached
    /// by glyphs in this font, excluding the height of glyphs for
    /// accented characters.

    public short Ascent
    {
        get
        {
            return Impl.Ascent;
        }
    }

    Very useful (and, unfortunately, often ignored) is the remarks tag , which allows you to specify notes on the described entity. This tag can be used almost everywhere except for the description of enumeration members. In fact, it is also possible for enumeration members, but in the documentation issued in the vs2005 style, these notes simply will not be visible, which reduces the usefulness of such notes.

    I will give a few more practical notes / recommendations.

    Download and install the extension for Visual Studio called GhostDoc. This extension works in all studio versions (starting with version 2005) and greatly simplifies the creation of xml comments. By pressing Ctrl-Shift-D, this extension inserts a description of the entity on which the cursor is currently located. All the necessary tags are inserted, and a description text is generated based on, for example, the name of the method and the name of its parameters. Often it remains only to correct and supplement the generated text.

    The disadvantage of writing documentation directly in the code is that there are sometimes more comments than code, which can make it very difficult to read the code. To circumvent this problem, it is very convenient to completely separate the public interface and implementation.

    If you have several overloaded methods, then when generating documentation for them a separate page will be created ( here is an examplesuch a page). The text for this page must be indicated in the overloads tag in the description of one of the overloaded methods.
    /// 
    /// Saves the font bytes to the specified stream.
    /// 

    /// The stream to save font bytes to.
    /// Saves the font bytes to a file or a stream.
    public void Save (Stream stream)
    {
        Impl.Save (stream);
    }

    If you want to give a reference to another method or type in the description of one method, then you need to use a design of the form Текст ссылки, where X is an optional prefix denoting the type of entity (T for a class, M for a method, P for a property, O for a group of overloaded methods), and MEMBER is the full or partial specification of the entity. A partial specification and a missing prefix can be used, for example, for links between two methods of the same class or between two entities of the same namespace.

    An example of using a partial specification (PdfFontEmbedStyle is in the same namespace as PdfFont):
    public sealed class PdfFont
    {
        ...
        /// 
        /// Gets or sets the  value that specifies
        /// how this font is embedded into the document.
        /// 

        /// The  value that specifies
        /// how this font is embedded into the document.

        public PdfFontEmbedStyle EmbedStyle
        {
            get
            {
                return Impl.EmbedStyle;
            }
            set
            {
                Impl.EmbedStyle = value;
            }
        }
    }

    If you are referring to an entity from another namespace, to a group of overloaded methods, or to any specific method from a group of overloaded methods, then you must use the full specification. Examples of the full specification:
    • property reference
    • method reference
    • link to a group of overloaded methods
    • class reference

    As you see, the full specification also indicates the parameters of the method, which allows you to uniquely identify the link, but complicates the writing of links. You can save manual labor by copying the full specifications from a previously compiled xml file.

    With links to a group of overloaded methods, one nuisance is associated. Visual Studio requires such links to be viewable O:XXX.YYY, while Sandcastle Help File Builder requires such links to be viewable Overload:XXX.YYY. To solve this problem, I use a simple script that is called on the Post-build event and replaces in the xml-file O:with Overload:, which is quite bearable.

    Use a good old tag to link to some external article of your documentation (not related to the API description) or to some resource on the Internetwith the href attribute. For example,Текст ссылки or Текст ссылки. In the first example, the name of the document with an external article is presented in the form “TOPIC_ID.htm”. The topic id will be discussed later.

    You can read more deeply about documenting code using xml comments in these articles:


    We generate the documentation file


    After the xml-description of your component is ready, you can generate a documentation file. I prefer to use the Sandcastle + Sandcastle Help File Builder (SHFB) bundle for this. I note that some prefer DocProject. This requires:
    1. Download and install Sandcastle
      sandcastle.codeplex.com
    2. Download and install Sandcastle Help File Builder
      shfb.codeplex.com
    3. Download and apply the patch for styles used by Sandcastle
      sandcastlestyles.codeplex.com
    4. If you have problems with the assembly of documentation in HTML Help format, you need to check that itircl.dll is present in the system and registered. Usually this dll lies in System32, it needs to be registered through regsvr32. Read more here:
      frogleg.mvps.org/helptechnologies/htmlhelp/hhtips.html#hhc6003

    We start assembling the documentation in chm format. To do this, run Sandcastle Help File Builder and set up Project Properties. In the “ComponentConfigurations” property, you can configure additional components used during assembly. If you do not know what components you may need, then you can select all components. In any case, I recommend that you always use IntelliSense Component, since it automatically creates a copy of the input xml file, cleared of all non-public comments. It is the result of this component that needs to be given to users, and not the xml file that the compiler will create.

    I also recommend immediately changing the following properties:
    • Build section: FrameworkVersion
    • Help File sections: CopyrightHref, CopyrightText, FeedbackEMailAddress, FeedbackEMailLinkText, HelpTitle, HtmlHelpName
    • section Paths: OutputPath

    Next, in the Project Explorer window, add Documentation Sources. I recommend choosing a specific assembly and an xml file with comments for it, and not a C # / VB.NET project file. If you select a project file, sometimes there is a problem with the fact that changes in xml comments are not reflected in the documentation. Who is to blame for this, I do not know.

    Another important step is to describe namespaces in SHFB. Xml comments in the code do not work for namespace, so you need to do this manually. The Comments section and the NamespaceSummaries property in it will help here. In the description of namespace you can use standard html tags.
    image
    Project setup is complete, it's time to build the .hm file. We select Documentation-> Build Project, and if everything was done correctly, we get a beautiful documentation file in the style of MSDN.

    Useful links on the topic:


    Writing articles


    However, do not stop there - a single API description of your component is not enough for full documentation. Good documentation usually contains additional articles, examples, FAQs, etc.

    In the Project Explorer window, add a new Content Layout element - this is a description (indicating the relative position) of what is included in the documentation. New content (topics) is added to the Content Layout window. Each article is described in MAML format (.aml files), it is an xml-based format. Sandcastle Help File Builder comes with a set of predefined templates, which greatly simplifies the debut in writing articles. I mainly use the Conceptual template , less commonly Walkthrough .

    The description of each article begins with the topic id - a unique identifier. Based on this identifier, an html file is generated, which later gets into chm. The generated html file is named in the form “TOPIC_ID.htm”. This topic id is also used to link to an article from other articles or xml comments in code.

    When creating an article, it is proposed to save it to a file with the name “TOPIC_ID.aml”. When creating, you can and should immediately indicate the normal name for the file.

    Consider some of the controls in SHFB that are useful when editing articles.
    image

    Default topic
    Sets the start page of the documentation (will be shown when
    opening the documentation.
    API insertion point
    Sets the position at which the API description
    generated from the xml file will be inserted . Depending on which option is selected, the
    API description will be inserted
    either before, after, or as a child of the element so marked
    .
    Preview topic
    Preview the current article.
    image
    Insert link to article in documentation. Use topic id
    as the address.
    SHFB tags
    Insert standard tags for article markup.

    The Entity Reference window (located on the right) can be used to insert links to the description of functions / methods, etc. entities from the code. This way of inserting links is not very convenient in my opinion, since you need to first open the text of the article, then open the Entity Reference window, then in this window write the part or the full name of the entity, then find the desired line in the list and double-click on it. All this will lead to the fact that the link at the cursor position is inserted into the article. I prefer to write links with my hands, and find the text for the links in the build log (the log from the previous build can be opened in a text editor).

    To insert code in an article, use the tag. Например:

    private void helloWorld()
    {
        Console.WriteLine(”Hello World!”);
    }

    To insert images, do the following:
    1. In the Project Explorer window, select Add, then the Existing Item and select the desired picture.
      Add image
    2. In the properties of the added file, change BuildAction to Image, and the ImageId property to a convenient name (it will be used in links to this image).
      Image properties

    Further, you can use the image in the articles as follows:

    Unfortunately, in the current version of SHFB, the editor is far from perfect. For example, tags do not close automatically, a lot of actions have to be done with the mouse (there are no hotkeys), not all standard tags have corresponding elements on the toolbar. It’s paradoxical, but for most actions with aml files it’s more convenient to use Visual Studio. Of course, you can use any other convenient xml-editor for writing articles.

    I described a solution to basic needs when writing articles for documentation. If you want to study the topic better, I recommend the following links:


    Integration into the build process


    You can include the project file (* .shfbproj) from Sandcastle Help File Builder in the solution of Visual Studio, however, at the moment there is no way to use it as a full-fledged project. That is, you cannot see the contents of such a project, the project will only be added to the Solution Items group.

    Adding is done as follows:
    1. For the solution, select Add-> Existing Item ..., add the documentation project. It will be added to the Solution Items folder.
      SHFB project in Visual Studio
    2. Right-click on the added item and select Open With ... In the dialog that opens, add the “Sandcastle Help File Builder GUI” and set it as the default editor.

    After that, the documentation project can be opened from Visual Studio.

    Building documentation from the command line is more useful. Such assembly can be done at the Post-Build event or in other cases. Collecting documentation from the command line is very simple with the following command:
    %SystemRoot%\Microsoft.NET\Framework\v3.5\MSBuild.exe" /p:Configuration=Release Help.shfbproj
    On this line, Help.shfbproj is the name of the documentation project.

    I hope this article helps you start writing documentation for your projects (if you are not already doing this) for which your users will probably thank you. Good luck in writing the documentation!

    Also popular now: