Efficient way to implement HashMap<Boolean, Object>: Java - java

I have a function in which I have to send two states of an object:
void functionA(MyObject objStateOff, MyObject objStateOn){
}
And there would always be only two types states: on and off
But instead of having two parameters of the same type for this function, I was hoping to combine them. SO I was thinking of having a HashMap<Boolean, MyObject>.
But since this map would at most contain only two entries, it seems to be a waste of resources, as I am developing for Android.
So, is there a better way of passing these two objects, without having two either use a HashMap or having two parameters in the function signature?
Update: I want to see if any other method would basically improve the following:
Readability, performance(even though i think that won't change) and maintainability
Thanks.

I would create a custom class with two MyObject fields, and accessors for each. This has a couple big advantages based on your goals:
Readability: The accessor methods describe what each object does. states.get(true), what does that mean? states.getFooOnState(), that's pretty clearly getting me the state for when foo is on.
Maintainability: Adding new state is much easier, if you ever need to do that; you just add a new field to this class. Maybe you'll want a MyObject for when the foo's state is unknown/initializing, or maybe you want to add event handlers that get triggered when foo gets turned on or off. One disadvantage to your current approach is that these sorts of things will cascade through your signatures: functionA needs to add a new argument, which means functionB which calls functionA needs to now get that extra parameter (so it can pass it to functionA), which means functionC needs to get it, and so on.
One caveat to the readibility issue is that you'll be gaining readibility where you use these MyObjects, but not where you first set them up. There, you'll be creating a new MyObjectState (or whatever you name it), and the constructor will look just as generic as your functionA:
MyObjectState s = new MyObjectState(objStateOff, objStateOn);
You could address that by creating a builder for MyObjectState, but that'd probably be overkill.
Performance wise, you're not going to get better than what you already have. But a custom class is going to add fairly minimal overhead (in terms of extra memory, GC activity, etc) in the grand scheme of things.

There's always the Pair class (http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/Pair.html). Or you could pass a MyObject[] with two elements.

I think this question doesn't have the only correct answer. Personally I would leave the function with two parameters, because that's not too much really and names of this parameters can help me to avoid confusion like "which element of map/array is for on state?".

You can always use composition.
Create a class that contains two objects of MyObject type.
It may look overkill at first, but it's safer than array.
Hope this helps.

You could use a simple ArrayList.
ArrayList<MyObject> a = new ArrayList<MyObject>();
a.add(objStateOff); a.add(objStateOn);
void functionA(ArrayList<MyObject>) {
...
}
functionA(a);
Or a simple argument logic:
void functionA(int x) {
MyObject state;
if (x == 0) {
MyObject state = objStateOff; // Supposing they were defined somewhere before.
} else if (x == 1) {
MyObject state = objStateOn;
}
if (state != null) {
// Use MyObject state.
}
}
In this way, you don't need to specify any convention, you just set the off or on right on the argument (You can use a string or a boolean instead of an int (I mean, you could use "ON" or "OFF", literally)).

if your requirement is to have two object states, then why you dont have a field in MyObject like boolean stateOfObject. Then in functionA, you can check the state and do the required logic. Why complicate by sending two objects when you have only two states? May be you have to mention the context where you are using it and why you need two objects to be passed to the functions when the object can be in only one state.
May be you could use enums:
public enum StateOfObject {
ON(10,2),
OFF(15,5);
private final int length;
private final int speed;
StateOfObject(int length, int speed) {
this.length = length;
this.speed = speed;
}
public MyObject getObject() {
MyObject myObj = new MyObject();
myObj.setLength(this.length);
myObj.setSpeed(this.speed);
return myObj;
}
}
Use it like this:
MyObject onObject = StateOfObject.ON.getObject();
System.out.print("Length: " + onObject.getLength() +
" Speed: " + onObject.getSpeed());

Related

Side effects in Java methods

This might be a trivial question, but I need some clarification...
There is a book called Clean Code that says that our methods should be small, preferably up to 5-10 lines long. In order to achieve that we need to split our methods into smaller ones.
For instance, we may have someMethod() shown below. Let's say, modification of 'Example' takes 5 lines and I decide to move it into a separate method, modify 'Example' there and return it back to someMethod(). By doing this, someMethod() becomes smaller and easier to read. That's good, but there is a thing called "side effects" which says that we shouldn't pass an object to another method and modify it there. At least, I was told that it's a bad idea ) But I haven't seen anything prohibiting me from doing so in Clean Code.
public Example someMethod() {
// ... different lines here
Example example = new Example();
example = doSomethingHere(example, param1, param2, ...);
// ... different lines here
return example;
}
private Example doSomethingHere(Example example, 'some additional params here') {
// ... modify example's fields here ...
return example;
}
So, am I allowed to split the methods this way or such a side effect is prohibited and instead I should deal with a rather long-line method that definitely breaks Clean Code's rules talking about short methods?
UPDATED (more specific name for the sub-method)
public Example someMethod() {
// ... different lines here
Example example = new Example();
example = setExampleFields(example, param1, param2, ...);
// ... different lines here
return example;
}
private Example setExampleFields(Example example, 'some additional params here') {
// ... modify example's fields here ...
return example;
}
As JB Nizet commented, it's not actually a side effect if it's the only effect, so any blanket statement that "all side effects are bad" doesn't apply here.
Still, the main question stands: Is this (side) effect okay?
Talking about the principles first, side effects are, in general, dangerous for two reasons:
they make concurrency more difficult
they obscure/hide information
In your example, there is some information that is hidden. You could call this a potential side effect, and it can be exposed with a question: "Does this doSomethingHere method create a new object or modify the one I pass in?"
The answer is important, and even more so if it's a public method.
The answer should be trivial to find by reading the doSomethingHere method, especially if you're keeping your methods 'clean', but the information is nonetheless hidden/obscured.
In this specific case, I would make doSomethingHere return void. That way there's no potential for people to think that you've created a new object.
This is just a personal approach - I'm sure that plenty of developers say you should return the object you modify.
Alternatively, you can pick a 'good' method name. "modifyExampleInPlace" or "changeSomeFieldsInPlace" are pretty safe names for your specific example, imo.
we shouldn't pass an object to another method and modify it there.
Who says that? That is actually a good practice in order to split your function in a way that forms a "recipe" and have specific functions that know exactly how to populate your object properly.
What is not recommended (and probably the source where you got your recommendation misunderstood this rule) is defining a public API and modify the arguments. Users appreciate not having their arguments modified as it leads to less surprises. An example of that is passing arrays as arguments to methods.
When you define an object and pass it to an other method, method itself can modify the content of the object therein which may be unwanted in some cases. This is because you pass the reference(shallow copy) of the object to that method and method can modify that object.For example when you pass an Array, Arrays are objects, to a method, method can change the content of the Array which may not be what the caller method expects.
public static void main(String[] args){
int[] arr= {1,2,3,4};
y(arr);
//After the method arr is changed
}
public void y(int[] comingArray){
comingArray[0] = 10;
}
To make sure the values of Array cannot be changed, deep copy of the Array should be sent to method which is another story
However this is not the case when you use primite types(int, float etc.)
public static void main(String[] args){
int a= 1
y(a);
//After the method a is not changed
}
public void y(int comingInt){
comingInt = 5;
}
Due to the nature of the Objects, you should be carefulTo learn more about shallow copy and deep copy https://www.cs.utexas.edu/~scottm/cs307/handouts/deepCopying.htm

