Documentation

Files

  • Include a README.md file at the root of the project that includes the following information:
    • Dependencies
    • Basic configuration
    • Basic command line
    • Links to other documentation
  • Include a LICENSE file at the root of the project that describes licensing restrictions.

Language

  • Use U.S. English spelling and grammar.
  • Use full sentences or clauses; do not use lists of keywords or short phrases.
  • Use the prepositional possessive for code elements (i.e. write “the value of <paramref name="prop">“ instead of “<paramref name="prop">’s value”).

Style

  • An API should document itself. Code documentation can sometimes be very obvious and simple. This indicates to the caller that it really is that simple.
  • Document similar members consistently; it’s better to repeat yourself or to use the same structure for all members as long as the documentation is useful for each member.
  • Include conceptual documentation for each concept/component to provide an overview and examples of how to use the product.
  • Move longer documentation out of the code and into higher-level conceptual documentation or examples.

XML Documentation

  • Include XML documentation to enhance code-completion.
  • Document public and protected elements.
  • Do not document private or internal members.
  • Include references to important members from class documentation.

Dependencies

  • Do not introduce dependencies for documentation.
  • Do not add using statements for documentation; if necessary, include the required namespace in the documentation reference itself.

Tags

  • Format block tags onto separate lines. E.g. <summary>, <param>, <remarks> and <returns>
  • Use <c> tags for the keywords null, false and true.
  • Use <see> tags to refer to properties, methods and classes.
  • Use <paramref> and <typeparamref> tags to refer to method parameters.
  • Use the <inheritdoc/> tag for method overrides or interface implementations.
  • Use a <remarks> section to indicate usage and to link to related members. It’s sometimes good to include references to other types or methods in descriptive sentences in addition to listing them in the <seealso> section.

Examples

Classes

  • An abstract implementation of an interface should use the following form:
    1. /// <summary>
    2. /// A base implementation of the <see cref="IMaker"/> interface.
    3. /// </summary>
    4. public abstract class MakerBase : IMaker { }
  • The standard (or only) implementation of an interface should use the following form:
    1. /// <summary>
    2. /// The standard implementation of the <see cref="IMaker"/> interface.
    3. /// </summary>
    4. public class Maker : IMaker { }
  • For one of several implementations, use the following form:
    1. /// <summary>
    2. /// An implementation of the <see cref="IMaker"/> interface that works with a
    3. /// Windows service.
    4. /// </summary>
    5. public class WindowsServerBasedMaker : IMaker { }

