1. Overview

In programming, it’s usual to come across the term “boilerplate” code once in a while. The term originated in the metal printing industry. In metal printing, boilerplate refers to metal printing plates that could be reused for the same purpose.

In software development, boilerplate has somewhat the same meaning, albeit there is more to it. In this article, we’ll cover boilerplate code in the context of programming. Then, we’ll take a look at practical, real-world examples where boilerplate code is used.

Finally, we’ll discuss how to avoid writing repetitive boilerplate code to increase productivity.

2. What Is Boilerplate Code

Boilerplate code is a piece of repetitive code that can be used over and over with little to no changes. Boilerplate code often represents standard practices and patterns throughout a codebase. Thereby creating a familiar structure that developers can follow.

In programming, we often see boilerplate code in object-oriented languages, where the private properties of a class are accessed and modified through accessors and mutator methods. Similarly, in markup languages like HTML, the boilerplate code is found in the head section that is similar across multiple HTML web pages.

In the next section, we’ll dive into several examples to see what boilerplate code looks like.

3. Boilerplate Code in Practice

Boilerplate code can be found in languages that are verbose like C++, Java, and Go. Sometimes, these verbose languages tend to be object-oriented. In contrast, functional programming languages tend to be less verbose.

3.1. Object-Oriented Languages

In object-oriented languages, we often deal with classes and encapsulation. Therefore, we declare the class properties to be private, and the only way to access or mutate them from clients is to use setter and getter methods.

So, we repeat writing these setters and getters for most classes in the codebase, which leads to boilerplate code. Let’s observe this in Java:

public class Taco {
    private String name;
    private double price;
    private List<Ingredient> ingredients;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public List<Ingredient> getIngredients() {
        return ingredients;
    }

    public void setIngredients(List<Ingredient> ingredients) {
        this.ingredients = ingredients;
    }
}

Notably, each property has its pair of setters and getters that follow a similar pattern throughout the class.

In addition, a class in Java can also contain an equals, a hashCode, and a toString methods for comparison, hash code generation, and string representation, respectively:

public class Taco {
    // ...
    @Override
    public boolean equals(Object o) {
        if (this == o) { 
            return true; 
        }
        if (o == null || getClass() != o.getClass()) { 
            return false; 
        }
        Taco taco = (Taco) o;
        return Double.compare(price, taco.price) == 0 &&
          Objects.equals(name, taco.name) &&
          Objects.equals(ingredients, taco.ingredients);
    }

    @Override
    public int hashCode() { 
        return Objects.hash(name, price, ingredients); 
    }

    @Override
    public String toString() {
        return String.format("Taco{name='%s', price=%.2f, ingredients=%s}", name, price, ingredients);
    }
}

These methods are implemented in many Java classes with minor changes. The implementation might be a bit different, but the general structure remains consistent.

Later on, we’ll learn how to minimize writing this boilerplate code ourselves.

3.2. Markup Languages

In markup languages like HTML and XML, we often see boilerplate code in the head sections. Let’s take a look at a typical HTML  boilerplate:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Title</title>
    <meta name="description" content="Description of the web page">
    <meta name="keywords" content="keyword1, keyword2, keyword3">
    <link rel="stylesheet" href="/static/styles.css">
    <link rel="icon" href="/static/favicon.ico" type="image/x-icon">
    <script src="/static/scripts/script.js" defer></script>
</head>
<body>
    <!-- Webpage elements -->
</body>
</html>

In the example, we see a common starting point of an HTML webpage. The head element is comprised of meta, title, link, and script elements. These elements provide the metadata and required assets for the webpage to function properly. Therefore, they are available on most web pages that we come across on the web.

On the other hand, we see a similar pattern in XML as well:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <!-- Document elements -->
</root>

The xml element defines the document’s version and encoding. The root element serves as a container for other elements. We can replace the root element with a more descriptive name.

We often encounter this boilerplate code in configuration files that use XML, which we’ll cover next.

3.3. Configuration Files

During the development of software, a programmer also deals with configuration files. These configuration files often follow a consistent structure across projects.

For instance, in Maven-based projects, there is a pom.xml file that lets us manage project dependencies, configuration, and build settings. Let’s take a look at a pom.xml file for a Spring Boot project:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.baeldung</groupId>
    <artifactId>example</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>example</name>
    <description>An example pom.xml to demonstrate boilerplate code</description>
    <properties>
        <java.version>21</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- Additional dependencies -->
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

Other projects might have a different pom.xml file, but the foundational structure remains the same. At the top, we define the project metadata and, then, project dependencies and configurations. We can see that the configuration uses elements like groupId and artifactId, which are also common to other Spring Boot projects.

This pattern also exists in other projects. For instance, a Node project includes a package.json file, a Rust project includes cargo.toml, and .NET projects contain *.csproj files.

4. Avoiding Boilerplate Code

In programming, the boilerplate code can sometimes be tedious, long, and boring. Not only that, but it can also negatively impact the development time of a project and clutter the codebase.

Fortunately, there is a wide range of solutions to address this problem.

4.1. Libraries

Most programming languages have libraries that provide boilerplate code generation for common patterns. For instance, the Lombok project in Java provides a library that helps us minimize writing boilerplate code.

It can handle automatic method generation for getters, setters, constructors, equals, hashCode, and so on:

import lombok.Data;

@Data
public class Taco {
    private String name;
    private double price;
    private List<Ingredient> ingredients;
}

In the example, we annotate the class with @Data, and Lombok generates the aforementioned methods at compile time. This increases productivity and makes the code very readable.

4.2. Code Generation in IDE

Most Integrated Development Environments (IDEs) come with code generation features. For instance, IntelliJ IDEA, Eclipse, and Netbeans provide tools to generate class boilerplate. These tools come in handy if we don’t need to use a third-party library.

As an example, let’s take a look at this feature in IntelliJ IDEA. We simply open up a Java file and put the cursor anywhere in the body of a class. Then, head over to Code → Generate:

Intellij: Generate Code Menu

In the menu, we select the required option, which will present us with a dialog:

Intellij: Generate Code Dialog

In the case of generating getters and setters, we need to select the relevant properties. Then, we press “OK” to generate the code. In the same way, we can also generate the constructors as well as the equals, toString, and the hashCode methods.

4.3. Plugins

Most IDEs and code editors support add-ons. Some of the plugins come pre-installed. For instance, VSCode, IntelliJ, and many other IDE comes with Emmet plug-in pre-installed, which lets us quickly generate HTML/XML markup.

For example, if we want to create an unordered list that contains list items, we can type ul.list>li.list-item*10 and press Tab:

<ul class="list">
    <li class="list-item"></li>
    <li class="list-item"></li>
    <li class="list-item"></li>
    <li class="list-item"></li>
    <li class="list-item"></li>
</ul>

Similarly, there are snippet plugins that let us quickly generate simple code. For example, in IntelliJ, we can type sout and press Tab to generate System.out.println(); at the cursor position.

4.4. Project Starters

In software engineering, there are patterns so common that developers have created project starters or project templates to help kickstart new projects with minimal setup and boilerplate code. It includes project structure, default configurations, and initial code.

One such project starter is Spring Initializr, which helps us kickstart a new Spring Boot project.

5. Conclusion

In this article, we learned about boilerplate code in software development. We discuss what boilerplate code looks like in programming languages, configuration files, and markup languages.

Afterward, we learned how to reduce boilerplate code through various approaches like using libraries, code generation, and project starters.

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments