Exercise index of this lecture   Alphabetic index   Course home   

Exercises and solutions
Documentation of Object-oriented Programs


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.


15.2   Give Doxygen a Try  

This exercise is guided tour in using Doxygen together with Visual C# 2008 Express. The exercise will help you set up the BankAccount documentation example, which we have seen on an earlier slide page in this lecture.

We will assume that you already have installed Doxygen and that you use Visual C# 2008 Express.

Start Visual C# 2008 Express. Use File > New Project... and make (at least in this exercise) a Class Library project.

Insert the BankAccount class in Visual C# 2008 Express in the usual way.

Do File > Save All. Notice the location of you project. On a piece of paper (or in a text editor) notice the full file path to your Visual C# 2008 project.

Start the Doxywizard program, which comes together with Doxygen.

In the Wizard > Project field: Give a name to your project. Just chose a suitable name.

In the Source Code Directory field, select the full path to the directory where Visual C# 2008 Express stores the source files. This is the directory in which Visual C# 2008 express stores the files with .cs file extension. You find this directory inside the Visual C# 2008 express project directory, which you captured earlier in this exercise. Relative to the way C# source programs are organized, it is usually not necessary to select Scan recursively.

In the Destination directory field select the directory in which you want to store the documentation which Doxygen generates. An existing directory of your choice.

In Wizard > Mode select the extraction mode. Try first documented entities only. It is recommended that you explicitly document the entries which appear in your documentation. Select the Java or C# programming language option.

In Wizard > Output select one of the HTML options (try first plain HTML). Deselect LaTeX.

In Doxygen, save the doxygen setup via File > Save or File > SaveAs.... This will make a file called Doxyfile. The Doxyfile contains all the settings of Doxygen. At another occasion, you can continue working on a particular batch of documentation by doing a File > Open... on the Doxyfile.

Now, in the Run tab, activate the button Run doxygen.

Use the button Show HTML output to look at the generated HTML documentation in your browser.

 

Notice that Doxygen is a very rich tool. Take a look at some of the Expert options in the DoxyWizard. There exists another note, written by a former student, Dan Jensen. You are encouraged read Dans note as your next step in getting familiar with Doxygen.


15.3   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

Here is the class with documentation comments:

using System;
using System.Collections.Generic;
using System.Collections;

/// <summary>
///  The generic class Set with elements of type T 
/// </summary>
//  <typeparam name = "T">The type of the elements of the set </typeparam>

public class Set<T> {
 
  /* Invariant: At most one occurrence of an element in the array store 
     Consequtive storing from low end.
  */

  private int capacity;
  private static int DefaultCapacity = 3;
  private T[] store;
  private int next;

///  <summary>
///    Construct a set with an initial capacity.
///    <param name="capacity">The initial capacity of the set </param>
///  </summary>
  public Set(int capacity){
    this.capacity = capacity;
    store = new T[capacity];
    next = 0;
  }

///  <summary>
///    Construct a set with DefaultCapacity.
///  </summary>
  public Set(): this(DefaultCapacity){
  }

///  <summary>
///    Construct a set with the initial elements from elements
///    <param name="elements">An array of T elements </param>
///  </summary>
  public Set(T[] elements): this(elements.Length){
    foreach(T el in elements) this.Insert(el);
  }

  // Copy constructor

///  <summary>
///    Construct a set with initial content copied from s.
///    A copy constructor
///    <param name="s">The set of initial elements </param>
///  </summary>
  public Set(Set<T> s): this(s.capacity){
    foreach(T el in s) this.Insert(el);
  }


///  <summary> Is element member of this set.
///    <param name="element"> An element in the type T </param>
///  </summary>
  public bool Member(T element){
    for(int idx = 0; idx < next; idx++)
      if (element.Equals(store[idx]))
        return true;
    return false;
  }

///  <summary> Insert element in this set if it is not already a member.
///    <param name="element"> An element in the type T </param>
///  </summary>
  public void Insert(T element){
    if (!this.Member(element)){
      if (this.Full){
        Console.WriteLine("[Resize to {0}]", capacity * 2);
        Array.Resize<T>(ref store, capacity * 2);
        capacity = capacity * 2;
      }
      store[next] = element;
      next++;
    }
  }

///  <summary> Delete an element from the set
///    <param name="element">The element to delete </param>
///  </summary>
  public void Delete(T element){
    bool found = false;
    int  foundIdx = 0;
    for(int idx = 0; !found && (idx < next); idx++){
      if (element.Equals(store[idx])){
         found = true;
         foundIdx = idx;
      }
    }
    if (found){   // shift remaining elements left
      for(int idx = foundIdx+1; idx < next; idx++)
        store[idx-1] = store[idx];
      store[next-1] = default(T);
      next--;
    }
  }

///  <value> The number of elements in the set </value>
  public int Count{
    get{
      return next;
    }
  }

///  <summary> Is other a subset of this set.
///    <param name="other">A set of T elements </param>
///  </summary>
  // Is this set a subset of other
  public bool Subset(Set<T> other){
    foreach(T e in this)
      if (!other.Member(e))
         return false;
    return true;
  }
     
///  <summary> Return the set of elements which are both member of this set and other
///    <param name="other">A set of T elements </param>
///  </summary>
/// <seealso cref="Union(Set<T>)">
  public Set<T> Intersection(Set<T> other){
    Set<T> res = new Set<T>(this.Count);
    foreach(T e in this)
      if (other.Member(e))
          res.Insert(e);
    return res;
  }

///  <summary> Return the set of elements which are member of this or other. 
///    <param name="other">A set of T elements </param>
///  </summary>
/// <seealso cref="Intersection(Set<T>)">
  public Set<T> Union(Set<T> other){
    Set<T> res = new Set<T>(this.Count + other.Count);
    foreach(T e in this) res.Insert(e);
    foreach(T e in other) res.Insert(e);
    return res;
  }

///  <summary> Return the set of elements in this set which does not belong to other
///    <param name="other">A set of T elements </param>
///  </summary>
  public Set<T> Diff(Set<T> other){
    Set<T> res = new Set<T>(this);
    foreach(T e in other) res.Delete(e);
    return res;
  }

///  <summary> Return a string that represents this set.
///  </summary>
  public override string ToString(){
    string elRes = "";
    for(int idx = 0; idx < next; idx++) 
      if (store[idx] != null)
        elRes += " " + store[idx];
    return "{" + elRes + " "+ "}" + this.Count;
  }
  
  private class SetEnumerator: IEnumerator<T>{
 
    private readonly Set<T> set; 
    private int idx;

    public SetEnumerator (Set<T> s){
      this.set = s;
      idx = -1;   // position enumerator outside range
    }
 
    public T Current{ 
      get {
       return set.store[idx];
      }
    }

    Object IEnumerator.Current{ 
      get {
       return set.store[idx];
      }
    }

    public bool MoveNext(){
      if (idx < set.next - 1){
        idx++; 
        return true;
      }
      else
         return false;
    }

    public void Reset(){
      idx = -1;         
    }

    public void Dispose(){
    }

  }    

///  <summary> Return an enumerator of this set.
///  </summary>    
  public IEnumerator<T> GetEnumerator (){
    return new SetEnumerator(this);
  }

  private bool Full{
    get{
      return next == capacity;
    }
  }

}

The generated documentation is also available.


Generated: Monday February 7, 2011, 12:24:06