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();
Related
In code I found:
String age = null;
String place = null;
new Employee(firstParam, secondParam, null, null, age, place);
Class Employee is not our class, probably generated from wsdl file where parameters(age and place) are called alter, platz so someone tried to name null parameters to know which is which but is it good practice? Another problem is that age and place are translated while other two parameters are just null but beside of that is creating variable with null value just to pass it in next line to constructor is okey?
In my experience, when I have pregenerated class defs that expose contracts that don't suit my needs, I tend to abstract them behind a factory method (may not be a full fledged builder, but depends..) and expose overloaded contracts that help API users to simply pass whatever args are actually needed. Now as to whether naming variables as null is considered good practice or not, i think that is more subjective of your choice rather than an established pattern. But IMO, simply passing null would be cleaner than writing few extra lines only to pass method args.
There is no clear yes or no on this pattern. It is indeed commonly used in some areas.
It has the obvious advantage that it introduces the naming and by that making your code easier to read and maintain, which is always good and also reduces likelyness of bugs.
But it also has disadvantages. The biggest is probably that, for a reader, the intend of the variable may not be directly clear. Tripping into thinking that it might be used later on, thus polluting your variable scope. It might also just not be very convenient if you employ this pattern all the time.
Without going into much detail, there are some other solutions to it:
Most IDEs have a feature called parameter-hints
Some languages, like Kotlin have named-parameters
A builder pattern for the method-call would introduce explicit naming
Redesign the method to not allow optional null-parameters (some consider optional-parameters a bad practice)
Get rid of optional parameters by overloading your method
Apart from that, the question is probably too opinion-based for StackOverflow, especially since there is not really a strong opinion on this pattern in the community.
No, it is not a good practice to do something like this. Anyway, when you're declaring some fields like this String age; , age will be null by default. Instead I would suggest to look over some generic builder patterns (look at #SpaceTrucker 's answer please) instead of instantiating by constructors with more than 2 parameters.
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.
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
This is a terminological question, which makes it hard to ask!
Let me give an example. Suppose I am writing a symbolic-differentiation algorithm. I have an abstract class Exp that is a superclass of a bunch of expression types (sums, integrals, whatever). There is an abstract method derivative such that e.derivative() is supposed to be the derivative of the expression e. All the concrete subclasses of Exp (imagine a whole hierarchy here) implement a derivative method that captures knowledge of how to differentiate expressions of that type. A given method will typically compute the derivative of an expression by combining derivatives of subexpressions.
The details of the example are not important. The important thing is that all of these scattered methods can be considered pieces of one (recursive) algorithm. This is not true of all methods, but it's true of many of them (and the use of overloading to reuse the same method name for fundamentally different operations is considered a Bad Idea). The question is, what is the term for 'derivative,' considered as a single function? It's not a method; in another language it would be a function, and the various clauses (what to do with sums, what to do with integrals) would be in the same place. I don't care which approach or languaage is better, or whether that style can be used in Java. I just want to know what term to use for 'derivative' considered as a single function or procedure (the idea is not limited to functional programming, nor is recursion a key feature). When I tell someone what I did today, I'd like to say "I tried to implement a symbolic-differentation __, but every algorithm I thought of didn't work." What goes in the blank?
I assume the same issue comes up for other OO languages, but Java is the one I'm most familiar with. I'm so familiar with it that I'm pretty sure there is no standard term, but I thought I would ask our fine battery of experts here before jumping to that conclusion.
That sounds like "normal" subtype polymorphism. The subclasses/implementations do the work but the interface is defined in a base-type. This "scatter" method is in contrast to say, the Visitor Pattern ("as good as Java gets") or Pattern Matching (not in Java) or a big manky switch/if-else controller. I'm not sure I really would call it anything else as an aggregate.
Addendum: you may find Are Scala case-classes a failed experiment? a nice read. In particular, the comments which talk about "column" vs. "row" organization and the "difference of locality" each approach has:
...in OO, you divide by rows. Each row is a module, called a class. All the functions pertaining to that data variant are grouped together. This is a reasonable way of organizing things, and it's very common. The advantage is that's easy to add a data variant ... However the disadvantage is that it's hard to add new functions that vary by data type. You have to go through every class to add a new method.
I'm not sure if this is what you're looking for but I think I can answer this in terms of design pattern terminology. Your example sounds vaguely like the GoF Strategy Pattern. Here is an example of the Strategy Pattern implemented in Java.
On the contrary, I think that "method" is the standard term for this in the Java context.
A polymorphic function can be applied to values of different types. The function may be implemented by more than one Java method.
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.