I'm having some difficulties about how to correctly design and implement two methods.
I have 2 methods, A and B. Method A does 2 things and method B does only 1 thing. One of the things that method A does is the same as what method B does, so it is very reasonable to call method B from within a method A.
Now the problem is that both methods need to send exactly one email to a user. When I invoke A, I want to receive 1 email and when I invoke B, I also want to get 1 email. This means that if I call method B inside A, I will now get 2 mails while doing 1 action (= invoking A). To make it even more tempting to simply include B in A, the set up procedure is truly the same for both methods and so instead of redoing the set up in the B, I could simply call method B with these set up data from A. But I have no setup data to provide when calling the B directly and so in this case I'd need to do the setup anyway.
What is the best approach to solve such a problem? Should I:
Add a parameter to method B in which I will say whether it should send the email or not and another parameters for the setup data
Keep the two methods separated, because method B is not doing exactly the same thing in the two contexts
... other suggestions?
PS. I'm not sure if stackoverflow is actually suitable for such a question, let me know if there's a better stackexchange platform for this.
Thanks for any ideas
I would suggest you split out the functionality a little further.
Currently you have two methods that might be described something like this:
void MethodA()
{
DoThing1();
DoThing2();
SendEmail();
}
void MethodB()
{
DoThing1();
SendEmail();
}
So one fairly simple answer is to extract the actual functional bits out of the two methods into methods of their own and leave behind a shell similar to the above. Each of the DoThingX methods can return whatever it is you need for building the email, etc.
Of course if the DoThingX methods are really small - a couple of lines or so, for instance - then it might not make sense to break them out this way.
I don't know if this is truly on-topic either. That said...
It seems to me that "sending email" is one of the things that is included in the method B work that method A needs done. As such, why not just implement it in method B? Then method A gets it for free when it calls method B.
If the exact contents of the email are different depending on whether method A was called or not, then sure…you can add a parameter to method B to customize the email in some way.
Finally, you're pretty vague on the details. It's not really clear just how much code you're saving by calling method B from method A. If it's significant, then I'm a strong proponent of code sharing like this. But if we're just talking a single statement, well...that seems less worth bothering with; maybe just putting that same single statement in each method is better.
Sorry for the vague answer. GIGO. :)
You could use the return of the methods for the content of our email:
private String funcA() {
// foo
return "Mail from funcA";
}
private String funcB() {
funcA(); // ignoring the return value here, we later return our on
// foo
return "Mail from funcB"; // our own return
}
Then you send the email outside of these functions (JUST EXAMPLE CODE):
private void mainFunc() {
String mail = condition ? funcA() : funcB();
sendMail(mail);
}
I have two ideas:
create C method that represents common functionality of A and B, and invoke C in A and B with different parameters
invoke B inside A, but extract mailing functionality alone to separate method C
To clarify the first idea:
methodA() {
firstAction();
secondAction(Parameter parameterFromA);
}
methodB() {
secondAction(Parameter parameterFromB);
}
Related
In Java, assume you have a data object object with an attribute bar that you need to set with a value that is returned from a complex operation done in an external source. Assume you have a method sendRequestToExternalSource that send a request based on 'object' to the external source and gets an object back holding (among other things) the needed value.
Which one of these ways to set the value is the better practice?
void main(MyObject object) {
bar = sendRequestToExternalSource(object);
object.setBar(bar);
}
String sendRequestToExternalSource(MyObject object) {
// Send request to external source
Object response = postToExternalSource(object);
//Do some validation and logic based on response
...
//Return only the attribute we are interested in
return response.getBar();
}
or
void main(MyObject object) {
sendRequestToExternalSourceAndUpdateObject(object);
}
void sendRequestToExternalSourceAndUpdateObject(MyObject object) {
// Send request to external source
Object response = postToExternalSource(object);
//Do some validation and logic based on response
...
//Set the attribute on the input object
object.setBar(response.getBar());
}
I know they both work, but what is the best practice?
It depends on a specific scenario. Side-effects are not bad practice but there are also scenarios where a user simply won't expect them.
In any case your documentation of such a method should clearly state if you manipulate arguments. The user must be informed about that since it's his object that he passes to your method.
Note that there are various examples where side-effects intuitively are to be expected and that's also totally fine. For example Collections#sort (documentation):
List<Integer> list = ...
Collections.sort(list);
However if you write a method like intersection(Set, Set) then you would expect the result being a new Set, not for example the first one. But you can rephrase the name to intersect and use a structure like Set#intersect(Set). Then the user would expect a method with void as return type where the resulting Set is the Set the method was invoked on.
Another example would be Set#add. You would expect that the method inserts your element and not a copy of it. And that is also what it does. It would be confusing for people if it instead creates copies. They would need to call it differently then, like CloneSet or something like that.
In general I would tend to giving the advice to avoid manipulating arguments. Except if side-effects are to be expected by the user, as seen in the example. Otherwise the risk is too high that you confuse the user and thus create nasty bugs.
I would choose the first one if I have only these two choices. And the reason of that is "S" in SOLID principles, single responsibility. I think the job of doComplicatedStuff method is not setting new or enriched value of bar to MyObject instance.
Of course I don't know use case that you are trying to implement, but I suggest looking at decorator pattern to modify MyObject instance
I personally prefer the variant barService.doComplicatedStuff(object); because I avoid making copies
Suppose I want to create a unit test for a method like this:
public Car map(CarReq request) {
Car car = new Car();
car.setPrice(carReq.getPrice());
car.setColour(carReq.getColour());
car.setType(carReq.getType());
// Other 20 lines like these
return car;
}
I can mock carRequest and tell each method what should return. But that's like not testing anything, as all the method does is getting values from carReq.
I can create a testing carReq object (without mocking) and check that the same values are copied into the output Car object. But that's a lot of work, right?
Isn't there a more intelligent way?
You want to test the logic of the method.
Therefore if what the method does is copying the properties of a CarReq into a Car, then this is what you should test:
#Test
public void mapTest() {
// Given
CarReq carReq = new CarReq(10000D, ...);
// When
Car car = myClass.map(carReq);
// Then
Assert.assertEquals(car.getPrice(), carReq.getPrice());
// ...
}
I'm not quite sure what the issue is ? Surely since the method takes a request and returns a new Car, that's precisely what you want to test ? If I was doing it, I would:
create a populated request and determine that the Car fields are what are in the request
perhaps assert that each invocation gives you a new Car ?
assert expected behaviour if you pass in a null (again, depending on the proposed usage of the method)
You say that all the method does is call setters/getters, but don't forget that one purpose of a unit test is to assert that the behaviour remains the same going forwards (i.e. you're testing for regressions). If you add additional functionality to this method, and you accidentally break something, the above test will tell you immediately.
Is it a lot of work ? Maybe (perhaps a few mins of copy/paste getter/setter invocations and changing params to be unique per attribute). But it's a lot less work than resolving an issue in production later on.
I can create a testing carReq object (without mocking) and check that
the same values are copied into the output Car object. But that's a
lot of work, right?
It is, but if you really are willing to unit-test this method, you have to do this.
Please note that you can use libraries like Orika to perform this kind of dumb field-mapping methods for you. Saves time and code lines :)
Following is an example code , checkUserGuess method that belongs to a Board class.
public String checkUserGuess(String aGuess)
{
// Some processing
return result_of_a_guess;
}
I have a SimpleGuessingGame class consumes this method and is satisfied with the processing that the method does. It does not use the returned value.
Another class ComplexGuessingGame consumes this method and also uses the value returned by the method for further processing.
So we have two cases , one where the return value is used and other where its ignored. Is this a common occurrence or does this point to bad design ?
When you need to do something like this, chances are that the method does two things that are of value to a caller:
Validates something, or produces another side effect, and
Computes the result to be returned to the callers
Since some users need only #1, while other users need both #1 and #2, it may be a good idea to split the method in two parts, like this:
public void validatekUserGuess(String aGuess) {
// Some processing
}
public String checkUserGuess(String aGuess) {
validatekUserGuess(aGuess);
// Some additional processing
return result_of_a_guess;
}
Now the users that wish to ignore the return value would not be required to "pay" with CPU and memory for computing a value that they are going to discard anyway.
There is nothing inherently wrong with using a return value in one call, and not using it in another.
Imagine in one case you want to attempt to turn a light on, and in another you want to make sure it was actually turned on.
public boolean turnOn(Light l);
case 1:
turnOn(new Light());
log.debug("Attempted to turn on light");
case 2:
boolean turnedOn = turnOn(new Light());
if (turnedOn) {
log.debug("Light is turned on");
} else {
log.debug("Not able to turn light on");
}
If the two are exactly identical (and the result_of_a_guess is needed but just not returned) then I would say that you are fine. Many times built-in functions have return values that people ignore because they just don't need them (but they are nice to have for extra processing, like you seem to be doing).
If you really don't like the return value then you can place result_of_a_guess in a member variable to be only set when the checkUserGuess is flagged as complex like so:
public void checkUserGuess(String aGuess, Boolean isComplex)
{
// Some processing
if (isComplex)
setResult(result_of_a_guess)
}
I've seen a lot of both. In my opinion it comes down to a stylistic choice/ preference. You need to know and understand the scope of your project and what works best for you and your future code!
Consider a class that uses an external jar. The class processes objects of type D, which are obtained via objects A, B, and C, all of which external objects from the jar.
class DProcessor() {
public void process(PoolOfA pool) {
A a = pool.borrowObject()
...
B b = a.getB()
C c = b.getC()
for (D d : c.getAllDs()) {
// Do something meaningful with d
}
}
}
How do I Unit test process(PoolOfA pool)?
My best shot so far is writing mocks for all external classes:
PoolOfA pool = mock(PoolOfA.class);
A a = mock(A.class);
B b = mock(B.class);
C c = mock(C.class);
D d1 = mock(D.class);
D d2 = mock(D.class);
D d3 = mock(D.class);
D d4 = mock(D.class);
List listOfDs = new ArrayList<D>();
listOfDs.add(d1);
listOfDs.add(d2);
listOfDs.add(d3);
listOfDs.add(d4);
// Set specific behaviour for each d
when(pool.borrowObject()).thenReturn(a);
when(b.getC()).thenReturn(a);
when(c.getAllDs()).thenReturn(d);
when(b.getC()).thenReturn(c);
when(c.getAllDs()).thenReturn(listOfDs);
This seems cumbersome and inelegant. Is there a better way?
Better way is to rewrite the method, of course. But if you cannot do it for some reason, mockito offers great feature called 'deep stubs'. Check out the docs.
What process really does, is process some Ds in the loop. I would first make it clear by changing the signature:
public void process(Collection<D> allDs)
Now you can test that more easily by mocking D only.
That method can either be public if it can replace the existing one or package private for example if you don't want to expose it. In that latter case, you might still want to test that the other process method (the one that takes a poolOfA) properly extract the Ds. But that means that process(PoolOfA) needs to know a lot about the poolOfA which does not seem right.
This is one of the ideas promoted by this "Guide to writing testable code" which I think contains interesting concepts. What you mention would probably fall into the "Digging into Collaborators" section.
I would suggest a small redesign of the process method: It is currently responsible for doing two things: Extracting an Iterable of D's from the internals of the input and processing them.
So actually, you method, although declaring that it is expecting an input of type PoolOfA, is absolutely not interested in this object. It wants what's inside. I wold declare the method as taking an Iterable and pass the responsibility to the caller to give it the correct input. This will clarify the intention of the method and make it easier to test.
You may say: "this is not a real solution, this is just moving the problem to another location!
now I need to test the calling method!"
Well, yes and no. First, remember that you do not have to UT everything, just for the sake of coverage. You should focus your UT efforts on algorithmic pieces of code, it is OK to skip trivial object interactions.
If you insist, you can use more powerful mocking libraries like PowerMock in order to mock only past of your class, but this is a discussion for a different Question.
Since arguments sent to a method in Java point to the original data structures in the caller method, did its designers intend for them to used for returning multiple values, as is the norm in other languages like C ?
Or is this a hazardous misuse of Java's general property that variables are pointers ?
A long time ago I had a conversation with Ken Arnold (one time member of the Java team), this would have been at the first Java One conference probably, so 1996. He said that they were thinking of adding multiple return values so you could write something like:
x, y = foo();
The recommended way of doing it back then, and now, is to make a class that has multiple data members and return that instead.
Based on that, and other comments made by people who worked on Java, I would say the intent is/was that you return an instance of a class rather than modify the arguments that were passed in.
This is common practice (as is the desire by C programmers to modify the arguments... eventually they see the Java way of doing it usually. Just think of it as returning a struct. :-)
(Edit based on the following comment)
I am reading a file and generating two
arrays, of type String and int from
it, picking one element for both from
each line. I want to return both of
them to any function which calls it
which a file to split this way.
I think, if I am understanding you correctly, tht I would probably do soemthing like this:
// could go with the Pair idea from another post, but I personally don't like that way
class Line
{
// would use appropriate names
private final int intVal;
private final String stringVal;
public Line(final int iVal, final String sVal)
{
intVal = iVal;
stringVal = sVal;
}
public int getIntVal()
{
return (intVal);
}
public String getStringVal()
{
return (stringVal);
}
// equals/hashCode/etc... as appropriate
}
and then have your method like this:
public void foo(final File file, final List<Line> lines)
{
// add to the List.
}
and then call it like this:
{
final List<Line> lines;
lines = new ArrayList<Line>();
foo(file, lines);
}
In my opinion, if we're talking about a public method, you should create a separate class representing a return value. When you have a separate class:
it serves as an abstraction (i.e. a Point class instead of array of two longs)
each field has a name
can be made immutable
makes evolution of API much easier (i.e. what about returning 3 instead of 2 values, changing type of some field etc.)
I would always opt for returning a new instance, instead of actually modifying a value passed in. It seems much clearer to me and favors immutability.
On the other hand, if it is an internal method, I guess any of the following might be used:
an array (new Object[] { "str", longValue })
a list (Arrays.asList(...) returns immutable list)
pair/tuple class, such as this
static inner class, with public fields
Still, I would prefer the last option, equipped with a suitable constructor. That is especially true if you find yourself returning the same tuple from more than one place.
I do wish there was a Pair<E,F> class in JDK, mostly for this reason. There is Map<K,V>.Entry, but creating an instance was always a big pain.
Now I use com.google.common.collect.Maps.immutableEntry when I need a Pair
See this RFE launched back in 1999:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4222792
I don't think the intention was to ever allow it in the Java language, if you need to return multiple values you need to encapsulate them in an object.
Using languages like Scala however you can return tuples, see:
http://www.artima.com/scalazine/articles/steps.html
You can also use Generics in Java to return a pair of objects, but that's about it AFAIK.
EDIT: Tuples
Just to add some more on this. I've previously implemented a Pair in projects because of the lack within the JDK. Link to my implementation is here:
http://pbin.oogly.co.uk/listings/viewlistingdetail/5003504425055b47d857490ff73ab9
Note, there isn't a hashcode or equals on this, which should probably be added.
I also came across this whilst doing some research into this questions which provides tuple functionality:
http://javatuple.com/
It allows you to create Pair including other types of tuples.
You cannot truly return multiple values, but you can pass objects into a method and have the method mutate those values. That is perfectly legal. Note that you cannot pass an object in and have the object itself become a different object. That is:
private void myFunc(Object a) {
a = new Object();
}
will result in temporarily and locally changing the value of a, but this will not change the value of the caller, for example, from:
Object test = new Object();
myFunc(test);
After myFunc returns, you will have the old Object and not the new one.
Legal (and often discouraged) is something like this:
private void changeDate(final Date date) {
date.setTime(1234567890L);
}
I picked Date for a reason. This is a class that people widely agree should never have been mutable. The the method above will change the internal value of any Date object that you pass to it. This kind of code is legal when it is very clear that the method will mutate or configure or modify what is being passed in.
NOTE: Generally, it's said that a method should do one these things:
Return void and mutate its incoming objects (like Collections.sort()), or
Return some computation and don't mutate incoming objects at all (like Collections.min()), or
Return a "view" of the incoming object but do not modify the incoming object (like Collections.checkedList() or Collections.singleton())
Mutate one incoming object and return it (Collections doesn't have an example, but StringBuilder.append() is a good example).
Methods that mutate incoming objects and return a separate return value are often doing too many things.
There are certainly methods that modify an object passed in as a parameter (see java.io.Reader.read(byte[] buffer) as an example, but I have not seen parameters used as an alternative for a return value, especially with multiple parameters. It may technically work, but it is nonstandard.
It's not generally considered terribly good practice, but there are very occasional cases in the JDK where this is done. Look at the 'biasRet' parameter of View.getNextVisualPositionFrom() and related methods, for example: it's actually a one-dimensional array that gets filled with an "extra return value".
So why do this? Well, just to save you having to create an extra class definition for the "occasional extra return value". It's messy, inelegant, bad design, non-object-oriented, blah blah. And we've all done it from time to time...
Generally what Eddie said, but I'd add one more:
Mutate one of the incoming objects, and return a status code. This should generally only be used for arguments that are explicitly buffers, like Reader.read(char[] cbuf).
I had a Result object that cascades through a series of validating void methods as a method parameter. Each of these validating void methods would mutate the result parameter object to add the result of the validation.
But this is impossible to test because now I cannot stub the void method to return a stub value for the validation in the Result object.
So, from a testing perspective it appears that one should favor returning a object instead of mutating a method parameter.