Theme index -- Keyboard shortcut: 'u'  Previous theme in this lecture -- Keyboard shortcut: 'p'  Next slide in this lecture -- Keyboard shortcut: 'n'Documentation of Object-oriented Programs

A complete PDF version of the text book is now available. The PDF version is an almost complete subset of the HTML version (where only a few, long program listings have been removed). See here.

56.  Documentation of Object-oriented Programs

 

56.1.  Program Documentation
Contents   Up Previous Next   Slide Annotated slide Aggregated slides    Subject index Program index Exercise index 

Documentation may serve several different purposes

  • User and usage documentation

    • Describes how the program is used

    • Oriented towards the end-user of the program

  • Documentation of types - for external purposes

    • Describes external properties of each type

    • Oriented towards programmers of client types

  • Documentation of programs or types - for internal purposes

    • Describes internal properties of a program or type

    • Oriented towards current and future developers of the current program or type

 

56.2.  Program Documentation - When and Where?
Contents   Up Previous Next   Slide Annotated slide Aggregated slides    Subject index Program index Exercise index 

  • Temporal: When is the documentation written?

    • The documentation is written before the program

    • The documentation is written together with the program

    • The documentation is written after the program is completed

  • Spatial: How is the documentation organized relative to the program structure

    • The documentation is written in documents separate from the program

    • The documentation and program are written and organized together

      • The documentation resides inside the program

      • The program resides inside the documentation

 

56.3.  Documentation of C# Programs
Contents   Up Previous Next   Slide Annotated slide Aggregated slides    Subject index Program index Exercise index 

Documentation of C# programs can be written in documentation comments

  • Documentation in C#

    • Selected types and members of types are documented

    • Documentation is written in distinguished comments

    • The documentation is intended to be written together with the program

 

56.4.  A documentation example in C#
Contents   Up Previous Next   Slide Annotated slide Aggregated slides    Subject index Program index Exercise index 

Documentation of class BankAccount

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
using System;

/// <summary> 
///   A simple bank account created as an everyday example
///   for the OOP course. Used in particular for demonstrating inheritance.
/// </summary>
public class BankAccount {

   private double interestRate;
   private string owner;
   private double balance;

   /// <summary>
   ///  Construct a bank account from owner. 
   ///  The interestRate is given the default value 0.0.
   ///  The balance is given the default value 0.0.
   /// </summary>
   /// <param name = "owner"> The owners name. A string.</param>
   public BankAccount(string owner): 
     this(owner, 0.0, 0.0) {
   }

   /// <summary>
   ///  Construct a bank account from owner, balance, and interestRate.
   ///  The interestRate is given the default value 0.0.
   /// </summary>
   /// <param name = "owner"> The owners name </param>
   /// <param name = "balance"> The initial amount of this account</param>
   public BankAccount(string owner, double balance): 
     this(owner, balance, 0.0) {
   }

   /// <summary>
   ///  Construct a bank account from owner, balance, and interestRate. 
   /// </summary>
   /// <param name = "owner"> The owners name </param>
   /// <param name = "balance"> The initial amount of this account</param>
   /// <param name = "interestRate"> 
   ///    The interest rate. 
   ///    Annual interet is calculated as balance * interestRate 
   /// </param>
   public BankAccount(string owner, double balance, double interestRate) {
      this.interestRate = interestRate;
      this.owner = owner; 
      this.balance = balance;
   }

   /// <summary>
   ///  Returns the current amount of the bank account 
   ///  without affecting the account.
   /// </summary>
   /// <value> Accesses the amount of money in the account</value>
   public double Balance {
     get{
      return balance;
     }
   }

   /// <summary>
   ///   Return the interest rate of the account
   /// </summary>
   /// <value> Accesses the interest rate of the account </value>
   public double InterestRate {
     get{
      return interestRate;
     }
   }

   /// <summary>
   ///   Withdraw an amount of money from the account.
   ///   This decreases the balance of the account.
   /// </summary>
   /// <param name = "amount"> 
   ///  The amount of money to withdraw from the account.
   ///  Precondition: Must be non-negative.
   /// </param>   
   public void Withdraw (double amount) {
      balance -= amount;
   }

   /// <summary>
   ///   Withdraw an amount of money from the account.
   ///   This increases the balance of the account.
   /// </summary>
   /// <param name = "amount"> 
   ///  The amount of money to deposit to the account.
   ///  Precondition: Must be non-negative.
   /// </param>   
   public void Deposit (double amount) {
      balance += amount;
   }

