Commenting Code

Bad Advice

I’ve encountered a lot of bad advice about commenting code over the decades.  I’ve known developers who insisted that commented code is actually worse than uncommented code because the comments will always be wrong or out-of-date.  But even dated comments give a clue about the original intentions of the code and how subsequent changes might have gone wrong.

I’ve seen style guides that recommend a one line comment above every paragraph of code. Mindlessly adding short comments every few lines ends up with obvious statements like “add one to index” that don’t actually provide any useful information.  Back in the 70s or 80s when hand coding assembly language was still a thing, such comments were bread and butter of the profession.  But modern high level languages are usually self-documenting in that regard.

Self-Documenting Code

Self-documenting code has all the sound and feeling of moral superiority.  But, like Communism’s “from each according to their ability, to each according to their need” which sounds all noble and just, in the real world it just doesn’t work.  This is often for the same reason: some people are just evil, and many more are just plain lazy.

But it also doesn’t work because programming languages are not intrinsically expressive enough to self-document more complex ideas.  More often than developers realize (because developers are too close to the problem and make assumptions about what a later developer will intuitively understand), the problem being solved is complex, with much jargon, hidden assumptions, and irreducibly complex algorithms being necessary to solve it.

A further issue is the fact that well-done comments serve more purposes than explaining what a bit of code does.  So leaving the political analogy snark above behind, I introduce another analogy to explain the many purposes of comments.

The Book Analogy

Let’s consider the text of a book as an analogy to the text of a program.  A well written book can be read from cover to cover without the aid of typographical conventions and be understood.  Consider the popularity of books-on-tape as proof of this idea.  The text of the book is effectively self-documenting.

But now let’s look at a couple of pages of a real book.  (Wallace, Daniel B. Greek Grammar Beyond the Basics.  Zondervan, 1996.)

We see many features that are not part of the text itself, but which aid the reader in navigating and understanding the text:

  • Titles
  • Headings
  • Subheadings…
  • Overviews
  • Bibliography
  • Footnotes
  • etc.

All these have useful counterparts in commenting code to make the easier to navigate and understand.

Titles, Headings, and Subheadings…

A hierarchy of titles and headings make navigating a book (and code) easier.  In a book they are usually set off by size, and often weight or font selection as well.  We don’t have such typographical conventions available in development environments.  Instead a construct called “block comments” have traditionally been used instead.

/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
////                                                         ////
//// MyPojo                                                  ////
////                                                         ////
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////

public class MyPojo {

    /////////////////////////////////////////////////////////////
    //                                                         //
    // CONSTRUCTORS                                            //
    //                                                         //
    /////////////////////////////////////////////////////////////

    public MyPojo() {
        …
    }

    public MyPojo(MyPojo source) {
        …
    }

    /////////////////////////////////////////////////////////////
    //                                                         //
    // PROPERTIES                                              //
    //                                                         //
    /////////////////////////////////////////////////////////////

    /////////////////////////////////////////////////////////////
    // primaryKey                                              //
    /////////////////////////////////////////////////////////////

    private String primaryKey;

    public String getPrimaryKey() {
        return primaryKey;
    }

    private String setPrimaryKey(String primaryKey) {
        this.primaryKey = primaryKey;
    }

    ///////////////////////////////////////////////////////////
    // widgetName                                            //
    ///////////////////////////////////////////////////////////

    private String widgetName;

    …

    ///////////////////////////////////////////////////////////
    //                                                       //
    // BUILDER                                               //
    //                                                       //
    ///////////////////////////////////////////////////////////

    public class Builder {

        ///////////////////////////////////////////////////////
        // Constructors                                      //
        ///////////////////////////////////////////////////////

        MyPojo template;

        public Builder() {
            …
        }

        …

        //////////////////////////////////////////////////////
        // Initializers                                     //
        //////////////////////////////////////////////////////

        public Builder primaryKey(String primaryKey) {
            template.setPrimaryKey(primaryKey);
            return this;
        }

        public Builder widgetName(String widgetName) {
            …
        }
    }
}

Headings in code can be given different font sizes and weights virtually by using heavier or lighter boxes around the heading text and by using all capitals, mixed case, or all lowercase text.

