How do you break a Monolith into Microservices at Scale? This ebook shows strategies and techniques for building scalable and resilient microservices.

In my previous post, I looked at some of the problems associated with long parameters lists for methods and constructors. In that post, I discussed replacing primitives and built-in types with custom types to improve readability and type safety. That approached made the numerous parameters to a method or constructor more readable, but did nothing to reduce the number of parameters. In this post, I look at use of a Parameter Object to reduce the number of parameters to a method or constructor.

It is generally not a good idea to make "junk drawer" objects that couple unrelated parameters whose only relationship to one another is that they need to be passed to the same method or constructor. However, when related parameters are being passed to a constructor or method as part of a highly cohesive object, therefactoring known as Introduce Parameter Object is a nice solution. This refactoring's usage is described as"group[ing] of parameters that naturally go together." I will demonstrate this refactoring in this post.

To demonstrate the utility of the Introduce Parameter Object refactoring, let's first look at the example from the last post which uses numerous String and boolean parameters in a method call.

As I discussed in the previous post, this approach is tedious for callers, makes it all too easy to pass parameters in the wrong order with little type safety, and can reduce readability of the code. Fortunately, the parameters in this example provide some good opportunities to apply the Introduce Parameter Object refactoring. The "names" parameters (including salutation and suffix) could be included in a single full name class. The address parameters (street address, city, and state) could be in a single address object. The other parameters might not be so easily grouped into a single class with high cohesion.

With the suggested applications of the Introduce Parameter Object refactoring, the previously shown method call is simpler thanks to the reduced number of parameters. This is shown in the next code listing.

public Person createPerson(
final FullName fullName,
final Address address,
final boolean isFemale,
final boolean isEmployed,
final boolean isHomeOwner)
{
return new Person();
}

The above example now only has five parameters and is more readable and easier to use by clients. It is also more safe from a typing perspective as it is nearly impossible to confuse strings of names with strings of address in this case. Unfortunately, the three boolean parameters remain a source of potential confusion and cloud readability a bit. The next code listings show potential implementations of the FullName and Addressclasses.

Although the code is improved, there are still some issues that can be improved. In particular, the original method with too many parameters still has three boolean parameters that can be easily confused with one another. Although the String parameters to that method were factored into two new classes, those two new classes still each consist of a bunch of Strings. In these cases, one might want to supplement the Introduce Parameter Object refactoring with use of custom types. Using the custom types I showed in my last post, the method with too many parameters now looks like that shown in the next code listing.

The method now has fewer parameters and the parameters it does have are all of distinct types. IDEs and the Java compiler can now be especially helpful in ensuring that clients use this interface properly. Applying custom types (written in last post) to the FullName and Address classes result in the next two new code listings for those classes.

All of my examples thus far have been of standalone public classes. I often find that if I need a parameter object simply for passing information between methods and constructors in the same package that it can be useful to make these parameter object classes package scope. Nested classes can also be used for these parameter objects in some cases.

Benefits and Advantages

The most obvious benefit of the parameter object is the reduction in number of parameters passed to a method or constructor. This encapsulation of related parameters makes it easier to quickly ascertain what types are being passed to the method or constructor. It is easier for a developer to understand a smaller number of parameters.

Parameter objects share one of the same benefits provided by custom types: the ability to add additional behaviors and characteristics to the parameter object for convenience functions. For example, having anAddress class rather than a bunch of String types allows one to validate addresses.

Costs and Disadvantages

The primary drawback to the parameter object is a little extra work to design, implement, and test the class. However, these are pretty easy to write and test and modern tools such as IDEs and scripting languages make it even easier to automate the most mundane and tedious portions of those tasks. An even smaller argument against this approach is that it can be abused. If a developer starts bundling unrelated parameters together into a class just to reduce the number of parameters, that doesn't necessarily help the situation. That approach does indeed reduce the number of parameters, but the ultimate goal of improving readability is not achieved and it could be argued that this approach is even less readable.

Conclusion

Parameter objects provide a nice clean approach to appropriately encapsulating related parameters to reduce the total parameter count to a method or constructor. They are easy to implement and can significantly enhance the readability and type safety parameters passed to method and constructor calls. Parameter objects can be enhanced further through the use of custom types as explained in my previous post.

How do you break a Monolith into Microservices at Scale? This ebook shows strategies and techniques for building scalable and resilient microservices.