This week's book giveaway is in the Java 8 forum.
We're giving away four copies of Java 8 in Action and have Raoul-Gabriel Urma, Mario Fusco, and Alan Mycroft on-line!
See this thread for details.
The moose likes Beginning Java and the fly likes Methods should return as much information as possible - Discuss Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Java 8 in Action this week in the Java 8 forum!
JavaRanch » Java Forums » Java » Beginning Java
Bookmark "Methods should return as much information as possible - Discuss" Watch "Methods should return as much information as possible - Discuss" New topic
Author

Methods should return as much information as possible - Discuss

Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 7081
    
  16

Hi,

I've added this topic to the Beginners forum, as I think the (hopeful) discussion might prove useful; even if the topic itself isn't strictly for first-timers. Bartenders, feel free to move if you see fit.

My contention is exactly as stated in the subject: Methods should return as much information as possible.

It's one of the reasons I hate methods that return booleans - like contains().
I much prefer ones like List.indexOf(), because it returns not only a value that indicates whether the List contains the object, but also where it is.

Does that make me a geek? Maybe; but I'll continue the analogy.

I've recently run into this with a class of mine that contains an array.
Arrays.equals(), which is designed to compare arrays element by element, is a great idea but, in my view, is seriously flawed because it hides useful information about the result (ie, where the difference was found). If it wasn't, I could use to implement both equals() and compareTo() optimally.

Let's assume for a moment that it returns the index of the element that is different, or -1 if they are all the same (the usual pattern for indexOf() methods).
I could then implement my equals() method based on Arrays.equal(myArray) < 0, and my compareTo() method would only need to compare the element at the returned index; if it returns -1, then my compareTo() can return 0.

But it doesn't. It returns a boolean; so all I know is that somewhere it found a difference.

And it doesn't stop there. What about if you're checking an expiry date, or trying to validate an index limit? Wouldn't it be nicer if the method returned the limit you're violating? Admittedly, it might make APIs a little more difficult to follow (but then you could always provide extra public methods that do return booleans), but for library methods I definitely reckon it's the right way to go.

My theory: As stated in the subject line.
My advice: Avoid methods that return booleans.

Any thoughts?

Winston


Isn't it funny how there's always time and money enough to do it WRONG?
Artlicles by Winston can be found here
William P O'Sullivan
Ranch Hand

Joined: Mar 28, 2012
Posts: 860

I've had this philosophical argument for years (decades?).

For example: boolean isDoorOpen(...)

Now calling this returns true or false.

However, would you want it to open the door if it were closed, or close it if it were open ??

Simple primitive return types imho should be just that and no more.
When Objects and Collections are flying around then all bets are off.

Talk among yourselves ... ;)

WP
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 7081
    
  16

William P O'Sullivan wrote:I've had this philosophical argument for years (decades?).
For example: boolean isDoorOpen(...)

Interesting; quite apart from whether such a method should be part of a public API for anything but a Door.

Winston
Seetharaman Venkatasamy
Ranch Hand

Joined: Jan 28, 2008
Posts: 5575

Winston Gutkowski wrote:
Arrays.equals(), which is designed to compare arrays element by element, is a great idea but, in my view, is seriously flawed because it hides useful information about the result (ie, where the difference was found).

sometime we want only true or false.because we are not going to do anything further with those objects...

* high level people always prefer false, true rather 0,1

just my thought ...
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 7081
    
  16

Seetharaman Venkatasamy wrote:* high level people always prefer false, true rather 0,1
just my thought ...

Yup, agreed (used to be one of those myself). But we don't always write public methods; and library methods, such as Arrays.equals(), are generally written for developers, not "high-levellers".

Maybe it sounds like I'm just moaning that Arrays doesn't have a bunch of diff() methods; but I think it's a bit more than that. For starters, if it did, all its equals() methods would be one-liners.

Winston
Seetharaman Venkatasamy
Ranch Hand

Joined: Jan 28, 2008
Posts: 5575

Winston Gutkowski wrote: For starters, if it did, all its equals() methods would be one-liners.Winston

i think, marketing kills programmer . easy to understand, it saves time etc... [sorry, if I misunderstood your post]
Seetharaman Venkatasamy
Ranch Hand

Joined: Jan 28, 2008
Posts: 5575

Winston Gutkowski wrote:such as Arrays.equals(), are generally written for developers, not "high-levellers".

but I am high-levellers developer, who knows how to drive a car ;)
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 7081
    
  16

Seetharaman Venkatasamy wrote:sorry, if I misunderstood your post