   /// <summary>
   ///   Add the annual interest to the account.
   ///   This may increase the current balance of the account.
   /// </summary>
   public void AddInterests() {
      balance = balance + balance * interestRate;
   }    

   /// <summary>
   ///   Return a text string that represents this account
   ///   for output purposes
   /// </summary>
   public override string ToString() {
      return owner + "'s account holds " +
            + balance + " kroner";
   }
}
Program 56.1    The class BankAccount - with documentation comments.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
<?xml version="1.0"?>
<?xml-stylesheet href="doc.xsl" type="text/xsl"?>
<doc>
    <assembly>
        <name>bank-account</name>
    </assembly>
    <members>
        <member name="T:BankAccount">
            <summary> 
              A simple bank account created as an everyday example
              for the OOP course. Used in particular for demonstrating inheritance.
            </summary>
        </member>
        <member name="M:BankAccount.#ctor(System.String)">
            <summary>
             Construct a bank account from owner. 
             The interestRate is given the default value 0.0.
             The balance is given the default value 0.0.
            </summary>
            <param name = "owner"> The owners name. A string.</param>
        </member>
        <member name="M:BankAccount.#ctor(System.String,System.Double)">
            <summary>
             Construct a bank account from owner, balance, and interestRate.
             The interestRate is given the default value 0.0.
            </summary>
            <param name = "owner"> The owners name </param>
            <param name = "balance"> The initial amount of this account</param>
        </member>
        <member name="M:BankAccount.#ctor(System.String,System.Double,System.Double)">
            <summary>
             Construct a bank account from owner, balance, and interestRate. 
            </summary>
            <param name = "owner"> The owners name </param>
            <param name = "balance"> The initial amount of this account</param>
            <param name = "interestRate"> 
               The interest rate. 
               Annual interet is calculated as balance * interestRate 
            </param>
        </member>
        <member name="M:BankAccount.Withdraw(System.Double)">
            <summary>
              Withdraw an amount of money from the account.
              This decreases the balance of the account.
            </summary>
            <param name = "amount"> 
             The amount of money to withdraw from the account.
             Precondition: Must be non-negative.
            </param>   
        </member>
        <member name="M:BankAccount.Deposit(System.Double)">
            <summary>
              Withdraw an amount of money from the account.
              This increases the balance of the account.
            </summary>
            <param name = "amount"> 
             The amount of money to deposit to the account.
             Precondition: Must be non-negative.
            </param>   
        </member>
        <member name="M:BankAccount.AddInterests">
            <summary>
              Add the annual interest to the account.
              This may increase the current balance of the account.
            </summary>
        </member>
        <member name="M:BankAccount.ToString">
            <summary>
              Return a text string that represents this account
              for output purposes
            </summary>
        </member>
        <member name="P:BankAccount.Balance">
            <summary>
             Returns the current amount of the bank account 
             without affecting the account.
            </summary>
             <value> Accesses the amount of money in the account</value>
        </member>
        <member name="P:BankAccount.InterestRate">
            <summary>
              Return the interest rate of the account
            </summary>
             <value> Accesses the interest rate of the account </value>
        </member>
    </members>
</doc>
Program 56.2    The generated XML documentation - augmented manually with xml-stylesheet clause.

Figure 56.1    A screenshot of the HTML rendering of the XML documentation file

 

56.5.  The XML Documentation Language for C#
Contents   Up Previous Next   Slide Annotated slide Aggregated slides    Subject index Program index Exercise index 

The elements of the C# documentation language

  • <summary> summary text </summary>

    • Describes types as well as type members

  • <remarks>description</remarks>

    • Additional information about a type, supplementing the information specified in a summary.

  • <param name="p">parameter description</param>

    • Description of the parameter p

  • <value>property-description</value>

    • Documents a property (the value which is represented by the property)

  • <typeparam name="name">description</typeparam>

    • Documents a type parameter of a generic type or method

  • <returns>description</returns>

    • Describes the return value of a method

  • <example>description</example>

    • An example of how to use a method. May contain code elements

  • <c>text</c>

    • Text indicated/emphasized as code

  • <code>text</code>

    • Text indicated/emphasized - multiple lines of code

  • <exception cref="e">description</exception>

    • Documents the exception e

  • <include file='filename' path='tagpath[@name="id"]' />

    • Include part of another documentation file in the current documentation.

    • Relies on XPath expressions.

  • <list> ... </list>

    • A bullet list facility. Can be used in summaries.

    • Relies on additional nested elements such as <listheader> ... </listheader> and <item> ... </item>

  • <para>content</para>

    • A paragraph. Used within summaries and remarks for markup of a paragraph.

  • <paramref name="name"/>

    • Used for references to parameters within summary or remarks

  • <see cref="member"/>

    • A reference to a member

  • <seealso cref="member"/>

    • Contributes to a separate "See also" clause of the documentation

  • <typeparamref name="name"/>

    • Format the name of a type parameter in distinct way.