Creating headers this way has several advantages:

Style guides recommend grouping related constructs together, such as constructors, properties, inner classes, etc.  By exposing the structure imposed by these guidelines in such a hard-to-miss fashion, future developers are less likely to place constructs in the wrong place.  Experience shows that without such headings, groupings of constructs inevitably break down as the code is further processed.

The typographical conventions are what they are because several centuries worth of experience has discovered that these conventions cooperate with the way the brain works.  By being able to pick out the higher level structure of the text (or code) prior to actually reading it, the mind is prepared to more quickly learn what the text has to say (or what the code does).  Headings speed up the learning curve.

Readily visible visual markers make it easier for even the readers who are most intimately familiar with the text (or code) to quickly navigate from place to place.  The visual shape of the different headings becomes a map in the reader’s brain.  They are the mile posts that the reader will remember  where specific passages are located relative to.

Overviews

Many developers like to gather the declarations of backing-store variables ahead of all the getters and setters to serve as a makeshift Overview section.  This is problematic for three reasons.  First, breaking up of the implementation of a property into two places makes the code harder to follow or modify.  But more importantly (and second), it frequently doesn’t serve as an adequate summary because (with some regularity) there is not always a one-to-one correspondence between backing-store variables and properties.  Finally, third, there is frequently more than just properties that can benefit from an Overview.

My preference generally is to add an overview to the title box for the class, giving a quick list of constructors, properties, inner classes, methods, etc.

/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
////                                                         ////
//// MyPojo                                                  ////
////                                                         ////
//// Constructors:                                           ////
////     MyPojo()                                            ////
////     MyPojo(MyPojo source)                               ////
//// Properties:                                             ////
////     primaryKey                                          ////
////     widgetName                                          ////
//// Inner Classes:                                          ////
////     Builder                                             ////
////                                                         ////
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////

An alternative would be to put the overview in a Javadoc comment on the class.  But generally IDEs already provide this information in name completion and the tags needed within the Javadoc for semantic annotation and formatting are hardly human readable.  The Overview is for the human reader of the source code to get a high level view of what the class contains, not for the IDE to read and generate separate documentation.

Bibliography

Any well written code most probably has design documents that may or may not be part of the source code itself.  That is, they may be held in a repository of Word documents such as One Drive or in a Wiki.  Where documentation is not held in the source file itself, the source file should contain citations of those documents.

Code that is more scientific in nature will often be based on published algorithms.  Citations to these documents should also be included in the source to aid future developers.

There are numerous styles of bibliographic citations.  Which one to use is not particular important.  But it is important for intranet or internet citations to include more than just a URL as URLs have an unfortunate tendency to become stale.  When citing a URL, include the date that the URL was valid.  This will aid in finding it in an internet archive site.  But also include standard bibliographic information such as author, title, publisher, and date of publication like would be done for any paper resource as these will aid in finding the resource again after the URL has become stale.

When citing a particular location within a document, don’t just cite the page number, as a future developer may be accessing an online version of the document.  Cite the section heading and possibly multiple levels of section headings, as this will help the future developer find the intended location in documents stripped of page number information.

Citations that cover the whole source file can be placed in the title box along with the overview.  Otherwise that may be attached in regular comments.  See “Footnotes” below.

Footnotes

The way that comments are most often thought of, as a short remark explaining what a small piece of code does, most closely correspond to footnotes in book typography.  There are, however, many functions that may be served by these footnotes.

Javadoc comments (or the equivalent in other program languages and development environments) serve as documentation for individual classes, methods, properties, and variables.  They often have semantic or formatting annotations within for generating printed documentation or documentation within integrated development environments, and so aren’t necessarily extremely human readable.

Just like the Bibliography section above, it is often useful to provide cross references to other documents, or even other code within the project, on smaller pieces of code.  This is analogous to what is probably the most common form a footnote in books: citing sources.

Summarizing what a paragraph of code does is often useful.  But caution must be exercised to not go overboard.  Writing a comment that says “Add one to index” is not very useful, whereas “collect sums needed for calculation of average and standard deviation” probably is.

