Bozhidar Bozhanov

About Bozhidar Bozhanov

Senior Java developer, one of the top stackoverflow users, fluent with Java and Java technology stacks - Spring, JPA, JavaEE. Founder and creator of Computoser and Welshare. Worked on Ericsson projects, Bulgarian e-government projects and large-scale online recruitment platforms.

Coping with Methods with Many Parameters

I will put my captain Obvious cape now and write in short how to get rid of methods with many parameters, especially if some of the parameters are optional, or depend on each other somehow (e.g. go in pairs, one excludes another, etc.).

Let’s take a simple RestClient class. You need to be able to pass the target resource, optional HTTP headers, HTTP method, request body, timeouts, etc. All of these, except the URL, are optional. How do you write this class?

The first thing that comes to mind is overloading:
 
 
 

public <T> T request(String url);
public <T> T request(String url, HttpMethod method, Object body);
public <T> T request(String url, HttpMethod method, Object body, Map<String, String> headers);
public <T> T request(String url, HttpMethod method, Object body, Map<String, String> headers, long timeout);

Good? No. Because you may want to call a URL with GET, specifying a timeout, but not specifying body or headers. And whenever a new parameter is to be added (e.g. for authentication), then you should copy all the methods and append the parameter. To put it simply: you cannot and should not have an overloaded method for each possible combination of the parameters.

How should we approach the problem? There are several ways, and the one I prefer is using something like the Builder pattern. The Builder pattern is supposed to be used for constructing objects and to replace constructors taking multiple arguments. But its philosophy can be transferred to the above problem. For example:

public <T> T request(RestCall call);

What is RestCall? It’s a mutable object that you configure, preferably with a fluent interface, in order to make your rest call. All fields have getters so that the RestClient can obtain all the fields in needs. A usage might look like this:

client.request(RestCall.to(url).withMethod(HttpMethod.POST)
    .withBody(requestObject).withTimeout(5000));

It reads like prose, it lets you have only one (or very few) methods, rather than overload for each possible combination, and at the same time allows you to have each possible combination of parameters. The “to(..)” method is a simple factory-method. An example implementation of a withX method looks like this:

public RestCall withBody(Object body) {
    this.body = body; //assign a private field
    return this;
}

You can also have reasonable defaults for each field. In this case, a GET method, a predefined default timeout.

This approach also gives you the option to specify constraints. For example, you shouldn’t allow setting a body for GET requests. So:

public RestCall withBody(Object body) {
    if (method == HttpMethod.GET) {
         throw
              new IllegalStateException("Body not supported for GET");
    }
    this.body = body; //assign a private field
    return this;
}

And if two parameters go together, for example you want to add headers one by one, then you can have an addHeader(String, String) method.

Generally, the approach is more readable and is easier to extend and maintain.
 

Reference: Coping with Methods with Many Parameters from our JCG partner Bozhidar Bozhanov at the Bozho’s tech blog blog.
Related Whitepaper:

Software Architecture

This guide will introduce you to the world of Software Architecture!

This 162 page guide will cover topics within the field of software architecture including: software architecture as a solution balancing the concerns of different stakeholders, quality assurance, methods to describe and evaluate architectures, the influence of architecture on reuse, and the life cycle of a system and its architecture. This guide concludes with a comparison between the professions of software architect and software engineer.

Get it Now!  

Leave a Reply


− one = 6



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.

Sign up for our Newsletter

20,709 insiders are already enjoying weekly updates and complimentary whitepapers! Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

As an extra bonus, by joining you will get our brand new e-books, published by Java Code Geeks and their JCG partners for your reading pleasure! Enter your info and stay on top of things,

  • Fresh trends
  • Cases and examples
  • Research and insights
  • Two complimentary e-books