19 December 2008

Is Javadoc killing program evolution?

Hello!


When I found what Javadoc was, I was totally impressed. The way that it made code more readable was increadible for me. So it didn't take too much time until I used to comment each class, method and parameter. I did that in one project and was satisfied with results. However, in the second one I found a problem that improving Javadoc after rebuilding some parts of code took even 3x more time and efford than it should have. That's why nowadays, I'm used to providing comments as little as possible. This doesn't mean that I avoid using Javadoc. I just try to make it as brief as possible, omitting as much as I can without harming a project.

What is the reason?

  • Let's use a standard library java.util.Arrays as an example in which each comment is repeated 1~8+ times with immortal [CTRL +C] [CTRL +V].
  • In code I use approximately 30% of my classes, 30% of base types & classes, 30% of generic classes. For those generics there's also no dedicated tag to describe parameter type for generic. What's more, if I declare generic, there is no way to make a nice description for it as well (this include simple arrays too).

What do we lose?

  • Each time when we make some changes, we need to search for all comments and fix them.
  • Even if all code works fine and we want only to improve documentation, we need to search all places where documentation is pleased.
  • If we use generics, we need to search the way to describe it clearly and we also should have a hope that someone reading it will understand comments in the same (our) way.

What do I expect?

  • Javadoc support for convention. I want to be able to define one describe for parameter, method, variable, ... and reuse it.
  • Reusing docs from implemented interfaces (classes).
  • Being able to describe generic once I define and use them.
  • Being able to call direct parameters(safe for refactor).
  • Support for multi-language comments

What would that give to me?

  • Evolution Javadoc in the same speed as code.
  • Improvement in usage. It would direct people to use the same names for the same aims.

Sample:


/**
 * ...
 * @paramconv element element that will be proceed
 * @methodconv addFromCollection add all elements from given container
 * @gen Unit component for this class ...
 * @author Marek Kozieł
 */

public abstract class DocSample<Unit> implements List<Unit> {

  /**
   * ...
   */

  class Entry<K, V> {
    
  }

  /**
   * @gen ArrayList#1 pair key and value
   * @get ArrayList#1#K Key for list of units
   * @gen ArrayList#1#V List of units
   * @get ArrayList#1#2#1 unit ...
   */

  ArrayList<Entry<String, List<Unit>>>  list;

  /**
   * @methodinherit
   * {@link #add(Object)#index} index at which to insert the first element from the specified collection
   * @paraminherit index
   * @param element
   */

  @Override
  public void add(int index, Unit element) {
    // TODO Auto-generated method stub
  }

  /**
   * @methodconv
   * @param iterator ...
   */

  public int addFromCollection(Iterator<? extends Unit> iterator) {
    int count = 0;
    while (iterator.hasNext()) {
      count += (add(iterator.next())?1:0);
    }
    return count;
  }

  /**
   * @methodconv
   * @param iterable ...
   */

  public int addFromCollection(Iterable<? extends Unit> iterable) {
    return addFromCollection(iterable.iterator());
  }

  /**
   * @methodconv
   * @param array ...
   */

  public <EUnit extends Unit> int addFromCollection(EUnit[] array) {
    int count = 0;
    for (EUnit eUnit : array) {
      count += (add(eUnit)?1:0);
    }
    return count;
  }

  /**
   * ...
   * @paramconv element
   */

  abstract public boolean add(Unit element);

  /**
   * ...
   * @paramconv element
   */

  abstract public int remove(Unit element);

}

Meaning:

@gen : represent generic parameter
@paramconv : get describe from same name @paramconv from class comment.
@methodconv : get describe from same name @methodconv from class comment.
@methodinherit : get describe from implemented Interface / Class from override method
@methodinherit(Interface/Class) : get describe from given implemented Interface / Class from override method

@paraminherit index ...
@paraminherit(Interface/Class) index ..

For
ArrayList<Entry<String, List<Unit>>> list;
describe would look like:

ArrayList< ... > :
-Entry< ... , ... > : pair key and value
--String : Key for list of units
--List< ... > : List of units
---Unit : unit ...

3 comments:

  1. Yes, I agree. I have even worse - we have enabled Checkstyle for each module, and it warns if no comments are found, so I need to copy&paste.
    I think we don't need all things you suggested here. Something like variables would be better:
    @var myVariable sometext
    And then you'd use it: {$myVariable}

    During refactoring is even worse. Your documentation will become outdated after a few refactorings. Then only one solution is right: - write long, meaningful class and method names (like doThisAndThat)
    - write comments only if you need to add some extra information to method/class names

    About localization of Javadocs: a good programmer needs to know English, because most Internet resources and good books aren't translated into native languages. So IMO Javadoc translation isn't needed.

    About Javadoc inheritance - you can write:
    {@inheritDoc}, but it applies only for whole comments, not for parts of it.

    ReplyDelete
  2. I'm very interesting your suggestion about Java docs, but in current form Lasu Java docs isn't convenient for me.

    Why I don't agree to your proposal:
    - some annotation is redundant
    - i think making this Java docs get more time than coding
    - code have elements like:
    /** this variable have current number of loop */
    private Integer iterator
    where comment is pointless. No comments is wrong but too much comment is the same.

    In the end I'm very pleased with Some one interesting comments in our code.

    I've been expecting Lasu Java docs in version 1.1

    ReplyDelete
  3. It's nice to hear that JavaDoc is under refreshing:
    Project Coin: Small Language Change Proposal Form Available

    And you can comment generics with:
    @param < ComponentType > desc...

    Thanks to Joe for informations ;)

    ReplyDelete