More often than not, the summarizing comment will actually provide a rationale for the code.  For example, where a comment saying “Add two to index” isn’t useful, a comment that says “Process array elements in even-odd pairs” on an increment by two probably is useful because it explains why we are incrementing by two.

Self-Documenting Code Redux

I’ve seen style guides that champion self-documenting code that would argue that the right way to document the “even-odd pairs” processing in the above example would be to refactor the code to have a processEvenOddPair() method.  This can certainly be a useful technique, but pushed to extremes tends to fragment the code into a non-linear mishmash of methods.  And extremes are what some style guides recommend.  I’ve seen one that insists no method should be more than 5 or 7 lines long!

Such code is nearly unreadable and very difficult to debug.  I know, because I’ve tried to read and debug such code before.  The human brain tends to process input in a linear fashion.  When one has to interrupt the brain to go looking for the next method, the mental stack gets overwhelmed.  Trying to trace through seven levels of function calls, each with long parameter lists typically, is just as hard as trying to follow seven levels of deeply nested loops spanning multiple pages of code.

A few judicious comments on well-paragraphed code result in much easier to read and understand code.  This is not to say that the concept of self-documenting code is useless and should be abandoned.  By all means, methods and variables should be given precise, accurate, self-documenting names.  And overly large blocks of code should be divided up into smaller methods, especially when an obvious, intuitive, object-oriented abstraction can be made, or when a complex piece of code has too many levels of deeply nested loops.

Paragraphing

While strictly not a comment in the explicit syntactical sense, grouping lines of code together into paragraphs of related code (with paragraphs separated by a blank line) is an important way to make code self-documenting.  When the lines of code that do a “thing” are scattered, the human brain has make considerable effort to work out how the “thing” is done.  It also makes future refactoring easier when an intuitive abstraction becomes obvious.

Afterthoughts

Writing good comments and keeping them up-to-date is hard.  Often even harder than writing good code in the first place.  When up against a deadline, it becomes tempting to crank out the code without concern for comments.  This almost always results in inferior code because the developer is not forced to impose structure and thoughtfulness on the code, and it becomes technical debt that slows down future enhancements and bug fixes.

While crunches are unavoidable, they should always include scheduling time after the crunch is over to clean up the code and comments.  Developers should consider it a matter of pride in their work to create code that is both stable and maintainable long after they are gone.

An analogy (I do like analogies don’t I?) would be a building contractor who puts up temporary walls and pillars while inserting new beams in a structure.  The contractor will always come back and replace the temporary structures with finely finished structures.  The programmer in a crunch is doing the equivalent of temporary walls.  They shouldn’t still be the primary wall ten years later as all too often happens in the software world.

Writing Builders for Complex Data Structures

1 Introduction

New objects are usually created by using the “new” operator and possibly passing a number of arguments to the constructor.  But for classes with many properties or with a more complex structure, the number of parameters the constructor needs becomes unwieldy or intractable.  Allocating an uninitialized object and then initializing its properties with setters gets very repetitive and unwieldy as well.  The builder design pattern offers a concise alternative.

A builder is a class that has a method (or methods) for each property to be initialized that initializes that property.  Each of these methods returns the builder so calls can be chained together using the fluent syntax pattern.  At the end of the chain, a build() method is called to actually build the object.  Typically,  a builder’s build() method can be called multiple times to construct multiple instances of an object.

This tutorial will examine what I have found to be the best way to design and implement the builder’s API.

2 Where to Define the Builder

Ideally, a class’s builder should be defined as a public part of the class itself and simply called Builder (though later on, a specialized builder with a variation on that name will be explored).

public class Resource {
    public Long id;
    public String resourceType;

    public class Builder {
        ………
    }
}

However there will be times when one doesn’t have control over the definition of the class being built, requiring the builder to be coded as a standalone class.  In this case, I recommend concatenating the class’s name with the word “Builder” to name the class’s builder.

public class ResourceBuilder {
   ………
}

3 Cloneable

In order to return a unique instance of an object for each call to build(), it is necessary to be able to make a deep copy of the object being built.  A copy constructor could be used, but I find implementing the Cloneable interface more convenient as it requires less maintenance work when the class changes.

