Documentation and Documentation Generators

Steven J Zeil

Last modified: Nov 20, 2013

Contents:
1. Source Code Documentation
1.1 Comments
1.2 Charting
2. API Documentation
2.1 javadoc
2.2 doxygen
2.3 Other API Documentation Generators
3. Project Reports
3.1 Test Reports
3.2 Static Code Analyzers
3.3 Configuration Reports
4. Project Websites
4.1 Publishing to a website
4.2 Forges

… because everyone loves writing documentation.

1. Source Code Documentation

1.1 Comments

Do Comments Matter?

McConnell has a good & balanced discussion on this.

Modern focus has shifted considerably away from commenting bodies towards API documentation.

Which is better?

double m; // mean average
double s; // standard deviation

double meanAverage
double standardDeviation

Which is better?

// Sum up the data
double sum = 0.0;
double sumSquares = 0.0;
// Add up the sums
for (double d: scores)
{
   sum += d;
   sumSquares += d*d;
}

// Compute the average and standard
//  deviation
double meanAverage = sum / numScores;
double standardDeviation =
   sqrt ((sumSquares - numScores*sum*sum)
            /(numScores - 1.0));

// Subtract the average from each data
// item and divide by the standard
// deviation.
for (int i = 0; i < numScores; ++i)
{
   scores[i] = (scores[i] - meanAverage)
       / standardDeviation;
}

// Compute summary statistics
double sum = 0.0;
double sumSquares = 0.0;

for (double d: scores)
{
   sum += d;
   sumSquares += d*d;
}

double meanAverage = sum / numScores;
double standardDeviation =
   sqrt ((sumSquares - numScores*sum*sum)
            / (numScores - 1.0));

// Normalize the scores
for (int i = 0; i < numScores; ++i)
{
   scores[i] = (scores[i] - meanAverage)
       / standardDeviation;
}

Which is better?

// Compute summary statistics
double sum = 0.0;
double sumSquares = 0.0;

for (double d: scores)
{
   sum += d;
   sumSquares += d*d;
}

double meanAverage = sum / numScores;
double standardDeviation =
   sqrt ((sumSquares - numScores*sum*sum)
            /(numScores - 1.0));

// Normalize the scores
for (int i = 0; i < numScores; ++i)
   scores[i] = (scores[i] - meanAverage)
       / standardDeviation;

void computeSummaryStatistics (
   const double* scores,      // inputs
   int numScores,
   double& meanAverage,       // outputs
   double& standardDeviation)
{
  double sum = 0.0;
  double sumSquares = 0.0;
  for (double d: scores)
  {
     sum += d;
     sumSquares += d*d;
  }

  meanAverage = sum / numScores;
  standardDeviation =
     sqrt ((sumSquares - numScores*sum*sum)
              /(numScores - 1.0));
}


void normalizeData (double* data,
                    int numData,
                    double center,
                    double spread)
{
  for (int i = 0; i < numData; ++i)
    data[i] = (data[i] - center) / spread;
}

    ⋮

double meanAverage;
double standardDeviation;
computeSummaryStatistics (scores, numScores,
    meanAverage, standardDeviation);
normalizeData (scores, numScores,
    meanAverage, standardDeviation);

Which is better?

void computeSummaryStatistics (
   const double* scores,      // inputs
   int numScores,
   double& meanAverage,       // outputs
   double& standardDeviation)
{
  double sum = 0.0;
  double sumSquares = 0.0;

  for (double d: scores)
  {
     sum += d;
     sumSquares += d*d;
  }

  meanAverage = sum / numScores;
  standardDeviation =
     sqrt ((sumSquares - numScores*sum*sum)
              /(numScores - 1.0));
}


void normalizeData (double* data,
                    int numData,
                    double center,
                    double spread)
{
  for (int i = 0; i < numData; ++i)
     data[i] = (data[i] - center) / spread;
}
    ⋮

double meanAverage;
double standardDeviation;
computeSummaryStatistics (scores, numScores,
    meanAverage, standardDeviation);
normalizeData (scores, numScores,
    meanAverage, standardDeviation);

void computeSummaryStatistics (
   const double* scores,      // inputs
   int numScores,
   double& meanAverage,       // outputs
   double& standardDeviation)
{
  double sum = accumulate(
     scores, scores+numScores);
  double sumSquares = accumulate(
     scores, scores+numScores,
     [](double x, double y)
       {return x + y*y;});

  meanAverage = sum / numScores;
  standardDeviation =
     sqrt ((sumSquares - numScores*sum*sum)
              /(numScores - 1.0));
}


    ⋮

// Normalize the scores
double meanAverage;
double standardDeviation;
computeSummaryStatistics (scores, numScores,
    meanAverage, standardDeviation);
transform (
    scores, scores+numScores,
    scores,
    [] (double d) {
      return (d - meanAverage)
               / standardDeviation});

1.2 Charting

How many forms of software documentation charting do you know?

From Code to Charts

From Charts to Code

A hallmark of so-called CASE (Computer-Aided Software Engineering) systems

2. API Documentation

API documentation tools are now more common

2.1 javadoc

Perhaps the best known tool in this category

Javadoc Comments

SegmentationTransformer.java
/**
 * 
 */
package edu.odu.cs.extract.control;

import org.jdom.Document;

import edu.odu.cs.extract.dataflow.Dataflow;
import edu.odu.cs.extract.dataflow.QuickTransformer;
import edu.odu.cs.extract.dataflow.TransformationResult;
import edu.odu.cs.extract.inputprocessing.segmentation.Segmentation;
import edu.odu.cs.extract.utils.Properties;