In addition to the XML elements mentioned above you can invent and use your own "tags"

 

56.6.  Tool support: The C# Compiler
Contents   Up Previous Next   Slide Annotated slide Aggregated slides    Subject index Program index Exercise index 

The /doc: option of the C# compiler and the generated XML file.

  • The C# Compiler

    • Via use of the /doc: compiler option an XML file can be produced

    • The XML file is not useful for direct presentation

    • The XML format does not contain full type information

  • Transformation of XML documentation to HTML

    • Via use of an XSLT stylesheet - made by Anders Hejlsberg

    • A stylesheet is provided with the book C# to the Point

      • Primitive and obsolete!

 

56.7.  Tool support: Doxygen
Contents   Up Previous Next   Slide Annotated slide Aggregated slides    Subject index Program index Exercise index 

Doxygen is a third part interface documentation tool written by Dimitri van Heesch, originally developed for C++, C, and Java

  • Doxygen

    • A documentation tool - for multiple programming languages

    • Can produce HTML documentation directly from the C# source

      • Can also produce documentation in other representations

    • The intermediate XML documentation - made by the C# compiler - is not used

    • Can be controlled from a GUI front end: Doxywizard

    • www.doxygen.org


Exercise 15.1. Install Doxygen

Download and install the latest version of Doxygen from www.doxygen.org on your computer. Consult the information about Doxygen on the accompanying slide. Also, consult our simple example of BankAccount documentation made by Doxygen.

More specifically on Windows (as of February 2010) go to the Doxygen Download page and download the binary distribution doxygen-1.6.3-setup.exe. The direct link is here. After installation, start the Doxywizard.

Consult the Doxygen documentation, maybe in particular the documentation of the GUI front-end. In addition, read Dan Jensens note Installing and Using Doxygen.

There is no solution to this exercise


 

56.8.  Tool support: Other possibilities
Contents   Up Previous Next   Slide Annotated slide Aggregated slides    Subject index Program index Exercise index 

  • NDoc

    • Documentation tool that collects documentation from assemblies and XML documentation file

    • Specific to .NET

    • Not actively developed since 2005

      • Does not support C# 2.0

  • Sandcastle

    • Generates MSDN style documentation

      • Based on assemblies (reflection) and the XML documentation file

      • Used internally by Microsoft to generate the .NET library documentation

    • Still difficult to install and use!!!

  • Visual Studio, regular or express

    • The documentation provided in documentation comments can be used by Intellisense

 

56.9.  Another documentation example in C#
Contents   Up Previous Next   Slide Annotated slide Aggregated slides    Subject index Program index Exercise index 

Documentation of class BankAccount and its three subclasses

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
using System;

/// \mainpage Doxygen Demo.
/// \section intro_sec Introduction
/// This documentation serves as a Doxygen demonstration.
/// We document the BankAccount class and a number of 
/// specialized bank account classes.

/// <summary> 
///   A simple bank account created as an everyday example
///   for the OOP course. Used in particular for demonstrating inheritance.
/// </summary>
/// <example>
///   <code>
///      BankAccount ba = new BankAccount("Peter");
///      ba.Deposit(100.0);
///      ba.Withdraw(50.0);
///   </code>
/// </example>
public class BankAccount {

   protected double interestRate;
   protected string owner;
   protected decimal balance;

   /// <summary>
   ///  Construct a bank account from owner, balance, and interestRate. 
   /// </summary>
   /// <param name = "o"> The owners name </param>
   /// <param name = "b"> The initial amount of this account</param>
   /// <param name = "ir"> 
   ///    The interest rate. 
   ///    Annual interet is calculated as balance * interestRate 
   /// </param>
   public BankAccount(string o, decimal b, double ir) {
      this.interestRate = ir;
      this.owner = o; 
      this.balance = b;
   }