Nothing to misunderstand. It's just my opinion, and I'm here to defend it; but I suspect there are others out there who don't agree.

And I'm also happy to concede that methods that return booleans may be a good thing for public APIs, particularly in addition to "returns all" methods. A good example is the String API.

Winston
Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 4419
    
    5

Standard consultant's reply: it depends

So what about the equals() method on Object, do you think that should return more than just boolean? Like a list of differences, maybe? And if the list was empty (again, determined by a boolean method call), then that means the two objects are equal? That would get a little unwieldy to code, I think. Going back to List.isEmpty(), what non-boolean value would that return? Say you were to refactor the names to match the return values, like say equals() becomes differences() and isEmpty() becomes ... size()? Wait, List already has size() or getSize(), whatever. So size() is there, but so is isEmpty()... redundant? I wouldn't say redundant. I'd say there is a place for boolean methods because they are a more straightforward way of expressing a natural idea: that of being or not being something.

Is boolean the right thing for everything? Obviously not. List.size() (or getSize(), whatever) is proof of that.

Edit: ok, so I obviously didn't read the entire OP. Just got as far as the first two paragraphs before I went and whipped up this reply.


Junilu - [How to Ask Questions] [How to Answer Questions]
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 3970
    
  17

Winston Gutkowski wrote:I've recently run into this with a class of mine that contains an array.
Arrays.equals(), which is designed to compare arrays element by element, is a great idea but, in my view, is seriously flawed because it hides useful information about the result (ie, where the difference was found). If it wasn't, I could use to implement both equals() and compareTo() optimally.

Let's assume for a moment that it returns the index of the element that is different, or -1 if they are all the same (the usual pattern for indexOf() methods).
I could then implement my equals() method based on Arrays.equal(myArray) < 0, and my compareTo() method would only need to compare the element at the returned index; if it returns -1, then my compareTo() can return 0.


This seems backwards to me. If you ask 'is that equal to this' I don't want to know the differences, I want to know if that is equal to this. If I wanted to know the difference(s) I would ask a different question: 'what is the difference between that and this'. And I would want that to be implemented in a method with an appropriate name, maybe Arrays.difference(myArray);

I think in general it would be good to provide methods which give out such pertinent information, but I think equals() is a bad example.

Steve
Matthew Brown
Bartender

Joined: Apr 06, 2010
Posts: 4246
    
    7

Winston Gutkowski wrote:My contention is exactly as stated in the subject: Methods should return as much information as possible.

It's one of the reasons I hate methods that return booleans - like contains().
I much prefer ones like List.indexOf(), because it returns not only a value that indicates whether the List contains the object, but also where it is.


Interesting discussion. Mind if I disagree?

For me, there's a difference between information and meaning. I want the most meaningful method in the context I'm interested in, because that makes the intent of my code clearer. Which, I suppose, means that I'd like both methods to exist. Both are better in different contexts.

A good (if slightly trivial) example is in the collection classes. If you're checking whether a list is empty, do you use list.isEmpty() or list.size() == 0? I'd use the former, because it makes the intent very clear - I want to know whether there's anything in the list. The latter approach says I'm comparing the size to something, that happens to be zero in this case.

A parallel and equally simple idea (not related to return values) is the difference between n = (n + 1), n += 1, and n++. All equivalent, but express slightly different intents. The former says "set to a new value, which is one more than the current value". The second says "increase the value by an amount equal to 1" and the third says "increment". If I'm using the variable as a loop counter, for instance, the latter is the meaning closest to what I want.

So, in summary, I love methods that return booleans. But I'm happy for them to delegate to a more flexible method.
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 7081
    
  16

Matthew Brown wrote:Interesting discussion. Mind if I disagree?

Absolutely not. Whole point of the topic.

For me, there's a difference between information and meaning. I want the most meaningful method in the context I'm interested in, because that makes the intent of my code clearer. Which, I suppose, means that I'd like both methods to exist. Both are better in different contexts.

A good (if slightly trivial) example is in the collection classes. If you're checking whether a list is empty, do you use list.isEmpty() or list.size() == 0? I'd use the former, because it makes the intent very clear - I want to know whether there's anything in the list. The latter approach says I'm comparing the size to something, that happens to be zero in this case.

Yes, I absolutely agree. And there we come (possibly) to the division of a public and private (or "friendly" (in C terms)) API. What do you want to give to the outside world? A contains() method, or the means to make a contains() method?

