Use builder pattern for methods with many parameters? [duplicate] - java

This question already has answers here:
Best practice for passing many arguments to method?
(17 answers)
Closed 9 years ago.
I've read a recommendation in "Effective Java" to use the Builder pattern when faced with constructors that use lots of parameters.
Does the same pattern apply to methods with lots of parameters ?

Yes, sort of. You basically create a new type to encapsulate all the parameters - or maybe just some of them.
Now you can create a builder and then an immutable version of the type - or you could just allow the "uber-parameter" type to be mutable and pass it directly in. In the latter case you don't have a builder pattern as such, but you can sort of view it as building the method call itself, in that you can specify each aspect of the method call separately.
You could argue that the builder pattern is actually just a special case of this pattern, in some ways - it so happens that the build() method is usually on the builder rather than having the builder as a method parameter elsewhere, but there's a definite correlation between the way the two work.
An example of this in the .NET framework is XmlWriterSettings which is passed into a bunch of methods or constructors. (It's sort of used as a builder in that usually it's used when constructing an XmlWriter.) I can't think of any examples within the standard Java library right now, but they may exist somewhere...
If you do find yourself with lots of parameters though, it's worth taking another look at the design to check whether you shouldn't be grouping some of them together anyway, just as part of normal design.

Not exactly, because what Builder does is building an object.
So what would be the point of changing some method, which does who knows what, into a Builder?
What you should do with methods containing too many arguments is for example:
break it down to smaller methods,
use varargs
use some Collection to put into the same type arguments

Turning a method into a builder is possible but atypical. Apache HashCodeBuilder is one example, used like int hash = new HashCodeBuilder().append(a).append(b).build();, although in that specific case you might prefer to just use a method with varargs, like Guava's Objects.hashCode, used like int hash = Objects.hashCode(a, b);.
A method which takes a large number of arguments of different types is ill-suited to varargs, so you might find a builder appropriate, or you might want to consider reducing the amount of work that is being done in that method, or encapsulating the arguments in some other composite type.

Related

Do "Clean Code"'s function argument number guidelines apply to constructors?

Chapter 3 of "Clean Code" makes it pretty clear that keeping the number of function arguments small is good practice. I'm now trying to avoid anything beyond dyads. It's been working out ok so far but I keep running into situations where I need three arguments to construct an object. Of course I could create an argument object to solve this but then I'd have to choose two of the three arguments to group together and that does not always make sense. So my question is if this guideline applies to constructors as well or if I shouldn't worry about triad constructors.
These "rules" are guidelines and it depends on the use case. In general, it's a good idea to keep the number of arguments low. Besides using composite types as arguments, there are some common patterns for this:
The classic builder pattern, or what I prefer, the modern variation fluent builder pattern
E.g.:
Email email = Email.EmailBuilder()
.setFrom("Test#gmail.com")
.setTo("mail#gmail.com")
.setSubject("Test with only required Fields")
.setContent(" Required Field Test")
.build();

Java 8 + Constructor References [duplicate]

I was reading about Java 8 features, which lead me to this article and I was wondering about the actual uses of constructor reference, I mean why not just use new Obj ?
P.S, I tried googling, but I failed to find something meaningful, if someone has a code example, link or tut it will be great
First of all, you should understand that constructor references are just a special form of method references. The point about method references is that they do not invoke the referenced method but provide a way to define a function which will invoke the method when being evaluated.
The linked article’s examples might not look that useful but that’s the general problem of short self-contained example code. It’s just the same as with the “hello world” program. It’s not more useful than typing the text “hello world” directly into the console but it’s not meant to be anyway. It’s purpose is to demonstrate the programming language.
As assylias has shown, there are use cases involving already existing functional interfaces using the JFC API.
Regarding the usefulness of a custom functional interface that’ll be used together with a constructor reference, you have to think about the reason to use (functional) interface in general: abstraction.
Since the purpose of an interface is to abstract the underlying operation, the use cases are the places where you do not want to perform an unconditional new SomeType(…) operation.
So one example is the commonly known Factory pattern where you define an interface to construct an object and implementing the factory via constructor reference is only one option out of the infinite possibilities.
Another important point are all kinds of Generic methods where the possibility to construct instances of the type, that is not known due to type erasure, is needed. They can be implemented via a function which is passed as parameter and whether one of the existing functional interfaces fits or a custom one is needed simply depends on the required number and types of parameters.
It's useful when you need to provide a constructor as a supplier or a function. Examples:
List<String> filtered = stringList.stream()
.filter(s -> !s.isEmpty())
.collect(Collectors.toCollection(ArrayList::new)); //() -> new ArrayList<> ()
Map<String, BigDecimal> numbersMap = new HashMap<>();
numbersMap.computeIfAbsent("2", BigDecimal::new); // s -> new BigDecimal(s)
someStream.toArray(Object[]::new); // i -> new Object[i]
etc.

Constructor with many required parameters