   /// <summary>
   ///  Construct a bank account from owner and interestRate. 
   /// </summary>
   /// <param name = "o"> The owners name </param>
   /// <param name = "ir"> 
   ///    The interest rate. 
   ///    Annual interet is calculated as balance * interestRate 
   /// </param>
   public BankAccount(string o, double ir):
     this(o, 0.0M, ir) {
   }

   /// <summary>
   ///   Returns the current amount of the bank account 
   ///  with affecting the account.
   /// </summary>
   ///  <value> The amount of money </value>
   public virtual decimal Balance {
     get {return balance;}
   }

   /// <summary>
   /// <list>
   ///   <item> Withdraw an amount of money from the account. </item>
   ///   <item> This decreases the balance of the account. </item>
   /// <list>
   /// </summary>
   /// <param name = "amount"> 
   ///  The amount of money to withdraw from the account.
   ///  Precondition: Must be non-negative.
   /// </param>   
   public virtual void Withdraw (decimal amount) {
      balance -= amount;
   }

   /// <summary>
   ///   Withdraw an amount of money from the account.
   ///   This increases the balance of the account.
   /// </summary>
   /// <param name = "amount"> 
   ///  The amount of money to deposit to the account.
   ///  Precondition: Must be non-negative.
   /// </param>   
   public virtual void Deposit (decimal amount) {
      balance += amount;
   }
 
   /// <summary>
   ///  Add the annual interest to the account.
   ///  This may increase the current balance of the account.
   /// </summary>
   public virtual void AddInterests() {
      balance += balance * (Decimal)interestRate;
   }    

   /// <summary>
   ///   Return a text string that represents this account
   ///   for output purposes
   /// </summary>
   public override string ToString() {
      return owner + "'s account holds " +
            + balance + " kroner";
   }
}
Program 56.3    The base class BankAccount.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
using System;

/// <summary> 
///   A specialization of BankAccount.
/// </summary>
public class CheckAccount: BankAccount {

   /// <summary> A constructor that constructs a CheckAccount on the 
   /// basis of an owner and the interestrate</summary>
   /// <param name = "o"> The owners name </param>
   /// <param name = "ir"> The interestrate </param>
   public CheckAccount(string o, double ir): 
     base(o, 0.0M, ir) {
   }

   /// <summary> A constructor that constructs a CheckAccount on the 
   /// basis of an owner, balance, and the interestrate</summary>
   /// <param name = "o"> The owners name </param>
   /// <param name = "b"> The initial balance of the account </param>
   /// <param name = "ir"> The interestrate </param>
   public CheckAccount(string o, decimal b, double ir): 
     base(o, b, ir) {
   }

   /// <summary> Withdraw an amount from the check account </summary>
   /// <param name = "amount"> The amount withdrawn </param>
   public override void Withdraw (decimal amount) {
      balance -= amount;
      if (amount < balance)
         interestRate = -0.10;
   }

   /// <summary> Returns a string which represents the account </summary>
   public override string ToString() {
      return owner + "'s check account holds " +
            + balance + " kroner";
   }
}
Program 56.4    The class CheckAccount.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
using System;

/// <summary> 
///   A specialization of BankAccount for saving purposes.
/// </summary>
public class SavingsAccount: BankAccount {

   /// <summary> A constructor that constructs a Savings account on the 
   /// basis of an owner and the interestrate. The balanced defaults
   /// to 0.0.</summary>
   /// <param name = "o"> The owners name </param>
   /// <param name = "ir"> The interestrate </param>
   public SavingsAccount(string o, double ir): 
     base(o, 0.0M, ir) {
   }

   /// <summary> A constructor that constructs a SavingsAccount on the 
   /// basis of an owner, balance, and the interestrate</summary>
   /// <param name = "o"> The owners name </param>
   /// <param name = "b"> The initial balance of the account </param>
   /// <param name = "ir"> The interestrate </param>
   public SavingsAccount(string o, decimal b, double ir): 
     base(o, b, ir) {
   }

   /// <summary> Withdraw an amount from the savings account </summary>
   /// <param name = "amount"> The amount withdrawn </param>
   /// <exception cref = "Exception"> In case of insufficient funds
   ///    an exception is thrown </exception>
   public override void Withdraw (decimal amount) {
      if (amount < balance)
          balance -= amount;
      else
          throw new Exception("Cannot withdraw");
   }