It's always a judgement call, but I think that a bad call in these terms comes down to trying to hide too much information too soon. A library class like Arrays should provide me, as a developer, with an API that allows me to make some decisions. Unfortunately, right now, the sort of methods that are part of this discussion are part of my own utility set.

Looking at my replies so far, and thinking over the problem again, I suspect that my topic boils down to using boolean as a return type when another one would provide more information; but I suspect not entirely...

Winston
dennis deems
Ranch Hand

Joined: Mar 12, 2011
Posts: 808
Winston Gutkowski wrote:What do you want to give to the outside world? A contains() method, or the means to make a contains() method?

What's wrong with having both? If I require the index, I'll use indexOf. If I do not require the index, I'll use contains, which expresses my intent with more clarity than indexOf(elem) >= 0.
dennis deems
Ranch Hand

Joined: Mar 12, 2011
Posts: 808
This reminds me of a discussion with a colleague a few years ago. He felt that a method should never return void -- that there is always some potentially useful value which a method could return. I argued that this could result in lack of clarity about the purpose of a method: returning a value implies that there is a reason for the invoker to be interested in what that value is -- obviously not the case if I am merely calling a setter.
fred rosenberger
lowercase baba
Bartender

Joined: Oct 02, 2003
Posts: 10925
    
  12

I think I fundamentally disagree with "as much as possible". You could return a LOT of information. For example, on the difference between two arrays, you could return:

1) Are they different?
2) Where are they different (i.e. what positions)
3) What is in 'A' that is not in 'B'
4) What is in 'B' that is not in 'A'
5) Which (if either) has more elements
6) What is common to both
7) a list of what is in both 'A' and 'B' but in a different spot

and probably a few other things. That is a lot more than what I want when i ask "are they different".


There are only two hard things in computer science: cache invalidation, naming things, and off-by-one errors
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 7081
    
  16

Dennis Deems wrote:
Winston Gutkowski wrote:What do you want to give to the outside world? A contains() method, or the means to make a contains() method?

What's wrong with having both? If I require the index, I'll use indexOf. If I do not require the index, I'll use contains, which expresses my intent with more clarity than indexOf(elem) >= 0.

OK, perhaps I'm talking specifically about library methods then (and I'd categorize Arrays and Collections as 'library' classes).
However, I would add that we are advised as a general practise to keep APIs 'as spare as possible' (ie, don't provide more methods than you need to), and to me, methods that hide more information than they need to can be guilty of forcing developers to provide redundant APIs.

As for your colleague's view: I tend to agree with him, and personally often write 'setters' that look more like 'swappers'. After all, there's nothing in the language that forces a return value to be used; and the savings of not providing one can probably be measured in machine instructions. And that's assuming there's even a need to provide public setters at all.
I suspect it also has advantages when dealing with thread-safety, as you end up with fewer situations where you're writing logic that needs to be synchronized. I'm also quite a fan of fluid interfaces though, so maybe I'm biased.

Winston

BTW: Thanks everybody for your contributions. Keep 'em coming.
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 7081
    
  16

fred rosenberger wrote:I think I fundamentally disagree with "as much as possible". You could return a LOT of information. ... That is a lot more than what I want when i ask "are they different".

But many of the types of information that you're referring to are highly specialized. To me, equals() and diff() (as I described it above) are functionally redundant, in the same way that contains() and indexOf() are (or, as Matthew said, isEmpty() and size() == 0); and in my opinion the latter methods are far more useful because they allow programmers (and we are talking about programmers here; not some non-technical "user") to choose how they build their APIs.

Don't get me wrong; I'm not advocating NOT providing equals() or contains() if the situation warrants it (indeed, as Junilu pointed out, you have no choice, because Object already has one), nor that they shouldn't return a boolean. I'm just saying that they make bad "building blocks" because they don't provide sufficient information.

I remember back in the dark ages when I was using PL/1, that it had a wonderful method called verify(), which was a bit like the "inverse" of an indexOf(): ie, it returned the index of the first element in an array, string, whatever, that didn't match the supplied value (or values), or -1 if all elements matched. Needless to say, it got a LOT of use; but I'm not sure that I'd publish it to a "user".

Winston

PS: Just thought I'd add this. One of the very first books I read about OOP had this quote on the introduction page, and I think it's very good:
"When it is not necessary to make a decision, it is necessary not to make a decision" - Lord Falkland.
And I'd say that providing Arrays.equals(), but no Arrays.diff() violates that principle.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Methods should return as much information as possible - Discuss
 
Similar Threads
next() cannot override next() in my abstract list.
Remove dates from an array list using iterator
Iterator Pattern