Methods

  • Document parameters in declaration order.
  • Do not document exceptions that are bugs (e.g. ArgumentNullException).
  • Refer to the first parameter as “given”; subsequent parameter references do not need to be qualified. For example,
    1. /// Gets the value of the given <paramref name="prop"/> in <paramref name="obj">.`
  • The documentation should indicate which values are acceptable inputs for a parameter (e.g. whether or not it can be null or empty (for strings) or the range of acceptable values (for numbers). The example below demonstrates all of these principles:
    ```csharp
    ///
    /// Fills the with random text using the given
    /// and .
    ///

    ///
    /// The generator to use to create the random text; cannot be null.
    ///
    ///
    /// The values with which to seed the random generator; cannot be null.
    ///
    void FillWithRandomText(IRandomGenerator generator, string seedValues);
  • For methods that return a bool, use the following form:
    1. /// <summary>
    2. /// Gets a value indicating whether the value of the given <paramref name="prop"/>
    3. /// in <paramref name="obj"> has changed since it was loaded from or last stored.
    4. /// </summary>
    5. /// <param name="obj">
    6. /// The object to test; cannot be <c>null</c>.
    7. /// </param>
    8. /// <param name="prop">
    9. /// The property to test; cannot be <c>null</c>.
    10. /// </param>
    11. /// <returns>
    12. /// <c>true</c> if the value has been modified; otherwise <c>false</c>.
    13. /// </returns>
    14. bool ValueModified(object obj, IMetaProperty prop);
  • Exceptions should begin with “If…” as shown in the example below:
    1. /// <summary>
    2. /// Gets the <paramref name="value"/> as formatted according to its type.
    3. /// </summary>
    4. /// <param name="value">
    5. /// The value to format; can be <c>null</c>.
    6. /// </param>
    7. /// <param name="hints">
    8. /// Hints indicating context and formatting requirements.
    9. /// </param>
    10. /// <returns>
    11. /// The <paramref name="value"/> as formatted according to its type.
    12. /// </returns>
    13. /// <exception cref="FormatException">
    14. /// If <paramref name="value"/> cannot be formatted.
    15. /// </exception>
    16. string FormatValue(object value, CommandTextFormatHints hints);

Constructors

  • Do not use <inheritdoc/> for constructors.
  • Documentation for parameters that initialize public or protected properties should reference that property instead of repeating documentation for properties in the documentation for the initializing parameter in the constructor.
  • Parameters assigned to read-only properties should use the form “Initializes the value of …”
  • Parameters assigned to read/write properties should use the form “Sets the initial value of …”
  1. class SortOrderAspect
  2. {
  3. /// <summary>
  4. /// Initializes a new instance of the <see cref="SortOrderAspect"/> class.
  5. /// </summary>
  6. /// <param name="sortOrderProperty">
  7. /// Initializes the value of <see cref="SortOrderProperty"/>.
  8. /// </param>
  9. /// <param name="sortOrderProperty">
  10. /// Sets the initial value of <see cref="Enabled"/>.
  11. /// </param>
  12. public SortOrderAspect(IMetaProperty sortOrderProperty, bool enabled)
  13. {
  14. }
  15. /// <summary>
  16. /// Gets the property used to create a manual sorting for objects using the
  17. /// <see cref="IMetaClass"/> to which this aspect is attached.
  18. /// </summary>
  19. IMetaProperty SortOrderProperty { get; private set; }
  20. /// <summary>
  21. /// Gets or sets a value indicating whether this <see cref="SortOrderAspect"/> is
  22. /// enabled.
  23. /// </summary>
  24. IMetaProperty Enabled { get; set; }
  25. }

Properties

  • If a property has a non-public setter, do not include the “or sets” part to avoid confusion for public users of the property.
  • Include only the <summary> tag. The <value> tag is not needed.
  • The documentation for read-only properties must begin with “Gets”.
    1. /// <summary>
    2. /// Gets the environment within which the database runs.
    3. /// </summary>
    4. IDatabaseEnvironment Environment { get; private set; }
  • The documentation for read/write properties should begin with “Gets or sets”, as follows:
    1. /// <summary>
    2. /// Gets or sets the database type.
    3. /// </summary>
    4. DatabaseType DatabaseType { get; }
  • Boolean properties should have the following form, formatting the value element as follows:
    1. /// <summary>
    2. /// Gets a value indicating whether the database in <see cref="Settings"/> exists.
    3. /// </summary>
    4. bool Exists { get; }
  • For properties with generic names, take care to specify exactly what the property does, rather than writing vague documentation like “gets or sets a value indicating whether this object is enabled”. Tell the user what “enabled” means in the context of the property being documented:
    1. /// <summary>
    2. /// Gets or sets a value indicating whether automatic updating of the sort-order
    3. /// is enabled.
    4. /// </summary>
    5. bool Enabled { get; }

Full Example

The example below includes many of the best practices outlined in the previous sections. It includes <seealso>, <exception> and several <paramref> tags as well as clearly stating what it does with those parameters and their acceptable values. Finally, it includes extra detail in the <remarks> section instead of the <summary>.

  1. /// <summary>
  2. /// Copies the entire contents of the given <paramref name="input"/> stream to the
  3. /// given <paramref name="output"/> stream.
  4. /// <param name="input">
  5. /// The stream from which to copy data; cannot be <c>null</c>.
  6. /// </param>
  7. /// <param name="output">
  8. /// The stream to which to copy data; cannot be <c>null</c>.
  9. /// </param>
  10. /// <remarks>
  11. /// Uses a 32KB buffer; use the <see cref="CopyTo(Stream,Stream,int)"/> overload to
  12. /// use a different buffer size.
  13. /// </remarks>
  14. /// <seealso cref="CopyTo(Stream,Stream,int)"/>
  15. /// <exception cref="IOException">If the <paramref name="input"/> cannot be read
  16. /// or is not at the head of the stream and cannot perform a seek or if the
  17. /// <paramref name="output"/> cannot be written.</exception>
  18. public static void CopyTo(this Stream input, Stream output)