Introducing Design Intention Driven Programming and Java with Intentions

Version 1.1

Copyright © 2010, Kevin Matz. This material is part of a forthcoming MSc thesis and shall not be reproduced without written permission of the author.




In team-based software development, and especially in the maintenance of legacy software systems, developers spend much of their time on the activity of program comprehension.

In order to make a change or an enhancement to an existing system, a developer must first understand the code to be modified. It can be very time-consuming to read and analyze complex code artefacts to understand what they do and how they work, and to determine how to modify them. A developer reading someone else's code must try to piece together the intentions of the original author -- that is, what the author had in mind when writing the code.

If the code has been written carefully, by using good naming of identifiers (variables, methods, and classes), by employing a clear logical structure, and by using commonly-known design patterns, later developers can often figure out what the code does and how it works. Due to time pressure, inexperience, or other factors, however, many systems were not constructed using "best practices", and even in "good" systems, the code quality and structure of the system have often deteriorated over time due to countless changes and quick fixes made by many developers. And often code is extremely complex to understand, simply because it is doing some very complex things.

In the absence of suitable documentation, a developer making changes to existing code that he or she is not familiar with must typically do time-consuming analyses, formulating and testing hypotheses about what is going on. Under deadline pressure, a developer may have to make assumptions and carry out changes based on an incomplete understanding of the code being modified, which often leads to further errors and defects that must be corrected again at a later date.

Obviously, developers can give clues and insights to future developers by writing comments that explain what the code does, how it works, and why it was designed that way. Comments could even contain hints about how to make future expected changes.

In many legacy systems, however, comments are non-existent or are of poor quality. And external documentation such as functional specifications, technical design documentation, or data dictionaries, that might provide additional clues, can become lost or out of date.

When we build new systems that will be maintained over long periods of time, is there any approach we can take to help reduce the burdens of program comprehension and missing documentation?


Introducing Design Intention Driven Programming

Design Intention Driven Programming (DIDP) is an approach which encourages developers to record their design intentions before they write a piece of code. Developers record their design intentions for a component of a system simply by writing a brief description of what they plan for that component to do, and how it will do it. The description may also include rationale -- a justification of why one particular solution was chosen over alternative solutions.

In the DIDP approach, a system is written using a programming language that has been extended with special language constructs called intention comments that aid in the recording of design intentions. For example, if you are constructing a system based on Java, you would use a language called Java with Intentions that extends the Java language syntax with support for intention comments.

In DIDP, before you write a new class, a new method, or a section of code within a method, you should write an intention comment for it, briefly explaining what you plan to do and how the code will work. When you then write the corresponding code, if you have to diverge from your plan, you should then update the intention comment to match the implementation.

Now you're probably asking, why can't we just use normal comments to do this?

Well, of course, you certainly could. Intention comments are very much like existing comments in programming languages -- they store free-form textual explanations -- but they have several unique features:

  • Intention comments encourage documentation re-use and help prevent duplication, because they are object-oriented constructs that support the inheritance mechanism. Intention comments can have fields containing either text or references to classes, objects, or other intention comments. An intention comment can be abstract, serving as a template, and other intention comments can extend it and fill in the required fields. This is a particularly suitable way of documenting instances of design patterns, as we will see shortly.

  • Because intention comments can be named and can refer to each other, and because intention comments representing requirements and goals can be created, interlinked networks of intention comments can be used to represent a design for the system at different levels of abstraction.

  • Intention comments can be made mandatory, to enforce the documentation of the code. The compiler enforces that intention comments are present by generating an error message if a class or method or a long section of code within a method does not have a corresponding intention comment associated with it.

    To prevent a programmer from just entering an empty or short gibberish comment to satisfy the compiler, it is envisioned that the compiler will compute a numeric information content metric for the intention comment, and a numeric complexity metric for the code that the intention comment describes. (The simplest metrics are simple counts of characters or lines, but more complex schemes are possible.) If the compiler determines that the information content of the comment is not enough to match the corresponding code (for example, a comment containing just five characters would be considered insufficient to describe a class containing a thousand lines of code), a compiler error will be generated. The metrics and thresholds could be configured for each project. Obviously, this scheme is imperfect and would be easy to circumvent, and cannot guarantee the quality of the comment text, but it is an attempt to "enforce" commenting. (The DIDP approach is obviously not suitable for all projects and teams, but it is suitable as an aid that could be adopted by project teams that value documentation and wish to ensure a certain standard of commenting.)

As this discussion has been very abstract, let's now briefly see what intention comments actually look like in the Java with Intentions language.


Introducing Java with Intentions

The Java with Intentions language (JWI) simply takes the existing Java programming language and adds support for intention comments. In JWI, intention comments have two basic forms:

  1. Free-standing
  2. Inline

