How should I design the method signature for the following scenario - java

If you have a method where the input parameter might be the output.
Let's say that we have a save method that generates an autogenerated id that the client might be interested to use after the call to save().
Person
id (autogenerated)
name
... (other fields)
Should you design the method signature like this:
1.
public void save(Person person);
The client call:
personService.save(person);
System.out.println(person.getId());
2.
public Person save(Person person);
The client call:
person = personService.save(person);
System.out.println(person.getId());
We know that in a method call that receives an object the reference to that object is passed so any changes made to the object will be perceived by others as long as they have the same reference. But in the case of remote calls serialization/deserialization occurs so my object reference is a different reference from the remote service object. So even though changes are made there the client won't notice the difference.
At this time I know that the method is not going to be a remote call so I could design it using the first signature. But what if in the future this changes and needs to be called as a remote call.
So my question is:
Should I design my API thinking that the API might be called in the future as a remote call and don't use the object parameter as a way to return a value to the client (2) or should I design my API according to my actual situation which the sevice is not remote (1)?
Thank you

It's OK to do both; have save() return the new ID and have a getId() method. Returning a value from a "setter" (a method that changes state) has lots of precedents - the java Collections API does it all the time, eg Map.remove(Object) returns a boolean.
Fluent Interface
There's another pattern you might want to consider, the Fluent Interface pattern. With a fluent API, you return the object (ie this) from every method you would otherwise return void. This lets the caller "chain up" method calls. With a fluent interface, your code would look like this:
public Person save() {
// do your save stuff
return this;
}
If you want the ID after a save, you'd code this:
save().getId();
Simple! This pattern has been used in lots of existing java code too, notably hibernate as in this java fluent code example
I would recommend using fluent, if nothing else to get the practice using it

Why not do both? Use the second signature, modify person locally, and for the time being, just return a reference to that same person. This way, changing it in the future for whatever needs arise won't change the API, and current users can still use your first approach.
That being said, in general, I am uncomfortable with methods that change their parameters unless that is their sole purpose and they are named and documented to indicate this. From the standpoint of "what is the method doing, and what new information do I get from it," I would probably opt for a signature like:
public ID save(Person);

I would recommend using the first approach since objects are seldom used in isolation. The Person object is usually referenced by other entities such as Employee. If you create a new instance, you're invalidating the whole object graph and believe me, you don't want to mess around with deep copying.
As for the possibility of future RPC's, whatever you'll be using to accomplish this, it will most likely be able to update the ID field after the operation commits.
#CPerkins - Objects are passed by "reference value" to be absolutely correct ;)

Related

How does one know if a certain method will change the state of a java object?

Some methods are mutator methods, usually they return nothing, the so-called setters. Others, like the .plusDays() method of the LocalDate class, return a full, instantiated object of type Localdate, so if you want to change the object, you need to point your existing object variable to the newly created one.
Is there a way to know beforehand if a method will be a mutator, or work like the before-mentioned apart from looking at its return value?
No, there is no way to know (short of looking at the documentation or implementation) whether a method will change some sort of state.
Methods that return void are generally going to change some sort of state (otherwise what are they doing?), but there's still no guarantee what will change (options include the object, one of its fields, the method's parameters, global state, or even the JVM runtime itself).
There's no general-purpose way to tell whether methods that return something will also have other side-effects or not.
If a type is immutable you can be confident that none of its methods will mutate its own state, but then the question has simply shifted to "how do you tell whether a type is immutable or not?" This is easier to answer, but still tricky. Static analysis tools like ErrorProne's #Immutable check are helpful but still fallible.
Well, pure setters which follow the pattern void setProperty(PropertyType property) are likely to modify the internal state (ok, one could implement it in a different way, e.g. modify the state of the passed parameter, but that would be strange).
Methods found in Builders for instance (like Builder withProperty(PropertyType property)) are free to choose whether they update the state of the actual instance or create and return new instance holding the updated property.
In the end one cannot foresee whether one or the other implementation strategy has been chosen just by looking at the method, so one has to read the docs (and sometimes the code).

How to determine if a Java method modifies an object passed as parameter