/**
 * Transforms a PDF file dataflow into Raw IDM by attempting a direct translation
 * of text PDF, but passing pages thought to be scanned on for OCR and thenby trimming to a selected number of pages
 * OCR-to-rawIDM conversion.
 * 
 * @author zeil
 *
 */
public class SegmentationTransformer extends QuickTransformer {

    
    /**
     * 
     */
    public SegmentationTransformer() {
        super();
    }

    /* (non-Javadoc)
     * @see edu.odu.cs.extract.dataflow.ThreadedTransformer#doTransform(edu.odu.cs.extract.dataflow.Dataflow[])
     */
    @Override
    public TransformationResult doTransform(Dataflow[] in) throws Exception {
        String status = "success";
        String message = "OK";

        IDMDataflow inputDF = (IDMDataflow) in[0];
        Document unsegmentedIDM = inputDF.getDocument();
        String mergeFailed = unsegmentedIDM.getRootElement().getAttributeValue("OCRmerge");
        
        if (mergeFailed != null && "failed".equals(mergeFailed)) {
            status = "warning";
            message = "unable to merge pages from OCR";
        }
        
        // Segment document
        Document segmentedIDM = new Segmentation(unsegmentedIDM).reSegment();

        IDMDataflow outputDF = new IDMDataflow (in[0].getTrace(), segmentedIDM);
        
        return new TransformationResult(outputDF,status, message, null);
    }

    @Override
    public String getOutputExtension() {
        Properties p = Properties.getProperties();
        return p.getProperty(Properties.Names.SEGMENTATION_OUT_EXT);
    }

        

}

.


Common Javadoc Markup


Running javadoc

<javadoc packagenames="edu.odu.cs.*" 
         destdir="target/javadoc" 
         classpathref="javadoc.classpath" Author="yes" 
         Version="yes" Use="yes" defaultexcludes="yes">
   <fileset dir="." defaultexcludes="yes">
      <include name="extractor/src/main/java/**" />
      <include name="generatedSource/gen-src/**" />
      <exclude name="**/*.html" />
   </fileset>
   <doctitle><![CDATA[<h1>ODU CS Extract
                    Project</h1>]]></doctitle>
</javadoc>

2.2 doxygen


Running doxygen

2.3 Other API Documentation Generators

Because a documentation generator needs to module and function structure and function parameters, a distinct parser is needed for each programming language.

This leads to a variety of language-specific tools, e.g.,

3. Project Reports

3.1 Test Reports

We’ve already looked JUnit, which can be used to generate test reports like this one.

This is generated in ant via the junitreport task:

junitreport.xml.listing
<project name="code2html" basedir="." default="build">

  <record name="ant.log" action="start" append="false" />

  <taskdef classpath="JFlex.jar" classname="JFlex.anttask.JFlexTask" name="jflex" />
    
  <echo>loading build-${os.name}.paths</echo>
  <include file="build-${os.name}.paths"/>
    

  <target name="generateSource">
    <mkdir dir="src/main/java"/>
    <jflex file="src/main/jflex/code2html.flex"
       destdir="src/main/java"/>
    <jflex file="src/main/jflex/code2tex.flex"
           destdir="src/main/java"/>
    <jflex file="src/main/jflex/list2html.flex"
       destdir="src/main/java"/>
    <jflex file="src/main/jflex/list2tex.flex"
           destdir="src/main/java"/>
  </target>
  

  <target name="compile" depends="generateSource">
    <mkdir dir="target/classes"/>
    <javac srcdir="src/main/java" destdir="target/classes"
       source="1.6" includeantruntime="false"/>
  </target>

  <target name="compile-tests" depends="compile">
    <mkdir dir="target/test-classes"/>
    <javac srcdir="src/test/java" destdir="target/test-classes"
       source="1.6" includeantruntime="false">
      <classpath refid="testCompilationPath"/>
    </javac>
  </target>

  <target name="test" depends="compile-tests">
    <property name="mypath" refid="testExecutionPath"/>
    <echo>testExecutioPath is ${mypath}</echo>
    <echoproperties/>
    <mkdir dir="target/test-results/details"/>
    <junit printsummary="yes" 
       haltonfailure="yes" fork="no"
       >
        <classpath refid="testExecutionPath"/>
      <formatter type="xml"/>
      <batchtest todir="target/test-results/details">
         <fileset dir="target/test-classes">
            <include name="**/*Test*.class"/>
         </fileset>
      </batchtest>
    </junit>
    <junitreport todir="target/test-results">
      <fileset dir="target/test-results/details">
        <include name="TEST-*.xml"/>
      </fileset>
      <report format="frames" todir="target/test-results/html"/>
    </junitreport>
  </target>

  <target name="build"  depends="test">
    <jar destfile="codeAnnotation.jar" basedir="target/classes">
        <manifest>
            <attribute name="Main-Class"
                       value="edu.odu.cs.code2html.Code2HTML"/>
        </manifest>
    </jar>
  </target>

  <target name="clean">
    <delete dir="target"/>
  </target>

  
</project>

Other common test reports

3.2 Static Code Analyzers

Many tools that we will cover later for analyzing code can produce useful (or at least, impressive) documentation as a side effect.

3.3 Configuration Reports

Configuration managers (to be covered later) generate reports about the dependencies among the software components.

Examples:

4. Project Websites

4.1 Publishing to a website

You can also add instructions to your build manager to post files to a website.


Posting to a website

4.2 Forges

A software forge is a collection of web services for the support of collaborative software devlopment:


Forge Examples

Among the best known forges are

The CS 350 course has its own forge