Avoiding the Builder Design Pattern in Kotlin
Tags: kotlin, designpatterns, antipatterns, builder
Published: 2018-01-05 04:28:27

---
title: Avoiding the Builder Design Pattern in Kotlin
published: true
tags: #kotlin #designpatterns #antipatterns #builder
cover_image: https://thepracticaldev.s3.amazonaws.com/i/wtslwgxu0avzs8vwddj9.jpg
---

The Builder Design Pattern provides us with a series of methods that can act as an aid in order to let the _consumer_ of your class better understand what is happening under the hood.

But it is considered an _Anti-Pattern_ by some developers.

# Why use Builder Design Pattern?

It's an alternative to using multiple `constructors` by overloading them with more and more parameters.

## What are the pros?

- There are tools that allow you to get hints of what the name of the parameter is, which may help if their names are informative, but it is not always the case. Like, for example: reading code on GitHub or another IDE/editor.
- You don't need to have all the data required to pass it to your object right when you initialize it.

## What are the cons?

- You can end up having methods that require others to be ran in a certain order; otherwise, the _consumer_ will run into issues if you implement it wrong.
- The chain of methods can get really long depending on the implementation.
- The _consumer_ may forget to finish up the statement with the `build()` method and not get the results they expected.
- Uses more memory resources.

# How can we avoid it?

## Default Parameters

[Kotlin](https://kotlinlang.org) supports _default parameters_ (Which is also available in other languages like C# and JavaScript).

```kotlin
fun pow(base: Int, power: Int = 2): Int {
    // ...
}
```

This can work as an alternative to method overloading, since the _consumer_ of this method can use it like this:

```kotlin
pow(2) // outputs 4
pow(2, 3) // outputs 8
```

Which can make our life easier by only having to maintain a single method.

## Named Arguments

This allows our _consumers_ to not only type in exactly what argument they want to assign to an exact parameter, but we can also reorder them in whatever way we want. This can be handy when dealing with "legacy code" that can be hard to understand because of how many parameters requires.

```kotlin
pow(base = 4, power = 3) // outputs 64
pow(power = 3, base = 4) // also outputs 64
```

## Can we combine them?

Of course, my dear Watson!

```kotlin
pow(base = 3) // outputs 9
```

In the example above we are passing the `base` argument as a `named argument` and the `power` is using the `default parameter` value in our method signature.

Now that we know how to do this, we can use them to avoid the Builder Design Pattern in Kotlin.

First, let's check out the code we would have to write in Java by creating a simplified version of a Hamburger `class`:

```java
// Hamburger.java


public class HamburgerJava {
    private final boolean hasKetchup;
    private final boolean hasTomatoes;
    private final int meats;


    private HamburgerJava(Builder builder) {
        hasKetchup = builder.hasKetchup;
        hasTomatoes = builder.hasTomatoes;
        meats = builder.meats;
    }

    public static class Builder {
        private boolean hasKetchup;
        private boolean hasTomatoes;
        private int meats;

        public Builder(int meats) {
            if (meats > 3)
                throw new IllegalArgumentException("Cannot order hamburger with more than 3 meats");
            if (meats < 1)
                throw new IllegalArgumentException("A hamburger must have at least 1 meat.");
            
            this.meats = meats;
        }

        public Builder addKetchup(boolean hasKetchup) {
            this.hasKetchup = hasKetchup;
            return this;
        }

        public Builder addTomatoes(boolean hasTomatoes) {
            this.hasTomatoes = hasTomatoes;
            return this;
        }

        public HamburgerJava build() {
            return new HamburgerJava(this);
        }

    }
}
```

Now, let's see how we can use our _HamburgerJava_ `class`:

```java
HamburgerJava doubleMeatWithEverything = new HamburgerJava.Builder(2)
                .addKetchup(true)
                .addTomatoes(true)
                .build();
```

Cool, maybe some of you guys are used to this.

Now let's take a look at the Kotlin implementation in our Hamburger `class`:

```kotlin
// Hamburger.kt

class Hamburger(
        val meats: Int,
        val hasKetchup: Boolean = false, 
        val hasTomatoes: Boolean = false
)
```

Let's see how it looks when we try to use it:

```kotlin
val doubleMeatWithEverything = Hamburger(
            meats = 2,
            hasKetchup = true,
            hasTomatoes = true
    )
```

By using `named arguments` and `default parameters` we can avoid the problem of not knowing what values we are being passed to each parameter and have only a single constructor to maintain.

The only cons we have with this approach is that we lose the ability to pass in values to our object after it's creation.

Which is something I don't think is that common, or is it? 🤔