Home > Mobile >  How to document a Builder with its methods using JavaDoc
How to document a Builder with its methods using JavaDoc

Time:07-25

I like to use the Builder pattern to instantiate objects of classes with complex states rather than using too many constructor arguments.

I can add a JavaDoc to the Class and each individual Method, but none of the JavaDoc keywords I know seems really fit to document the specificity of a builder, like what settings are mandatory, what are the defaults for optional settings.

If I document mandatory or optional and defaults for each individual method, it feels like the documentation is spread too much to get a global picture of it. Same if I document only the final build() method telling when it can build the instance with what defaults, and when it cannot.

None of these options seems really satisfying. It feels like JavaDoc does not fit so well with builder pattern but was designed for legacy Object Oriented code style; this or I don't understand it well enough.

I searched the https://www.oracle.com/technical-resources/articles/java/javadoc-tool.html documentation but could not find an answer or guidance for documenting a Builder with proper tags.

@param looked like a valid candidate to document all the setFoo, withBar, addBaz from a builder at one place like the Builder class itself, but it seems not appropriate for this kind of usage.

How to properly document a Builder in JavaDoc or some other more appropriate tool?

CodePudding user response:

Already your first assumption ("I can add a JavaDoc to the Class and each individual Method, […]") is wrong.

Documentation is still mandatory, and it should be done as closely to the source as possible. A JavaDoc comment is part of the source, so it cannot be closer!

People telling you that comments are an "anti-pattern" nowadays do not have a clue or are too lazy to type or both – and when you read the source for that "anti-pattern" crap, you will find that it talks about inline comments explaining what's happening in your code, but not about externalisable comments for documentation purposes – so not about JavaDoc or Doxygen comments (or how the respective tools are named in other languages).

To your question: a builder class will be documented like any other class as well, with the keywords provided by JavaDoc and proper descriptive text. If you are too lazy to add this text manually, you can write your own extension to JavaDoc and define your own keywords that will generate that text for you.

Or you create your own Annotation and refer to that in the main description. My sample below does both (annotation and descriptive text), to give you an idea what I am talking about (the definition for the annotation @IsMandatory is omitted).

But usually, a Builder will not have methods for mandatory attributes; instead these are the arguments for the Builder's constructor.

/**
 *  <p>{@summary Builder for new instances of
 *  {@link MyObject}.}</p>
 *  <p>Attributes whose setter methods are marked with the
 *  {@link IsMandatory &#64;IsMandatory}
 *  annotation are – obviously – mandatory. If not set when
 *  {@link #build()}
 *  is called, an
 *  {@link IllegalStateException}
 *  will be thrown.</p>
 *  <p>In particular, these are the attributes</p>
 *  <ul>
 *    <li>{@link #setName(String) name}</li>
 *    … 
 *  </ul>
 */  
public final class MyObjectBuilder
{
  /**
   *  Creates a new instance of {@code MyObjectBuilder}.
   */
  public MyObjectBuilder() {…}

  /**
   *  Creates a new instance of
   *  {@link MyObject}.
   *
   *  @return The new instance.
   *  @throws IllegalStateException A mandatory attribute was not set.
   */
   public final MyObject build() throws IllegalStateException {…}

  /**
   *  <p>{@summary Sets the name for the new instance of
   *  {@link MyObject}.} It can be any arbitrary string with more than
   *  one character that is not
   *  {@linkplain String#isBlank() blank}.</p>
   *  <p><b>Note:</b> This attribute is mandatory! If missing,
   *  {@link #build()}
   *  will throw an
   *  {@link IllegalStateException}.</p>
   *
   *  @param name The name for the new instance.
   *  @throws NullPointerException {@code name} is {@code null}.
   *  @throws IllegalArgumentException {@code name} is the empty string, or
   *      it is
   *      {@linkplain String#isBlank() blank}.
   */
  @IsMandatory
  public final void setName( final String name ) throws NullPointerException, IllegalArgumentException {…}

  /**
   *  Sets the other attribute for the new instance of
   *  {@link MyObject}.
   *
   *  @param other The other attribute.
   */
  public final void setOther( final Object other ) {…}
}

Have fun!

  • Related