   /// <summary>
   ///   Add the annual interest to the savings account.
   ///   This may increase the current balance of the account.
   /// </summary>
   public override void AddInterests() {
      balance = balance + balance * (decimal)interestRate 
                        - 100.0M;
   }    

   /// <summary>
   ///   Return a text string that represents this account
   ///   for output purposes
   /// </summary>
   public override string ToString() {
      return owner + "'s check account holds " +
            + balance + " kroner";
   }
}
Program 56.5    The class SavingsAccount.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
using System;

/// <summary> 
///   A specialization of BankAccount.
/// </summary>
public class LotteryAccount: BankAccount {

   private static Lottery lottery  = Lottery.Instance(20);

   /// <summary> Construct a lottery account based on 
   ///   owner o and the initial balance b </summary>
   /// <param name = "o"> The owner of the account </param>
   /// <param name = "b"> The initial balance of the account </param>
   public LotteryAccount(string o, decimal b): 
     base(o, b, 0.0) {
   }

   /// <summary> Add interest to the lottery account.
   ///    This may be a lot if a drawn lottery number is
   ///    the winning number. If not, zero interest is added.
   /// </summary>
   public override void AddInterests() {
      int luckyNumber = lottery.DrawLotteryNumber;
      balance = balance + lottery.AmountWon(luckyNumber);
   }    

   /// <summary>
   ///   Return a text string that represents this account
   ///   for output purposes
   /// </summary>
   public override string ToString() {
      return owner + "'s lottery account holds " +
            + balance + " kroner";
   }
}
Program 56.6    The class LotteryAccount.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
using System;

/// <summary> A class which assists LotteryAccount with the selection 
///           of lucky accounts. Encapsulates a secret winning number
///           and the amount won. A singleton class. </summary>
public class Lottery{

  private static Random rdm = new Random(unchecked((int)DateTime.Now.Ticks));

  private int difficulty;
  private readonly int winningNumber;
  private readonly decimal amountWon;
  private static Lottery uniqueInstance = null;

  private Lottery(int difficulty){
    this.difficulty = difficulty;
    this.winningNumber = rdm.Next(difficulty);
    this.amountWon = 500000.00M;
  }

  /// <summary> Returns the unique instance of this class</summary>
  /// <param name = "difficulty"> A measure of the difficulty of winning. </param>
  public static Lottery Instance(int difficulty){
    if (uniqueInstance == null)
      uniqueInstance = new Lottery(difficulty);
    return uniqueInstance;
  }

  /// <value>Draw and return a lottery number </value>
  public int DrawLotteryNumber{
    get {return rdm.Next(difficulty);}
  }

  /// <summary> Return if n is equal to the winning number </summary>
  public bool WinningNumber(int n){
    return n == winningNumber;
  }

  /// <summary> 
  ///   Return the encapsulated amount won if
  ///   luckyNumber is the winning number.
  /// </summary>
  /// <param name = "luckyNumber">Some integer number </param>
  public decimal AmountWon(int luckyNumber){
    decimal res;
    if (WinningNumber(luckyNumber))
       res = amountWon;
    else
       res = 0.0M;
    return res;
  }
}
Program 56.7    The singleton class Lottery - used by LotteryAccount.


Exercise 15.2. Documentation of class Set

In a previous exercise we have worked with the class Set<T>.

Write documentation for the operations insersection, union, and diff (set difference). If you have time and energy, also write documentation for other members.

Generate Doxygen documentation for the class.

You may also want to generate XML documentation for the class.

The natural starting point of this exercise is your own solution to the previous exercises. You can also chose to document my solution.

Solution


 

56.10.  Conclusion - Documentation of C# Programs
Contents   Up Previous Next   Slide Annotated slide Aggregated slides    Subject index Program index Exercise index 

  • XML Comments in C# programs

    • In principle a good idea

    • The XML documentation repertoire is not comprehensive

    • Voluminous

  • The generated XML documentation file

    • In principle a good idea

    • Should have been self-contained and complete

    • Should "automatically" be translated to good HTML documentation

Microsoft's C# documentation facilities are complicated to use, rudimentary, and of poor quality

Does not meet the standards of C# as such

Far away from the quality of Javadoc from Sun

Generated: Monday February 7, 2011, 12:24:12
Theme index -- Keyboard shortcut: 'u'  Previous theme in this lecture -- Keyboard shortcut: 'p'  Next slide in this lecture -- Keyboard shortcut: 'n'