design issue about multiple parameters in a function - java

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

Related

Is there a convention or correct order for chaining constructors?

Ive been thinking about this and I've seen different examples on this. Usually I would chain constructors in a upward manner. So if I have 4 different constructors, starting with a default constructor, who calls the constructor where we need to pass in one argument, who calls the constructor where we need 2 arguments to pass in and so on, so we have usable objects, where all the fields hold data.
Is there a different approach to chaining constructor because I couldn't think of another case ? Why would I want my constructor, where I need 3 arguments to pass in, call my constructor where I only need to pass in 2 arguments ?
The Builder pattern works for this scenario. A rough demo could look like this:
Dog dog = new DogBuilder().setHeight(10).setWeight(40).setColor(Color.BROWN).build();
Each set method returns a reference to the DogBuilder instance, with that property set. Calling .build() calls a private/package private constructor with all values set.
This is a good article for reference:
https://dzone.com/articles/design-patterns-the-builder-pattern
I think "common sense" best practices are:
Minimize the number of constructors your class offers (for example by relying on the Builder pattern)
Yes, "upward chaining" where the n arg constructor calls an n+1 constructor (and provides a default argument) is probably the more common (and more useful) style.
But as the last sentence indicates: to a certain degree, this is about "personal" style. Or whatever "style" applies. When your team is used to do things in a different way, and you have hundreds of existing classes following that "special style", then you allow that "team internal" preference to guide your actions.

Passing whole object vs passing object's property