Public class Resource implements Cloneable {
    // declare properties
    ………

    @Override
    public Resource clone() {
        try {
            Resource clone = (Resource)super.clone();

            // do any deep copying needed here
            ………

            return clone;
        } catch (CloneNotSupportedException e) {
            // this should never happen
            throw new RuntimeException(e);
        }
    }
}

In cases where one doesn’t have control over the implementation of the class being built, it may be necessary to have a utility method to perform the deep copy in the builder itself.

Public ResourceBuilder() { 
    ………

    private Resource clone(Resource resource) {
        Resource clone = new Resource();

        // deep copy from resource to clone
        ………

        return clone;
}

4 The Builder’s Constructors and build() Method

4.1 build()

The builder needs to have an object of the type being built to serve as the prototype for the object returned by the build() method.  The build() method will return a clone of the prototype object, allowing the prototype object be be further modified to build other similar object(s).

Though build() is the most common name for this method, something like toResource() where Resource is the type of the object being built is acceptable as well.  The important thing is for the method’s name to not resemble the name of a field being initialized.

4.2 Constructors

For building an object from scratch, a parameterless constructor is defined which allocates a new uninitialized prototype object.

For building an object similar to another object, a constructor is defined which takes an object as a parameter which the constructor will clone to use as the builder’s prototype object. The user might then modify just a few properties before calling the build() method to get an object that’s the same as the original object, except for the handful of properties that were modified.

For building an object similar to what would be built by another builder, a constructor is defined which takes another builder as a parameter. The constructor will clone that other builder’s prototype object to use as the new builder’s prototype object.

class Builder {
    Resource resource;

    public Builder() {
        resource = new Resource();
    }

    public Builder(Resource resource) {
        this.resource = resource.clone();
    }

    public Builder(Builder builder) {
        this.resource = builder.resource.clone();
    }

    public Resource build() {
        return resource.clone();
    }

    ………
}

4.3 Prototype Object

The “resource” field serves as the prototype or template for the object to be built.  It is common to name this variable “prototype” or “template” as well, but I prefer a name to describe what it is rather than how it’s used.  This is a matter of personal taste though.

In many cases, it can be private, but for complex objects it’s more convenient to leave it package scoped so that it is visible to subobject’s builders.  These cases will be expored in a later section.

4.4 Abstract Base Class

If a program has lots of builders, this boilerplate could be refactored into a parameterized abstract class for all builders extend.  But given the simplicity of the code (all the methods are one-liners), this may be more obfuscating than it’s worth.  The derived classes would still need to define constructors that call super(…).

abstract class AbstractBuilder<T> {
    T prototype;

    public AbstractBuilder() {
        prototype = new T();
    }

    public AbstractBuilder(T resource) {
        this.prototype = prototype.clone();
    }

    public AbstractBuilder(Builder builder) {
        this.prototype = builder.prototype.clone();
    }

    public T build() {
        return prototype.clone();
    }
}

5 Simple Builders

Consider the following simple class (a real class would define setters and getters, but for the purposes of illustration, I omit these details along with the Cloneable implementation):

public class Resource implements Cloneable {
    public Long id;
    public String resourceType;
    ………

    public class Builder {
        ………
    }
}

A builder for this class, might be used to create an object in this manner:

Resource resource = new Resource.Builder()
        .id(1234L)
        .resourceType(“PLACE”)
        .build();

Each property has its own method, with the same name as the property, for initializing that property.  Each method returns the Resource.Builder object so calls can be chained together using fluent syntax.  Also, there’s a build() method that returns a unique instance of the built Resource.

Some people like to name the initialization methods withId(), withResourceType(), etc.  But the addition of “with” to the name is syntactical sugar that just makes the syntax look cluttered.  I don’t recommend it.

public Builder id(Long id) {
    resource.id = id;
    return this;
}

public Builder resourceType(String resourceType) {
    resource.resourceType = resourceType
    return this;
}

6 Objects with Sub-Objects

Objects can have other objects as properties (in order to group related properties, for example).

 public class Resource {
    public Long id;
    public String resourceType;
    public PersonDetails personDetails;
    public PlaceDetails placeDetails;
    public ThingDetails thingDetails;
}

public class PlaceDetails {
    public String city;
    public String state;
}

………

A builder could be used to build each of the sub-objects.  Then the sub-object properties could be initialized in the object like any other property.

Resource resource = new Resource.Builder()
        .id(1234L)
        .resourceType("PLACE")
        .placeDetails(new PlaceDetails.Builder()
            .city("Phoenix")
            .state("Arizona")
            .build())
        .build();

But this is really ugly and messy, and it gets worse when sub-sub-objects and arrays of sub-objects get involved.  Better would be to access a PlaceDetails.Builder directly in the fluent syntax, like this:

Resource resource = new Resource.Builder()
        .id(1234L)
        .resourceType("PLACE")
        .startPlaceDetails()
            .city("Phoenix")
            .state("Arizona")
        .endPlaceDetails()
        .build();

6.1 The Start Method

Here’s how this can be coded.  In Resource.Builder, define startPlaceDetails() to return a builder for the PlaceDetails sub-object.

If the placeDetails property in the builder’s prototype is not yet already initialized, it is initialized here with an uninitialized PlaceDetails object, otherwise it is left alone.  This allows multiple calls to be made to startPlaceDetails() if the Resource.Builder is being used to build multiple similar objects.

public PlaceDetails.NestedBuilder startPlaceDetails() {
    if (resource.getPlaceDetails()==null) {
        resource.setPlaceDetails(new PlaceDetails());
    }
    return new PlaceDetails.NestedBuilder(this,
                                          resource.getPlaceDetails());
}

6.2 NestedBuilder

The sub-object’s builder here is called NestedBuilder to distinguish it from a regular standalone builder that terminates in a build() method.  In a later section, I’ll discuss having both a Builder and a NestedBuilder class for the same type.

The nested builder’s constructor is package scoped so that it can only be used from within the package defining resources and sub-resources.

The nested builder takes a pointer to the parent builder as an argument. When it terminates with endPlaceDetails(), that parent builder must be returned for the fluent syntax to continue with initializing the parent object.

The nested builder also takes a pointer to the sub-object it will use as its prototype object. For nested builders, it is the concern of the parent builder to manage that property and the concern of the sub-object builder to manage its initialization.

A parent object could conceivably have multiple properties of the same type.   Resource could have a PlaceDetails properties specifying birth location, marriage location, and burial location, for example.  The same nested builder can initialize all three.

Recall above that the prototype object was declared with package scope.  This was so that these nested builders can access it.

public static class NestedBuilder {
    private Resource.Builder parent;
    private PlaceDetails placeDetails;

    NestedBuilder(Account.Builder parent,
                  PlaceDetails placeDetails) {
        this.parent = parent;
        this.placeDetails = placeDetails;
    }

    public Account.Builder endPlaceDetails() {
        return parent;
    }

    public NestedBuilder city(String city) {
        placeDetails.city = city;
        return this;
    }

    public NestedBuilder state(String state) {
        placeDetails.state = state;
        return this;
    }
}

6.3 Clear Method

Ordinarily, I omit having a placeDetails(…) method when there’s a startPlaceDetails() method.  But this leaves no way to clear the placeDetails property.  If this functionality is needed, a clearPlaceDetails() method may be defined.  This sort of functionality should be used sparingly however (as discussed below).

public Builder clearPlaceDetails() {
    resource.placeDetails = null;
    return this;
}

6.4 Building Multiple Similar Objects

Several similar objects can be built with a shared builder with this setup. Obviously, this example is quite contrived, so that it would be better in this case to use separate builders, but for larger more complex objects with only minor differences between them, this capability can be very convenient.  Methods like clearPlaceDetails() should be used only very sparingly so that interdependence between the building of multiple objects doesn’t become fragile.

// create builder to reuse
Resource.Builder builder = new Resource.Builder().resourceType("PLACE");

// Phoenix
Resource phoenix = builder
        .id(1L)
        .startPlaceDetails()
            .city("Phoenix")
            .state("Arizona”)
        .endPlaceDetails()
        .build();

Resource tucson = builder
        .id(2L)
        .startPlaceDetails()
            .city("Tucson")
        .endPlaceDetails()
        .build();

Resource abrahamLincoln = builder
        .id(3L)
        .resourceType("PERSON")
        .clearPlaceDetails()
        .startPersonDetails()
            .name(“Abraham Lincoln”)
        .endPersonDetails()
        .build();

7 Objects with Arrays of Sub-Objects

What if Resource has, say, an inventory list?  This can be handled by Resource.Builder having a startInventoryList() method that returns an InventoryListBuilder, which in turn has a startInventoryItem() method that returns an InventoryItem.NestedBuilder.

InventoryListBuilder is coded as a nested class in Resource.Builder, so its constructor doesn’t need to be passed the Resource.Builder object as an explicit parameter.  It’s startInventoryItem() method adds a new item to the list.

The InventoryItem.NestedBuilder’s constructor gets passed the InventoryItem to use as its prototype object.  It is the responsibility of the InventoryListBuilder to do all manipulation of the inventoryList.

public InventoryListBuilder startInventoryList() {
    return new InventoryListBuilder();
}

public class InventoryListBuilder {
    List inventoryList;

    InventoryListBuilder() {
        if (Builder.this.account.getInventoryList()==null) {
            Builder.this.account.setInventoryList(new ArrayList());
        }
        inventoryList = Builder.this.account.getInventoryList();   
    }

    public InventoryItem.NestedBuilder startInventoryItem() {
        InventoryItem inventoryItem = new InventoryItem();
        inventoryList.add(inventoryItem);
        return new InventoryItem.NestedBuilder(this, inventoryItem);
    } 
}

An object containing an array property can then be initialized like this:

Resource resource = new Resource.Builder()
        .id(100L)
        .startInventoryList()
            .startInventoryItem()
                .item("Sword")
                .count(2)
            .endInventoryItem()
            .startInventoryItem()
                .item("Knife")
                .count(4)
            .endInventoryItem()
        .endInventoryList()
        .build();

When using builders to create several similar objects, it is convenient to add additional methods to the InventoryListBuilder to manipulate the list.  I find this particularly useful when construction test values and expected results in tests.

// modify an existing element
public InventoryItem.NestedBuilder startInventoryItem(int index) {
    return new InventoryItem.NestedBuilder(this, inventoryList.get(index));
}

// insert before an existing element
public InventoryItem.NestedBuilder insertInventoryItem(int index) {
    InventoryItem inventoryItem = new InventoryItem();
    inventoryList.add(index, inventoryItem);
    return new InventoryItem.NestedBuilder(this, inventoryItem);
}

// remove an existing element
public InventoryListBuilder removeInventoryItem(int index) {
    inventoryList.remove(index);
    return this;
}

InventoryItem.NestedBuilder needs a constructor that takes both the parent builder for being returned by endInventoryItem() and a prototype object to use.  It doesn’t clone the prototype object like the public Builder constructors do because we are explicitly wanting this builder to edit a particular prototype object in the parent builder.

NestedBuilder(Resource.Builder.InventoryListBuilder parent,
              InventoryItem inventoryItem) {
    this.parent = parent;
    this.inventoryItem = inventoryItem;
}

8 Multiple Builders for a Class

8.1 AbstractBuilder

Sometimes, both a Builder for building standalone objects and one or more NestedBuilders for building objects that are sub-objects of another object might be needed.  It is desirable for these builders to share as much code as possible (the DRY principle: Don’t Repeat Yourself).  For encapsulating the common code between the builders, a private AbstractBuilder can be defined which Builder and NestedBuilder extend.  This AbstractBuilder defines the property initializer methods while the derived builders define the constructors and the build() and end…() methods.

Writing an AbstractBuilder is a little tricky because it must be parameterized so that the property initializer methods return the derived builder object, not the AbstractBuilder object.  So, AbstractBuilder gets parameterized with a type that’s an extension of AbstractBuilder.  Amazingly, this works.

The builders derived from AbstractBuilder will provide a subThis() method that returns the subclasses’ “this” pointer.  It is used to provide the value that is returned by the initializer methods.

private static abstract class 
        AbstractBuilder<T extends AbstractBuilder<T>> {
    protected InventoryItem inventoryItem;

    // sub classes provide a this pointer of the appropriate type
    protected abstract T subThis();
    private T subThis = subThis();

    public T item(String item) {
        inventoryItem.setItem(item);
        return subThis;
    }

    public T count(int count) {
        inventoryItem.setCount(count);
        return subThis;
    }
}

8.2 Extensions of AbstractBuilder

Extensions of AbstractBuilder should parameterize AbstractBuilder with their own type so that the initialization methods can return the subtype’s object instead of the AbstractBuilder object. They provide a constructor, a subThis() method, and an appropriate build() or end…() method. The constructors and build() or end…() methods are coded just like they are for regular Builder and NestedBuilder classes as described above.

The subThis() method just returns the extension’s “this” pointer and is called by the AbstractBuilder’s initialization methods to return the appropriate builder object.

public static class Builder extends AbstractBuilder<Builder> {
    public Builder() {
        this.inventoryItem = new InventoryItem();
    }

    // more constructors can go here as needed
    ………

    public InventoryItem build() {
        return inventoryItem.clone();
    }

    @Override
    protected Builder subThis() {
        return this;
    }
}

public static class NestedBuilder extends AbstractBuilder<NestedBuilder> {
    private Account.Builder.InventoryListBuilder parent;

    NestedBuilder(Account.Builder.InventoryListBuilder parent,
                  InventoryItem inventoryItem) {
        this.parent = parent;
        this.inventoryItem = inventoryItem;
    }

    public Account.Builder.InventoryListBuilder endInventoryItem() {
        return parent;
    }

    @Override
    protected NestedBuilder subThis() {
        return this;
    }
}

8.3 Multiple NestedBuilders

Conceivably, a class may be used in serveral different places of multiple complex data structures.  For this case, parameterize the NestedBuilder class with the type of the parent builder.

public static class NestedBuilder<T> 
        extends AbstractBuilder<NestedBuilder<T>> {
    private T parent;

    NestedBuilder(T parent, InventoryItem inventoryItem) {
        this.parent = parent;
        this.inventoryItem = inventoryItem;
    }

    public T endInventoryItem() {
        return parent;
    }

    @Override
    protected NestedBuilder<T> subThis() {
        return this;
    }
}

Then, in the definition of the start…() method in the parent builder, parameterize the NestedBuilder return type with the parent builder’s type.

InventoryItem.NestedBuilder<InventoryListBuilder> startInventoryItem() {
    InventoryItem inventoryItem = new InventoryItem();
    inventoryList.add(inventoryItem);
    return new InventoryItem.NestedBuilder<InventoryListBuilder>
            (this, inventoryItem);
}

9 Cookbook

This essay presents a broad cookbook of builder features and how to implement them. While the implementation of some of these features is complex, and some of the features can easily be abused to create fragile code, I have found these ideas to be very powerful and useful in building complex data structures in a succinct and easy-to-read manner.

They are especially useful in writing tests because lots of similar objects with minor variations are often needed.  For example in a test for a REST service, a number of similar resources might be built for POSTing.  The result that is returned from the REST service may then consist of what was posted, plus some additional bits and pieces like a generated primary key and HATEOAS links.  The expected results to compare against can be built from the POSTed resources with some additional initialization.

Pragmatic Unit Testing, Part 2

4 Integration Testing REST Services

Now, we’ll look at using junit to do integration testing of a full REST service.  This will work much like functional tests in that we’ll first test creating resources, then test the rest of the CRUD operations by operating on such created resources.  But first some preliminaries.

Continue reading “Pragmatic Unit Testing, Part 2”

Pragmatic Unit Testing, Part 1

1  Extreme Programming Extremism

Dark chocolate is good for you.  It’s good for your heart and may prevent cancer.  But no one should take consumption of dark chocolate to the extreme and eat it for breakfast, lunch, and dinner. That wouldn’t just be silly, it would be decidedly unhealthy.  Yet a current fad in software development goes under the moniker of “extreme programming” where otherwise good ideas are taken to extremes.  Code reviews are good, so have someone sitting next you continuously code reviewing every keystroke you type.  Or, the subject of this essay, testing code in isolation is good and using mocks is useful, so obsessively test every class in isolation while mocking every other class it depends on.  It is the goal of this essay to argue for a more pragmatic, moderate approach to unit testing. Continue reading “Pragmatic Unit Testing, Part 1”