Free-standing intention comments

Free-standing intention comments sit inside of Java source code files, but outside of classes, or within classes but outside of methods. A class or method can be linked to a free-standing intention comment by referring to its name. For example:

File Flashcard.java

package vocabularytrainer;

intention FlashcardIntention {
    description {
        To represent a flashcard for learning foreign-language vocabulary,
        with a cue (on one side of the card) and a list of one or more
        acceptable answers (on the other side of the card).
    }
}

class Flashcard implementsintention FlashcardIntention {
    ...
}

This explains that the intention of the Flashcard class is to represent a flashcard in a vocabulary-training application.

At this point, intention comments don't appear to have any advantage over writing plain comments, or writing comments with Javadoc. However, if you were to compile Flashcard.java using the JWI compiler, and class Flashcard did not declare that it was an implementation of any intention, of if the compiler judged that the information content of the comment was insufficient, then the compiler would refuse to compile the code.

To demonstrate the object-oriented features of JWI, let's now use intention comments to document an instance of the Model-View-Controller pattern. First, we will create an abstract intention comment to represent the MVC pattern in general:

File ModelViewControllerIntention.java

package vocabularytrainer.abstractintentions;

abstract intention ModelViewControllerIntention {
    description {
        To implement the Model-View-Controller pattern, in order to
        structure the user interface code into separate components.
        This separation of concerns helps improve understandability
        and modifiability.
        
        The model consists of a representation of the application's data.
        The model notifies listeners (typically, one or more view
        components) when the data changes.
        
        The view component presents the data to the user in the form of
        UI components. Multiple views based on the same model may exist.
        
        The controller acts upon input from the user and updates the
        model and/or interacts with the view.
    }

    classreference[] modelClasses;
    classreference[] viewClasses;
    classreference controllerClass;
}

Then we can describe a specific instance or application of the MVC pattern by declaring an intention comment that extends this abstract intention. In the new intention comment, we fill in the required fields (in this case, references to classes):

File VocabularyTrainerMVCIntention.java

package vocabularytrainer.intentions;

intention VocabularyTrainerMVCIntention extends ModelViewControllerIntention {
    description {
        To implement the vocabulary trainer user interface according to the 
        Model-View-Controller pattern.
    }
    
    modelClasses = { QuizState, Flashcard, FlashcardList };
    viewClasses = { QuizFrame };
    controllerClass = QuizController;
}

The classes that take part in this pattern can then link themselves to the intention for the pattern instance. For example:


class QuizController implementsintention VocabularyTrainerMVCIntention {
    ...
}

Now, when new developers join this project and encounter any class that is a part of this pattern instance, they will be able to read the comments and follow the links to locate the other components of the pattern and understand their relationships.


Inline intention comments

Within a method, lengthy blocks of code without any descriptive comments will be flagged by the JWI compiler. To associate comment texts with blocks of code, we need a syntax for "inline intention comments" that includes start and end tags that can surround blocks of code. This additionally allows inline intention comments to be nested, allowing each step of an algorithm to be broken into smaller sub-steps.

The following example illustrates the syntax in JWI:


[[ 1 | Shuffle the deck of flashcards (flashcardList) by iterating
       through the list and swapping the card at the current position
       with another randomly-chosen card ]]
for (int i = 0; i < flashcardList.size(); i++) {

    [[ 1.1 | Generate a random number, which will serve as the index
             of the card to be swapped with the current index ]]
    int otherIndex = randomGenerator.nextInt(flashcardList.size());
    [[ /1.1 ]]

    [[ 1.2 | Swap the records at indices i and otherIndex ]]
    Flashcard tempCard = (Flashcard) flashcardList.get(i);
    flashcardList.set(i, flashcardList.get(otherIndex));
    flashcardList.set(otherIndex, tempCard);
    [[ /1.2 ]]
}
[[ /1 ]]

"Opening" comment tags take the syntax [[ commentIdentifier | descriptionText ]] (where the square brackets and vertical bar are literal characters). The comment identifiers could be virtually any names, but in this example they follow a hierarchical numbering scheme.

"Closing" comment tags use a slash in front of the comment identifier, similar to XML.


Summary

By elevating comments to be "first-class citizens" of programming languages, Design Intention Driven Programming and Java with Intentions attempt to reduce the long-term burden of program comprehension by encouraging (and forcing) programmers to record their design intentions in the code, so that present and future maintainers can spend less time reading and reverse-engineering code.

It is not a perfect scheme, and it is not suitable for all projects and teams. Many developers would be very resistant to any attempt to force them to write comments, so the approach is suitable only for project teams where an agreement has been reached on the value of comments. However, for those who wish to document their systems, it could be a useful tool. ∎




How to contact the author
Author's homepage