I'm thinking about the solution for my application. Here's the situation: I have a class with a method that takes ObjectA as an input parameter and calls several small methods. Each one of these methods needs some parts of the ObjectA (they don't overlap, i.e. method1() needs ObjectA.field1 and ObjectA.field2, method2() needs ObjectA.field3 and so on...)
Given the general good code practices and performance, is it better to pass ObjectA to each one of these methods so they can extract the value they need on their own or is it better just pass them values? I mean:
method1(ObjectA);
method2(ObjectA);
or
method1(Object1.getField1(), ObjectA.getField2());
method2(ObjectA.getField3());
Keep in mind, with your code, you're not actually passing ObjectA. Namely, you're passing the reference type to ObjectA, so on a performance note the difference between passing a String object reference and a ObjectA object reference would be negligible.
The way I would write it
I would pass the whole object, if the method is pertinent to the class. My reasoning for this is to split up class knowledge as much as possible. What I mean by this is the following.
public void doSomethingRelatedToTheClass(String param)
{
// Do something with param.
}
My first criticism here is that this method assumes that the input is the correct field. My second, is that now, the class calling this code needs to know a little bit more about this method, because it has to call it like this:
doSomethingRelatedToTheClass(myObject.getValue());
And what this means is, if you find that another member of ObjectA works better inside this method, or you want to access other members of ObjectA, and you change doSomething() to reflect this change, you also need to change the method call, to:
doSomethingRelatedToTheClass(myObject.getOtherValue(), myObject.getValue());
So by passing in the whole object, you abstract that detail away, and the method can handle it; namely:
doSomethingRelatedToTheClass(myObject); // Doesn't need to know what you do with it.
public void doSomethingRelatedToTheClass(ObjectA object)
{
String val = object.getValue();
String otherVal = object.getOtherValue();
}
When a change to one class, results in a change in other classes, this is an Anti-pattern called Shotgun Surgery.
Edit
I've had chance to review my answer here and I've amended my original answer slightly because I believe it isn't the best solution for all situations. As above, if a method is related to a class specifically, then the instantiation of that class (or more preferably, its superclass or implemented interface[s]) should be the parameter.
The time this is not the case is when the functionality can be generic. An example of a generic function might be:
public String[] findNouns(String sentence);
In this case, finding the nouns in a sentence might be appropriate for lots of use cases, and not just the use cases that you have defined. As such, passing in the value is the only sensible approach because otherwise, you couple two pieces of logic together that have no direct relationship. The finding of nouns and the arbitrary object you have defined.
In Summary
If the method is logic that is related to the object, pass in the object
If the method has nothing to do with the object, and the object is just using it as a utility function, then pass in the value and name the function generically.
Let's examine a scenario. Now this may or may not be your scenario but it illustrates a point.
Lets say field1 and field2 in your case are two integers and method1 sums them and returns the result.
If you pass in the objects then that method can only ever sum those two fields. The method is also now strongly coupled with those objects.
On the other hand, if you pass in only the fields, the two integers in this case your method becomes more generic. You can now sum any 2 arbitrary integers regardless of which objects they are on.
In general though, always expose as little of your objects to other methods and classes. This promotes loose coupling.
Exceptions
AS maaartinus points out if for example field1 and field2 were Points and method1 calculated the distance between those two points, then I would have to agree that passing two Points would be better than passing 2 xy integer pairs (4 parameters)
Hope this helps
I'd say, it depends. A method may be clearer and more general if it operates on the arguments rather than requiring a whole object. Sometimes you have the arguments ready (e.g., x and y) and would have to aggregate them first into e.g. a Point in order to be able to call the method. Sometimes you have a different unrelated object (e.g., some ImmutablePoint, obviously not extending java.awt.Point) and would have to extract the coordinates and create an object to pass.
Usually, if the passed object is the proper abstraction, then passing it as a whole is the way to go. It's not a performance question, it's about readability and maintainability. See also the Law of Demeter which may lead to looser dependency on the passed object.
As others have said, it depends but in my experience passing entire objects makes code harder to read and maintain.
Lets consider this method getUserDetails(User user) which relies on few methods like getUserAddress(User user) getUserFamilyInfo(User user) etc which may further connect to different data sources to fetch the information.
There is no easy way to know that getUserFamilyInfo needs only userId or it needs userId and lastName or something else from user when entire object is passed. It makes it hard to understand dependencies among different services and do any refactoring.
I prefer to pass individual arguments if count is less than 3 or create a dto if handful of properties are required from a vary large object.

Method parameters with same type

I am wondering what is the best practices to write method that takes at least three parameters of the same type. The problem is that you can mix up parameters when using such method. For example
method(int userId, int productId, int weight, int price)
The only solution I see is to use some holder class(maybe with builder pattern used) and passing it as method parameter.
The best practice is to use clear parameter names (and possibly clarifying them in the Javadoc). If there are too many parameters, a separate object is better.
If the caller of the method can't distinguish between different (well named) parameters, then maybe he shouldn't be calling the method in the first place.
Depending on your exact situation, Introduce Parameter Object may be a relevant refactoring option.
More explanations here, from which I quote the below (emphasis mine):
Often you see a particular group of parameters that tend to be passed
together. Several methods may use this group, either on one class or
in several classes. Such a group of classes is a data clump and can be
replaced with an object that carries all of this data. It is
worthwhile to turn these parameters into objects just to group the
data together. This refactoring is useful because it reduces the size
of the parameter lists, and long parameter lists are hard to
understand. The defined accessors on the new object also make the code
more consistent, which again makes it easier to understand and modify.
For me i think the best practice is to use Data class (java bean ) and but your parameter there with a will named standard and then you use this data class object as parameter.
The disadvantage of this approach is that you are increasing coupling in you system .
You can use variable arguments concept in this case.
method(int… ids){
userid = ids[0];
productid = ids[1];
}

Best Practice - HashMap instead of list of parameters, good idea ?

Hi Stackoverflow community,
I am working on some code where a list of optional criterias criterias is submitted to my dao.
Method signature contains the list of +/- 10 parameters, which I really don't like and want to reformat.
Plus I would like to avoid having to refactor all method signatures from different layers just because I add/remove a criteria
List searchParams(String name, Long countryCode, ...){
...
}
would become
List searchParams(HashMap<String,Object> map) {
BeanUtils.populate(this,map);
...
}
I am a bit worried that this happen to because kind of a bad practice, because I give up control of what is passed in the map to give me that flexibility ? So my question is if I am on the right path proceeding that way?
When I encounter situations like this, I tend to create a Params class, and pass that around. The benefits are that:
unlike when using a Map, you can have meaningful getters/settings, proper validation etc;
it's type-safe and self-describing (meaning it's easy to find out the available parameters and their types).
you can add new parameters without having to refactor any intermediate layers.
You could define a new class to hold/handle your set of parameters, so you get a bit more control than a HashMap would give you. Annoying to write, or at least tedious, but seems like a better balance between flexibility & control.
You could look at your parameters and see if you can wrap them as a logical group into an object. For example a name an a country code could be a person object
public Person {
private String name;
private String countryCode;
}
Then you will just be passing this object down and can use getters to get the data out which should be easier to read and maintain than needing to know all the keys for the HashMap on multiple layers.
The only case where using a map is appropriate is when you are designing a factory, and you need to pass different kinds of parameters to different classes being created. In all other cases, a solution with a specialized parameter info class would be preferred.
For an example of where passing a map is appropriate, look at the DriverManager.getConnection method: this method needs to pass parameters to constructors of driver-specific implementations of the Connection being created, so it wraps a map into Properties, and lets the user pass it through to the driver-specific connection. Note that DriverManager does not have another solution that would be future-proof.
I would strongly discourage using a map in all other cases: the added flexibility shifts error detection from compile-time to run-time, which has a strong potential of multiplying your headache beyond belief.

