I like builders. If you’ve ever seen a constructor with ten parameters, eight of which can be null, you probably like builders, too. While this pattern is quite verbose, it is elegant.

After doing some work with builders, I found myself wondering. Why are getters ever used in these? From Single Responsibility Principle point of view, a builder’s only purpose is to ease creation of a complex object.

Giving access to its data is definitely not the purpose of a builder. It allows the builder to be passed around instead of the (immutable) object itself. However, until built, builder is still invalid and incomplete and definitely not a data object.

I came up with a custom pattern of my own. The builder is in an inner class, the object has a single constructor that takes the builder as its only parameter. Judging by my experience so far, it was a good decision. It also goes well with my no getters approach.

Using a simple immutable class Product, the object-builder duo can look like this:

class Product {
    private final int price;
    private final List<Photo> photos;

    private Product(final Builder builder) {
        this.price = builder.price;
        this.photos = builder.photos;
    }

    public builder() {
        return new Builder(this);
    }

    // equals, hashCode, toString, getters

    public static class Builder {
        private int price;
        private List<Photo> photos;

        public Builder() {
        }

        private Builder(final Product entity) {
            this.price = entity.price;
            this.photos = entity.photos;
        }

        public Builder withPrice(final int price) {
            this.price = price;
            return this;
        }

        public Builder withPhotos(final Collection<Photo> photos) {
            this.photos = Collections.unmodifiableList(
                    new ArrayList(photos));
            return this;
        }

        public Product build() {
            this.validate();
            return new Product(this);
        }

        private void validate() {
            if (photos == null {
                throw new IllegalStateException("photos is null");
            }
        }
    }
}

As you can see, the object constructor is private, as it is only called from the inner class. Another nice thing about it is the fact it only has one parameter – the builder.

To ensure a list is immutable, a defensive copy is needed. It is usually done in constructor of the object. I chose the setter instead, as it is the only entry point where a mutable list can come from. Also, if you use Builder to change Product’s price, you can reuse photos without copying.

Method validate throws an IllegalStateException whenever anything makes it impossible to build correctly. (Your conventions may differ). I used simple if/throw in the example, however, an utility class can shorten it significantly.

Now, imagine you had an (abstract) super-class for your Product object. I’ve read that you need getters in this case, as you cannot access the (private) fields of the superclass. It would be true, provided that you had to pass the individual parameters to the constructor. But if you pass the builder instead, it is actually easy without them:

class Product extends NamedItem { ...
    private Product(ProductBuilder builder) {
        super(builder);
        ...
    }
    ...
    public static class Builder extends NamedItem.Builder {
        ...
        protected void validate() {
            super.validate();
            ...
        }
    }
}

No getters needed either. So I still haven’t encountered a builder problem that actually requires getters. Have you?

Probably every programmer knows switch-case keywords. They are often used to convert data, e.g. some string from another (sub)system to your enum. While working with those, I found two patterns I call best practices.

The first one uses return outright. Its code is short and elegant:

transformGender(String gender) {
    switch(gender) {
        case "M": return Gender.MALE;
        case "F": return Gender.FEMALE;
        case "I": return Gender.INTERSEX;
        default:  return Gender.UNKNOWN;
    }
}

However, some might argue it doesn’t follow the single-exit pattern. If you happen to add e.g. logging, it makes it complicated. Since copy-pasting code would make it a direct opposite of what you were trying to do there, a different pattern should be used. I found one:

transformGender(String gender) {
    final Gender result;
    switch(gender) {
        case "M": result = Gender.MALE;
                  break;
        case "F": result = Gender.FEMALE;
                  break;
        case "I": result = Gender.INTERSEX;
                  break;
        default:  result = Gender.UNKNOWN;
    }
    return result;
}

Obviously, the price for single exit is a longer code (breaks, storing the value). However, it still keeps one advantage of the previous pattern (the basic Java tutorial doesn’t teach it): You can be sure your result is not modified, thanks to final keyword. If you fail to write the value exactly once, a compiler error warns you instantly. Also, it makes it hard to write messy code with preset value and no default branch.

I was curious if the pattern can be used in C#, but it seems it can’t. The keyword final has no equivalent in C#, with readonly not really working in the same manner. Where readonly states that it can only be written in constructor or declaration, final means that the field or variable can only be written once.