Best strategies when calling a method that should modify more than one variable

I am pretty new to Java, I have to convert C/C++ code to Java and I am running into obstacles. Because of the way variables are passed to the methods, their modification in the method is not straightforward, and I have no idea what is the most reasonable approach to take. Sorry for the pseudocode examples, I hope they will clearly explain what I am talking about without delving into unnecessary details.
I need something that would be equivalent to C
ModifyMyString(type1 &t1,type2 &t2);
(return type doesn't matter, it can be void) as I need the function to modify both t1 and t2.
I can easily modify one of the variables, say t1, by declaring in Java
type1 modifyMyString(type1 t1, type2 t2);
and assigning the returned value to
t1 = modifyMyString(t1,t2);
but it is only half of a success, as the new value of t2 is lost.
I can declare new class
class JustToPassTwoVariables {
type1 t1;
type2 t2;
JustToPassTwoVariables(type1 tt1, type2 tt2) { t1 = tt1; t2 = tt2; }
}
and do something like
JustToPassTwoVariables jtptv = modifyMyString(JustToPassTwoVariables(t1,t2));
but I feel like it is clumsy and makes the code unreadable.
In desperation I could also resign the idea of using a modifyMyString method, and repeat all the code locally in each place I would call modifyMyString - but it makes even less sense than using JustToPassTwoVariables class.
Is there a correct (or at least widely used, accepted as a standard, whatever) strategy to code such things in Java?
The recommended way in java is (in some people's opinion the clumsy way) to create a class containing the two fields and return an instance of that class.
I feel that it is much less clumsy if you stop and think about what the method is actually doing, and taking care to properly name both the method and the class returning the two values.
The simple answer is no. This sort of feature is not allowed in Java.
The correct way to do it is to pass in the object to be modified not the two variables. After all in virtually all cases those variables are already wrapped in an object, in cases where they aren't they often easily can be.
Either split the function into two functions and call it once for each variable, or wrap the variables into an object and pass that object into the function.
Don't forget Java allows Inner Classes which makes this sort of thing less painful.
You can't return two values from a method in java. The way is to return an object and set all the values in it. i.e. In your case, you need to create a value container class i.e. say Result class that will have two fields storing the type1 and type2 value in it. The return type of the method would be of value container object type i.e. say Result instance with two fields in it - type1 and type2
Example :
Result result = modifyMyString(t1,t2);
result.getT1(); //gets t1 value
result.getT2(); // gets t2 value
Please learn about setters and getters in Java to work on the class or object level fields
In Java if you want to do this you would generally make type1 and type2 into object whose values can be modified. The method can then modify the values of the parameters to get the desired effect. For example :
void myMethod(type1 arg0, type2 arg1) {
arg0.setValue(newValue0);
arg1.setValue(newValue1);
}
If type1 and/or type2 do not have any way of changing their values (e.g. they are of type String) then you would either make a wrapper class for each of them e.g.
class Type1Wrapper {
private type1 type1;
type1 getType1() {
return type1;
}
void setType1(type1 newType1) {
type1 = newType1;
}
}
or you would make a wrapper for both of the types simultaneously like you have in your question (although the method return type will be void and the method will modify your wrapper's values)
There are several methods to modify a group of objects "of the same type/class". The simplest of them being, add them to a "list" pass that list to your modification function, do whatever modifications/additions/deletions etc.. The list reference will be automatically available outside with the "changes made in the called function" .
So, you can do
List<String> l = new ArrayList<String>();
l.add("Hello");
l.add("world");
ModifyMyString(l);
// here also l = "hello" , "world" , "added"
public void ModifyMyString(List l)
{
l.add("added"); // now l = "hello" , "world" , "added"
}
Java is an OO language so to get the best out of it you should look to an OO solution. It's hard to give you a definite solution with this abstract example but this is how I would approach this.
You mention that t1 and t2 both need to be updated by this modify procedure/method. Also that they need to be updated at the same time, if they were unrelated then you could just call modify on each string in turn. If these two strings are related like this then it's likely they belong to the same type.
So we need a class containing type 1 and type 2.
public class TypeContainer
{
private String type1;
private String type2;
.. getters and setters
}
Obviously you'll want a better class name.
You suggest something similar yourself but call it JustToPassTwoVariables. This is missing the point of OO. You could write a simple wrapper like this and pass it to some other method to modify the values but a more OO approach would be to add the modify method to this class itself.
...
public void modfiy(String val1, String val2)
{
type1 = val1;
type2 = val2;
}
...
I'm not sure what your modify is trying to do but in this case I would probably have these as two separate setter methods. This is quite an abstract example!
Basically I would avoid having the modify method in some other unrelated class. You should look to group common related attributes into classes and then write methods in those classes for any actions you need to take (such as modify).
Trying to convert a procedural C program into an OO Java program sounds like a PITA. It's a complete paradigm shift. Having said that I have seen automated conversions which while technically Java are still very procedural. Not very pretty and hard to maintain but was done for political reasons.
Java discourages this strategy beacause in-variable should be immutable, but if you have to migrate from C/C++/C# and you have a lot of "void function with parameters passed as in/out", you can create a Custom "Reference" class like this and you can incapsulate the original object.
public class CustomRef {
public Object internal;
public CustomRef(Object object) {
this.internal=object;
}
}
then when you call
CustomRef ref1= new CustomRef(myParams1);
CustomRef ref2= new CustomRef(myParams2);
myFunction(ref1, ref2);
myParams1 = ref1.internal;
myParams2 = ref2.internal;
the function is
void myFunction(CustomRef ref1, CustomRef ref2) {
Object param1 = ref1.internal
// a lot of code
ref1.internal = param1;
}
really discouraged way ... such as using ArrayList, arrays [] to "pass by reference".
NOTE: this way is a waste of resource; CustomRef instance should be reused through object pool (another discouraged way).
I would use a StringBuffer. You can initialize it with a String and convert it back to a String

Is there a way in Java to pass multiple parameter pairs to a method?

Pretty new to Java
I would like to be able to use a method in following sort of way;
class PairedData {
String label;
Object val:
}
public void myMethod(String tablename, PairedData ... pD) {
/*
insert a record into a table -tablename with the various fields being
populated according to the information provided by the list of
PairedData objects
*/
}
myMethod("firststring",{"field1",Date1},{"field2",12},{"field3","aString"});
I realise the syntax is not valid but I hope it gives the gist of what I would like to do.
What I am trying to do is to directly pass the data rather than populate the instances of the class and then pass those. Is that possible or am I just trying to break a whole lot of OOPs rules?
No, what you're trying to do really isn't possible. It looks to me like it would be much better to pass instances of your class to the method as opposed to doing something convoluted with arrays like that. Another answer suggested using an Object[] varargs parameter - that's probably the closest you'll get to achieving something like what you show in your example. Another alternative (and I think a better one) would be
public void myMethod(String tablename, String[] labels, Object[] vals) {
You could instantiate your class for each labels[i] and vals[i] (pairing them up) in those arrays. In other words, in your method you could have something like
pD = new PairedData[labels.length];
for (i = 0; i < labels.length; i++)
pD[i] = new PairedData(labels[i], vals[i]); // assuming you
// added this
// constructor
The method call example that you included would then be converted to
myMethod("firststring", new String[]{"field1", "field2", "field3"},
new Object[]{date1, 12, "aString"});
You can do this by using arrays of Object:
public void myMethod(String tableName, Object[] ...pairs)
and invoke this method in a such style:
myMethod("someTable", new Object[] {"field1", date1}, new Object[] {"field2", date2});
usually...
you would make a class that has variable in it for all the parameters.
then you would build an instance of that class and populate the values.
then you could use that class instance to pass those around.
if you want a whole bunch... then make a Collection (Map, HashMap, List etc.) and pass that.
Seems to be a good case for a future language extension if you ask me. But by slightly changing the way you call your method we should be able to get close ...
myMethod("someTable",
new PairedData("field1", date1),
new PairedData("field2", date2)
);
It’s more type-work, but it is probably the safest as it is typesafe and not error prone to matching pairs.
You would also be required to write your constructor for ‘PairedData(String label, Object val)‘ for which I advise to write multiple overloaded versions one for each type of val you plan to store.

How to create IN OUT or OUT parameters in Java

In PL/SQL (or many other languages), I can have IN OUT or OUT parameters, which are returned from a procedure. How can I achieve a similar thing in Java?
I know this trick:
public void method(String in, String[] inOut, String[] inOut2) {
inOut[0] = in;
}
Where the in parameter represents an IN parameter and the inOut parameter can hold a return value. The convention would be that String[] inOut is an array of inOut.length == 1.
That's kind of clumsy.
EDIT Feedback to answers: Other tricks include:
holder/wrapper classes, but I don't want to introduce any new types, callbacks, etc.
return values: I'd like a general solution. I.e. one with several IN OUT parameters involved.
wrapper for IN OUT parameter as a return value: That's a viable option, but still not so nice, because that wrapper would have to be generated somehow
Does anyone know a better way to achieve this generally? The reason I need a general solution is because I want to generate convenience source code from PL/SQL in a database schema.
My question would be: Why doesn't method return something? Rather than setting an in/out argument?
But assuming you absolutely, positively must have an in/out argument, which is a whole different question, then the array trick is fine. Alternately, it's not less clumsy, but the other way is to pass in an object reference:
public class Foo {
private String value;
public Foo(String v) {
this.value = v;
}
public String getValue() {
return this.value;
}
public void setValue(String v) {
this.value = v;
}
}
// ....
public void method(String in, Foo inOut) {
inOut.setValue(in);
}
(Or, of course, just make value public.) See? I said it wasn't less clumsy.
But I'd ask again: Can't method return something? And if it needs to return multiple things, can't it return an object instance with properties for those things?
Off-topic: This is one of the areas where I really like the C# approach. One of the arguments against in/out arguments is that they're unclear at the point where you're calling the function. So C# makes you make it clear, by specifying the keyword both at the declaration of the function and when calling it. In the absense of that kind of syntactic help, I'd avoid "simulating" in/out arguments.
Java copies anything you pass as an argument. If you pass a primitive, inside method you have copy of that primitive, and no modifications will affect the actual variable outside method. If you pass object, you pass copy of reference, which actually references to the original object. This is the way how you can propagate modifications to the context of something that called the method - by modifying the state of the object that the reference is 'pointing' to. See more on this: Does Java Pass by Value or by Reference?
There's no direct way. Other technique include:
Passing a holder object (a bit like your 1-ary array)
Using, e.g., an AtomicInteger
Passing a more useful object from a business perspective that happens to be mutable
A callback to a custom interface for receiving the result
If you think about it, the array trick is not dissimilar to passing a T* in C/C++

Best practice for passing many arguments to method?

Occasionally , we have to write methods that receive many many arguments , for example :
public void doSomething(Object objA , Object objectB ,Date date1 ,Date date2 ,String str1 ,String str2 )
{
}
When I encounter this kind of problem , I often encapsulate arguments into a map.
Map<Object,Object> params = new HashMap<Object,Object>();
params.put("objA",ObjA) ;
......
public void doSomething(Map<Object,Object> params)
{
// extracting params
Object objA = (Object)params.get("objA");
......
}
This is not a good practice , encapsulate params into a map is totally a waste of efficiency.
The good thing is , the clean signature , easy to add other params with fewest modification .
what's the best practice for this kind of problem ?
In Effective Java, Chapter 7 (Methods), Item 40 (Design method signatures carefully), Bloch writes:
There are three techniques for shortening overly long parameter lists:
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.
For more details, I encourage you to buy the book, it's really worth it.
Using a map with magical String keys is a bad idea. You lose any compile time checking, and it's really unclear what the required parameters are. You'd need to write very complete documentation to make up for it. Will you remember in a few weeks what those Strings are without looking at the code? What if you made a typo? Use the wrong type? You won't find out until you run the code.
Instead use a model. Make a class which will be a container for all those parameters. That way you keep the type safety of Java. You can also pass that object around to other methods, put it in collections, etc.
Of course if the set of parameters isn't used elsewhere or passed around, a dedicated model may be overkill. There's a balance to be struck, so use common sense.
If you have many optional parameters you can create fluent API: replace single method with the chain of methods
exportWithParams().datesBetween(date1,date2)
.format("xml")
.columns("id","name","phone")
.table("angry_robots")
.invoke();
Using static import you can create inner fluent APIs:
... .datesBetween(from(date1).to(date2)) ...
It's called "Introduce Parameter Object". If you find yourself passing same parameter list on several places, just create a class which holds them all.
XXXParameter param = new XXXParameter(objA, objB, date1, date2, str1, str2);
// ...
doSomething(param);
Even if you don't find yourself passing same parameter list so often, that easy refactoring will still improve your code readability, which is always good. If you look at your code 3 months later, it will be easier to comprehend when you need to fix a bug or add a feature.
It's a general philosophy of course, and since you haven't provided any details, I cannot give you more detailed advice either. :-)
First, I'd try to refactor the method. If it's using that many parameters it may be too long any way. Breaking it down would both improve the code and potentially reduce the number of parameters to each method. You might also be able to refactor the entire operation to its own class. Second, I'd look for other instances where I'm using the same (or superset) of the same parameter list. If you have multiple instances, then it likely signals that these properties belong together. In that case, create a class to hold the parameters and use it. Lastly, I'd evaluate whether the number of parameters makes it worth creating a map object to improve code readability. I think this is a personal call -- there is pain each way with this solution and where the trade-off point is may differ. For six parameters I probably wouldn't do it. For 10 I probably would (if none of the other methods worked first).
This is often a problem when constructing objects.
In that case use builder object pattern, it works well if you have big list of parameters and not always need all of them.
You can also adapt it to method invocation.
It also increases readability a lot.
public class BigObject
{
// public getters
// private setters
public static class Buider
{
private A f1;
private B f2;
private C f3;
private D f4;
private E f5;
public Buider setField1(A f1) { this.f1 = f1; return this; }
public Buider setField2(B f2) { this.f2 = f2; return this; }
public Buider setField3(C f3) { this.f3 = f3; return this; }
public Buider setField4(D f4) { this.f4 = f4; return this; }
public Buider setField5(E f5) { this.f5 = f5; return this; }
public BigObject build()
{
BigObject result = new BigObject();
result.setField1(f1);
result.setField2(f2);
result.setField3(f3);
result.setField4(f4);
result.setField5(f5);
return result;
}
}
}
// Usage:
BigObject boo = new BigObject.Builder()
.setField1(/* whatever */)
.setField2(/* whatever */)
.setField3(/* whatever */)
.setField4(/* whatever */)
.setField5(/* whatever */)
.build();
You can also put verification logic into Builder set..() and build() methods.
There is a pattern called as Parameter object.
Idea is to use one object in place of all the parameters. Now even if you need to add parameters later, you just need to add it to the object. The method interface remains same.
You could create a class to hold that data. Needs to be meaningful enough though, but much better than using a map (OMG).
Code Complete* suggests a couple of things:
"Limit the number of a routine's parameters to about seven. Seven is a magic number for people's comprehension" (p 108).
"Put parameters in input-modify-output order ... If several routines use similar parameters, put the similar parameters in a consistent order" (p 105).
Put status or error variables last.
As tvanfosson mentioned, pass only the parts of a structured variables ( objects) that the routine needs. That said, if you're using most of the structured variable in the function, then just pass the whole structure, but be aware that this promotes coupling to some degree.
* First Edition, I know I should update. Also, it's likely that some of this advice may have changed since the second edition was written when OOP was beginning to become more popular.
Using a Map is a simple way to clean the call signature but then you have another problem. You need to look inside the method's body to see what the method expects in that Map, what are the key names or what types the values have.
A cleaner way would be to group all parameters in an object bean but that still does not fix the problem entirely.
What you have here is a design issue. With more than 7 parameters to a method you will start to have problems remembering what they represent and what order they have. From here you will get lots of bugs just by calling the method in wrong parameter order.
You need a better design of the app not a best practice to send lots of parameters.
Good practice would be to refactor. What about these objects means that they should be passed in to this method? Should they be encapsulated into a single object?
Create a bean class, and set the all parameters (setter method) and pass this bean object to the method.
Look at your code, and see why all those parameters are passed in. Sometimes it is possible to refactor the method itself.
Using a map leaves your method vulnerable. What if somebody using your method misspells a parameter name, or posts a string where your method expects a UDT?
Define a Transfer Object . It'll provide you with type-checking at the very least; it may even be possible for you to perform some validation at the point of use instead of within your method.
I would say stick with the way you did it before.
The number of parameters in your example is not a lot, but the alternatives are much more horrible.
Map - There's the efficiency thing that you mentioned, but the bigger problem here are:
Callers don't know what to send you without referring to something
else... Do you have javadocs which states exactly what keys and
values are used? If you do (which is great), then having lots of parameters
isn't a problem either.
It becomes very difficult to accept different argument types. You
can either restrict input parameters to a single type, or use
Map<String, Object> and cast all the values. Both options are
horrible most of the time.
Wrapper objects - this just moves the problem since you need to fill the wrapper object in the first place - instead of directly to your method, it will be to the constructor of the parameter object.
To determine whether moving the problem is appropriate or not depends on the reuse of said object. For instance:
Would not use it: It would only be used once on the first call, so a lot of additional code to deal with 1 line...?
{
AnObject h = obj.callMyMethod(a, b, c, d, e, f, g);
SomeObject i = obj2.callAnotherMethod(a, b, c, h);
FinalResult j = obj3.callAFinalMethod(c, e, f, h, i);
}
May use it: Here, it can do a bit more. First, it can factor the parameters for 3 method calls. it can also perform 2 other lines in itself... so it becomes a state variable in a sense...
{
AnObject h = obj.callMyMethod(a, b, c, d, e, f, g);
e = h.resultOfSomeTransformation();
SomeObject i = obj2.callAnotherMethod(a, b, c, d, e, f, g);
f = i.somethingElse();
FinalResult j = obj3.callAFinalMethod(a, b, c, d, e, f, g, h, i);
}
Builder pattern - this is an anti-pattern in my view. The most desirable error handling mechanism is to detect earlier, not later; but with the builder pattern, calls with missing (programmer did not think to include it) mandatory parameters are moved from compile time to run time. Of course if the programmer intentionally put null or such in the slot, that'll be runtime, but still catching some errors earlier is a much bigger advantage to catering for programmers who refuse to look at the parameter names of the method they are calling.
I find it only appropriate when dealing with large number of optional parameters, and even then, the benefit is marginal at best. I am very much against the builder "pattern".
The other thing people forget to consider is the role of the IDE in all this.
When methods have parameters, IDEs generate most of the code for you, and you have the red lines reminding you what you need to supply/set. When using option 3... you lose this completely. It's now up to the programmer to get it right, and there's no cues during coding and compile time... the programmer must test it to find out.
Furthermore, options 2 and 3, if adopted wide spread unnecessarily, have long term negative implications in terms of maintenance due to the large amount of duplicate code it generates. The more code there is, the more there is to maintain, the more time and money is spent to maintain it.
This is often an indication that your class holds more than one responsibility (i.e., your class does TOO much).
See The Single Responsibility Principle
for further details.
If you are passing too many parameters then try to refactor the method. Maybe it is doing a lot of things that it is not suppose to do. If that is not the case then try substituting the parameters with a single class. This way you can encapsulate everything in a single class instance and pass the instance around and not the parameters.
... and Bob's your uncle: No-hassle fancy-pants APIs for object creation!
https://projectlombok.org/features/Builder

Categories

Resources