Best way to name methods that returns list of objects

I have a class named ActivityLog. This class holds a list of ActivityRecords. I want to return a list of ActivityRecords by these criterias: Environment and Condition. Should the method name include the "criteria"? See example:
activityLog.allRecords();
activityLog.allRecordsBy(Environment environment);
activityLog.allRecordsBy(Condition condition);
activityLog.allRecordsBy(Condition condition, Environment environment);
or
activityLog.allRecordsByEnvironment(Environment environment);
activityLog.allRecordsByCondtion(Condition condition);
I probably think the first is better because you will read the method name and you will understand from the parameter what it does, but I may be wrong? Which is the best, or are there even better alternatives?
I could have named the methods records(), recordsBy etc. too, but I want to have a consitency through my API where you always start writing all for lists of objects so you get help from for example Intelli Sense.
I like putting the criteria in the actual method name. So I would use:
activityLog.allRecordsByEnvironment(Environment environment);
To me proper method naming expresses a small summary of what the method does. Since the parameters are included in the method signature I would not consider the parameters to be part of the actual name, therefore not placing the criteria in the name gives the user of an api incomplete information about the methods functionality. (IMO)
I applaud your effort to practice self documenting code, great practice.
I like the overloaded variant (your first example), because it communicates that the methods are all related and provide largely the same functionality, aka, you are returning records, filtered by some criteria. You will see examples of this in many open source libraries and even the SDK itself.
I'd treat it the same as static factory methods, which are named constructors. And there not only parameter says what this method does, its name itself does it. So I'd choose 2nd option.
#Bob, about names being too long - even if you would put 2 parameters into its name, it still would be ok for me. Anyway you should avoid having methods with more than 3 parameters. Following this rule will prevent your methods' names from being enormous long.
I would take the first one.
If these methods are doing the same thing or providing the same functionality then they should have the same name. But be aware of Effective Java Item 41 and 42. You've to ensure that at least one corresponding param of overloaded method are having radically different types.
The 2nd approach becomes ugly very fast with every param added. I see this in often in Broker classes at work. There are people writing methods like findByFirstnameAndLastnameAndBirthdayOrderByUgliness(blablub). No comment.
Methods in OOP represent behavior, so I would name all of them getRecords() and made them overloaded.
In my opinion, specifying criteria in the name of method looks like naming heirarchy classes like this
Car -> BMW_Car -> X5_BMW_Car

Categories