I come from a C++ background and I am currently learning Java. One question arose when I have tried using some third party libraries. How do I determine if the call to a method taking an object reference as parameter modifies the object?
In C++ this is clear thanks to the use of the const keyword. If the method signature is:
void foo(Boo& boo);
I know that the referenced object might be modified, while if the method signature is:
void foo(const Boo& boo);
The compiler guarantees that the referenced object is not modified.
I haven't seen something analogous in Java, as only the reference itself can be declared final, not the referenced object, and a final argument doesn't make much sense in the first place since it is passed by value anyway. Therefore, when I see a method such as:
void foo(Boo boo) {...}
How do I determine if the object referenced by boo is modified inside the body of the function (maybe using annotations)? If there is no way to know, is there some widely used convention or some best practices to avoid confusion and bugs?
how do I determine if the object referenced by boo is modified inside the body of the function (maybe using annotations)?
The only way is to read the code unfortunately.
If there is no way to know, is there some widely used convention or some best practices to avoid confusion and bugs?
The common convention is to pass an object which cannot be modified, using a wrapper if needed. This ensure the class cannot modify the object.
List<String> readOnly = Collections.unmodifiableList(list);
If the object is Cloneable, you can also use clone() but another common approach is to use a copy.
List<String> readOnly = new ArrayList<>(list);
If you care about such behaviour, unit tests can show whether a method modifies an object or not. If you have unit tests already, it is usually one or two lines extra to check for this.
There's no such facility built in to the language, unfortunately. A good defensive practice is to define the data objects you pass around as immutable (i.e., without any public method that allows modifying their state). If you are really concerned about this, you could copy/clone an object before passing it to a method you don't trust, but this is usually a redundant precaution.
NOTE: this answer is a more detailed version of
You can also write purity or side-effect annotations in your code — mernst
There exists the Checker Framework among the various things it can check at compile-time via annotations is the IJG Immutablity checker. This checker allows you to annotate object references with #Immutable or #ReadOnly.
The problem is that you often would have to annotate the library yourself. To ease your task the Checker Framework can automatically infer part of the annotations; you will still have to do much yourself.
A side effect analysis is not built into the Java language.
You can perform side effect analysis via manual inspection, but several tools exist to automate the process.
You can use an inference tool (1, 2, 3) to detect whether your code side-effects a parameter.
You can also write purity or side-effect annotations in your code and then use a checking/verification tool (1, 2) to ensure that your code conforms to the annotations you have written.
All of the above-linked tools have limitations, but you might find them useful. If you know of other tools, mention them in comments.
How do I determine if the object referenced by boo is modified inside
the body of the function (maybe using annotations)?
I must agree with other answers that there is no direct way to determine that method will modify your object or not and yes to make sure that method can not modify your Object you all have to do it is from your side.
If there is no way to know, is there some widely used convention or
some best practices to avoid confusion and bugs?
Here the method name comes to the scene. Moving ahead with the naming convention of method we have to take a look at some method declarations which clearly convince you that your Object will not be changed at all.
For example, You know that Arrays.copyOf will not change your actual array, System.out.println(boo) will not change your boo
Method names are real weapons to provide as much information as possible to the method user.(Yes! it's always not possible but quite a good practice to follow.)
Let's consider it in your case that say printBoo will only print, copyBoo will only copy, clearBoo will reset all attributes, checkAndCreateNewBoo will check your boo Object and create new if required.
So, ultimately if we can use them in a proper way caller can be assured with the fact that Object will remain the same after calling the method.
As everyone says, prefer using immutable objects and also avoid void methods
The available purposes of methods like this
void foo(Boo boo) {...}
are to change the state of the object itself or change the object passed as a parameter
void completOrder(Order order) { ... }
//or
void parserTokenEnded(String str) { ... }
There is a way , that the method developer should mark parameter as final , if it is not going to modify the parameter.
public void test(final Object param)
However very few people follow this , so it is difficult to know. However good programmer follow this rule , especially writing the api. If you want to write method and expose it. Make param final to indicate that passed object is not going to be modified.

Is passing 'this' in a method call accepted practice in java

Is it good/bad/acceptable practice to pass the current object in a method call. As in:
public class Bar{
public Bar(){}
public void foo(Baz baz){
// modify some values of baz
}
}
public class Baz{
//constructor omitted
public void method(){
Bar bar = new Bar();
bar.foo(this);
}
}
Specifically, is the line bar.foo(this) acceptable?
There's nothing wrong with that. What is NOT a good practice is to do the same inside constructors, because you would give a reference to a not-yet-completely-initialized object.
There is a sort of similar post here: Java leaking this in constructor
where they give an explanation of why the latter is a bad practice.
There's no reason not to use it, this is the current instance and it's perfectly legitimate to use. In fact there's often no clean way to omit it.
So use it.
As it's hard to convince it's acceptable without example (a negative answer to such a question is always easier to argument), I just opened one of the most common java.lang classes, the String one, and of course I found instances of this use, for example
1084 // Argument is a String
1085 if (cs.equals(this))
1086 return true;
Look for (this in big "accepted" projects, you won't fail to find it.
Yes, but you should be careful about two things
Passing this when the object has not been constructed yet (i.e. in its constructor)
Passing this to a long-living object, that will keep the reference alive and will prevent the this object from being garbage collected.
It's perfectly normal and perfectly acceptable.
this stands for the current object. What you are doing is sytatically correct but i don't see a need of this if you are calling the method in the same class.
It is bad practice to pass the current object in a method call if there less complex alternatives to achieve the same behaviour.
By definition, a bidirectional association is created as soon as this is passed from one object to another.
To quote Refactoring, by Martin Fowler:
Change Bidirectional Association to Unidirectional (200)
Bidirectional associations are useful, but they carry a price. The
price is the added complexity of maintaining the two-way links and
ensuring that objects are properly created and removed. Bidirectional
associations are not natural for many programmers, so they often are a
source of errors
...
You should use bidirectional associations when you need to but not
when you don’t. As soon as you see a bidirectional association is no
longer pulling its weight, drop the unnecessary end.
So, theoretically, we should be hearing alarm bells when we find we need to pass this and try really hard to think of other ways to solve the problem at hand. There are, of course, times when, at last resort, it makes sense to do it.
Also it is often necessary to corrupt your design temporarily, doing 'bad practice things', during a longer term refactoring of your code for an overall improvement. (One step back, two steps forward).
In practice I have found my code has improved massively by avoiding bidirectional links like the plague.
Yes. you can use it.Its just common in programming to pass this.But there are pros and cons about using that.Still it is not hazardous to do so.
Just to add one more example where passing this is correct and follows good design: Visitor pattern. In Visitor design pattern, method accept(Visitor v) is typically implemented in a way it just calls v.visit(this).
Acceptable
Snippet from Oracle JAVA docs:
Within an instance method or a constructor, this is a reference to the
current object — the object whose method or constructor is being
called. You can refer to any member of the current object from within
an instance method or a constructor by using this.
Using this with a Field
The most common reason for using the this keyword is because a field
is shadowed by a method or constructor parameter.
Everything in java is passed by value. But objects are NEVER passed to the method!
When java passes an object to a method, it first makes a copy of a reference to the object, not a copy of the object itself. Hence this is pefectly used method in java. And most commonly followed usage.

Java: When to use fields vs. arguments?

My current IVR app uses a wrapper class with several methods to call a web service and then parse its results. Each class has a single "invoke" method which calls the web service, and then calls subsequent submethods to break up the parsing into logical chunks.
Whenever a new input argument is needed in one or more of the submethods, the previous developer would add it as an argument on the invoke, and then add it as an argument on the submethods.
Is this the proper way to do this, or would it be better to set a field on the class, and then reference that whenever necessary?
Instead of:
invoke (oldField1, oldField2, newField1)
submethod1 (results, oldField1, oldField2, newField1)
submethod2 (results, oldField1, oldField2, newField1)
Should it be:
invoke(oldField1, oldField2, newField1){
OldField1=oldField1
OldField2=oldField2
NewField1=newField1
}
submethod1(results)
submethod2(results)
Or even:
new (oldField1, oldField2, newField1){
OldField1=oldField1
OldField2=oldField2
NewField1=newField1
}
invoke()
submethod1(results)
submethod2(results)
Thanks!
The first solution allows making the object stateless, and allows using a unique instance for all the invocations, even in parallel.
The third one allows making the object stateful but immutable. It could be used for several invocations using the same set of fields, even in parallel (if made immutable).
Both of these solutions are acceptable. The less state an object has, the easiest it is to use it, particularly in a multi-thread environment.
The less mutable an object is, the easiest it is to use it.
The second one makes it a stateful mutable object, which can't be used by several threads (without synchronization). It looks less clean than the other two to me.
My general rule is to avoid statefulness in a service-oriented class whenever possible. Although Java doesn't really support functional programming per-se, the simplest and most scalable implementation is your first approach, which uses no member variables.
If your goal is to avoid frequent changes to method signatures, you could try to use a more generic field encapsulation:
public class Invoker {
public static void invoke(ResultContainer result, List<String> parameters) {
submethod1(result, parameters);
submethod2(result, parameters);
}
}
I would also recommend that you take a look at the Decorator design pattern for more ideas.
It depends on if your argument is data or identifying a mode/switch.
I suggest one argument for the data structure type and another argument that contains the enum types of different operations.
And then based on your enum type or mode of operation you can choose a strategy on which class to execute.
To restrict this increasing argument approach, you could provide an interface. And force the implementation to adhere to that.

trying to use only one method name

When I was programming a Form Validator in PHP, when creating new methods, I needed to increase the number of arguments in old methods.
When I was learning Java, when I read that extends is to not touch previously tested, working code, I thought I shouldn't have increased the number of arguments in the old methods, but overridden the old methods with the new methods.
Imagine if you are to verify if a field is empty in one part of the form, in an other and in yet an other.
If the arguments are different, you'll overload isEmpty, but, if the arguments are equal, is it right to use isEmpty, isEmpty2, isEmpty3, three classes and one isEmpty per class or, if both are wrong, what should I have done?
So the question is:
If I need different behaviors for a method isEmpty which receives the same number arguments, what should I do?
Use different names? ( isEmpty, isEmpty2, isEmpty3 )
Have three classes with a single isEmpty method?
Other?
If that's the question then I think you should use:
When they belong to the same logical unit ( they are of the same sort of validation ) but don't use numbers as version, better is to name them after what they do: isEmptyUser, isEmptyAddress, isEmptyWhatever
When the validator object could be computed in one place and passed around during the program lifecycle. Let's say: Validator v = Validator.getInstance( ... ); and then use it as : validator.isEmpty() and let polymorphism to it's job.
Alternatively you could pack the arguments in one class and pass it to the isEmpty method, although you'll end up with pretty much the same problem of the name. Still it's easier to refactor from there and have the new class doing the validation for you.
isEmpty( new Arguments(a,b,c ) ); => arguments.isEmpty();
The Open/Closed Principle [usually attributed to Bertrand Meyer] says that "software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification". This might be the principle that you came across in your Java days. In real life this applies to completed code where the cost of modification, re-testing and re-certification outweighs the benefit of the simplicity gained by making a direct change.
If you are changing a method because it needs an additional argument, you might choose to use the following steps:
Copy the old method.
Remove the implementation from the copy.
Change the signature of the original method to add the new argument.
Update the implementation of the original method to use the new argument.
Implement the copy in terms of the new method with a default value for the argument.
If your implementation language doesn't support method overloading then the principle is the same but you need to find a new name for the new method signature.
The advantage of this approach is that you have added the new argument to the method, and your existing client code will continue to compile and run.
This works well if there is an obvious default for the new argument, and less well if there isn't.
Since java 5 you can use variable list of arguments as in void foo(Object ... params)
You will need to come up with creative names for your methods since you can't overload methods that have same type and number of arguments (or based on return type). I actually personally prefer this to overloading anyway. So you can have isEmpty and isEmptyWhenFoo and isEmptyWhenIHaveTheseArguments (well meybe not the last one :)
Not sure if this actually answers your question, but the best way to think about OO in "real life" is to think of the Nygaard Classification:
ObjectOrientedProgramming. A program execution is regarded as a physical model, simulating the behavior of either a real or imaginary part of the world.
So how would you build a physical device to do what you are trying to do in code? You'd probably have some kind of "Form" object, and the form object would have little tabs or bits connected to it to represent the different Form variables, and then you would build a Validator object that would take the Form object in a slot and then flash one light if the form was valid and another if it was invalid. Or your Validator could take a Form object in one slot and return a Form object out (possibly the same one), but modified in various ways (that only the Validator understood) to make it "valid". Or maybe a Validator is part of a Form, and so the Form has this Validator thingy sticking out of it...
My point is, try to imagine what such a machine would look like and how it would work. Then think of all of the parts of that machine, and make each one an object. That's how "object-oriented" things work in "real life", right?
With that said, what is meant by "extending" a class? Well, a class is a "template" for objects -- each object instance is made by building it from a class. A subclass is simply a class that "inherits" from a parent class. In Java at least, there are two kinds of inheritance: interface inheritance and implementation inheritance. In Java, you are allowed to inherit implementation (actual method code) from at most one class at a time, but you can inherit many interfaces -- which are basically just collections of attributes that someone can see from outside your class.
Additionally, a common way of thinking about OO programming is to think about "messages" instead of "method calls" (in fact, this is the original term invented by Alan Kay for Smalltalk, which was the first language to actually be called "object-oriented"). So when you send an isEmpty message to the object, how do you want it to respond? Do you want to be able to send different arguments with the isEmpty message and have it respond differently? Or do you want to send the isEmpty message to different objects and have them respond differently? Either are appropriate answers, depending on the design of your code.
Instead having one class providing multiple versions of isEmpty with differing names, try breaking down your model into a finer grained pieces the could be put together in more flexible ways.
Create an interface called Empty with
one method isEmpty(String value);
Create implemntations of this
interface like EmptyIgnoreWhiteSpace
and EmptyIgnoreZero
Create FormField
class that have validation methods
which delegate to implementations of
Empty.
Your Form object will have
instances of FormField which will
know how to validate themselves.
Now you have a lot of flexibility, you can combine your Empty implemenation classes to make new classes like EmptyIgnoreWhiteSpaceAndZero. You can use them in other places that have nothing to do with form field validation.
You don't have have have multple similarly named methods polluting your object model.

Categories

Resources