If I have a constructor for an immutable object that requires several (4+ parameters), is having a single constructor with all the required parameters the correct approach?
I feel this becomes a candidate for the Builder pattern, but I also feel like shying away from it since the parameters are required, and a Builder seems more appropriate when you get to pick and choose.
The example in my mind is a model object that does not change once created.
If you want to create an immutable object, you have to provide a constructor with all necessary fields.
You cannot set the state partially as later you would have to add some notion of "setters" which would by definition add mutability.
Builder pattern is really about partial object building.
Both options have their drawbacks, as you suggest. A four argument constructor is hard to use correctly and makes the code hard to read. However, it communicates the intent that all parameters are mandatory.
A builder would be easier to use and make the code easier to read, but communicate the intent that the arguments are optional.
Since code is more often read than written, I recommend to use the option that promotes readability in this case. Go for a builder and make sure that all paramters are validated when the build() method is called to fail as fast as possible when using the builder incorrectly. Use javadoc to assist with communicating that all parameters are mandatory.

design issue about multiple parameters in a function

first of all I'm using java, even though it could be a question for any language
say I have a complicated system, now sometimes I end up building objects (setting all the parameters), then passing it over to a "target layer"(manager), which opens the object (getting the parameters).
if I were to pass all the parameters in one function, it would be considered poor design, because there's suppose to be a small amount of parameters per function
this seems like a waste, and in the past I also decided to set the parameters straight to the "target layer"
is there a design pattern that deals with this issue?
or something that books or experts in the subject recommend?
You might take a look on the Effective Java Book that will cover Design method signatures carefully
There will be three techniques for shortening long parameters :
break the method into multiple methods, each which require only a subset of the parameters
create helper classes to hold group of parameters (typically static member classes)
adapt the Builder
pattern from object construction to method invocation
Since you're asking the reference, I hope it can help solve your problem and don't forget to buy the book here
Since you were asking about book references, here is one from Clean Code, Chapter 3: Functions:
When a function seems to need more than two or three arguments, it is
likely that some of those arguments ought to be wrapped into a class
of their own. [...]
Reducing the number of arguments by creating objects out of them may
seem like cheating, but it’s not. When groups of variables are passed
together, [...] they are likely part
of a concept that deserves a name of its own.
So I guess it's ok to group a lot of method arguments into classes, as long as these classes represent some coherent concepts.
Personally if I do something like this, I like the wrapper class to be immutable and created by a dedicated builder. Which increases the number of additional classes twofold (wrapper and the builder), but enables the treatment of such a class as one atomic argument.
Extract the parameters into its own "Parameter-Object" (pattern name) and pass that object to the function.
If the Parameter-Object itself is complicated to construct, use the Builder-Pattern which simplifies the construction if the object can be constructed in different ways.
For Example:
function(param1, param2, param3, ...)
The parameters are then extracted into an Object:
class ParamObject {
param1;
param2;
param3;
}
with its corresponding setters and getters.
To construct the ParamObject use the BuilderPattern.
And finally, the invocation would look like this:
function(paramobject):
Inside the function the former arguments are then retreived from the object.
As siledh stated: Make sure to group arguments into classes that share a common concept, which means that it´s ok to create several classes out of the paramlist.
This sounds like a Data Transfer Object to me.
http://martinfowler.com/eaaCatalog/dataTransferObject.html

What design is better: universal builder or several concrete methods?

I need to create an email-notification service (as a part of a bigger project).
It will be used to send several types of notification messages which are based on html-templates.
I can design it in two ways:
The first way is based on the builder pattern. It's universal (as I think) and can handle all necessary cases. But it's not very convenient for those who will use it. The typical usage would look like this:
messageBuilder
.put("name", "John Doe")
.put("company", companyObj)
.processPattern(pattern)
.send(addresses, subject);
The second way is to implement all cases explicitly. It means that usage code (shown below) will be as simple as possible but we'll have to modify API (add new methods) every time when we need to handle any new case.
messageSender.sendPersonExpenceNotification(addresses, "John Doe", company);
Which one is better? Why? (the language is Java if it matters)
Thanks!
I think the answer is to use both. I would suggest using the more generic approach (the message builder) in the API and then providing client-side convenience functions/classes that are simple to use for specific tasks. This way the API doesn't have to update when you add new cases but the client can still use the most direct call for what they're trying to do.
Effective Java 2nd Edition, Item 2: Consider a builder when faced with many constructor parameters.
The builder pattern is more readable, especially as you have potentially many more parameters. That said, it's usually more common to have specific setName, setCompany, etc methods for a builder. That way you can also enforce type-safety, e.g. setSomeBoolean(boolean), setSomeInt(int), etc.
A builder pattern also allows you to set default values to some parameters, and user can conveniently override the default on some parameters. Providing methods to simulate this involves writing many overloads, which exacerbate the problem further.
Related questions
When would you use the Builder Pattern?
Nowadays, the most favored design pattern relies upon "fluent" builder. This way, you gain the genericity of the builder, with an understandable interface.
Implementing it is rather mundane, considering it's only a matter of well choosing your method names.
Good real world examples are all the FEST* libraries.

Categories