2

lets say we have a class called Intersection, with a findIntersect(line1, line2) method. It returns an object called point, with 2 fields the x and y coordinates. Now, if the input are 2 parallel lines, what is the best way to communicate that no result was obtained with the user? Though example is specific to lines, the question is generic - assuming a method returns value object, what to return if conditions don't match? Some options are:

  1. Return null (issue: read in many places that null return value should be avoided if possible)
  2. Have a method in object which determines if object is valid, similar to hasNext() in Iterator?
  3. Throw an Exception?

Please let me know best approach.

Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
JavaDeveloper
  • 5,320
  • 16
  • 79
  • 132
  • Personally, I like null. If you're going to have to check validity anyway, a null check is quick, simple, and readable to any coder. Just my two cents. – Geobits Aug 02 '13 at 03:58
  • If you are working with `float`, `Float.NaN` could be returned, but explain it in docs as well. – S.D. Aug 02 '13 at 04:01

4 Answers4

11

Whatever you do, document it. As a caller of the function, I would expect the exact behavior, particularly for edge cases, to be clearly described in the method's JavaDoc.

In this particular case, I would probably return an Optional<Point>. Optional is quite nice because it very clearly communicates that a value might not be present. A sane API would never – never – return null if its declared return type is Optional.

More reading: Using and avoiding null and Avoiding != null statements

Community
  • 1
  • 1
Matt Ball
  • 354,903
  • 100
  • 647
  • 710
  • 3
    Upvote for documenting it. So long as I can easily tell whats returned I'm happy. – Gabe Sechan Aug 02 '13 at 03:58
  • +1. document edge cases, always. – S.D. Aug 02 '13 at 03:59
  • 1
    Regardless of whether you have a `checkParallel` method, someone will eventually pass in two parallel lines, and you have to handle that somehow. I would probably throw a `ParallelLinesException extends IllegalArgumentException`, but whether you do that or return some sort of "invalid" value, you should specify exactly what your code contract is. – chrylis -cautiouslyoptimistic- Aug 02 '13 at 06:13
1
  1. One should be very careful about returning nulls. Your API users will have to bloat their code with null checks.
  2. A good solution, having an object decide if its in a valid state or not. If not it defaults to a pre-defined state.
  3. A possible solution, if it makes sense in your API's case. For example: Is the user allowed to pass 2 parallel lines?
Matt Ball
  • 354,903
  • 100
  • 647
  • 710
rocketboy
  • 9,573
  • 2
  • 34
  • 36
  • I get that it is easier to read, but both 1 and 2 will require a check for a variable each time, so the code will almost equally be littered by it. – Jeroen Vannevel Aug 02 '13 at 04:15
  • Possibly, but if you are `sure` the returned object will always be in a valid state you do not really need defensive checks and such. – rocketboy Aug 02 '13 at 04:21
1

I suggest you make a condition that will prevent the program to proceed to that method if the inputs are invalid then, notify the user. By that, you don't have to adjust the object point.

0

Your second option seems ideal...

It is true you do not want to return null if some conditions aren't met - null doesn't mean "does not exist", it basically implies an escape sequence.

Exceptions typically are only thrown when internal computations are preformed (attempting to read a file that doesn't exist, formats of particular variables, etc.) Throwing an exception alerts the user something illegal was performed...not finding an intersection doesn't mean something illegal was found, but rather, it returns false.

It would be much 'cleaner' to call a boolean function to first test if a particular intersection exists, if so, then call your next function to find it.

Another option would be an else statement, after all iterations of findIntersect() runs...if intersection found, return it, else return some other object indicative of no intersection (ex. -1,-1)

Hope this helps.

  • 2
    _"It would be much 'cleaner' to call a boolean function to first test if a particular intersection exists, if so, then call your next function to find it."_ I disagree. I don't think that's clean at all, and it's doing double the work. Additionally, an object indicative of no intersection could not have real-valued coordinates (such as `(-1, -1)`) since the real Cartesian plane is infinitely large. The only sensible "null object" result I could see is `(NaN, NaN)`, or `(∞, ∞)`. – Matt Ball Aug 02 '13 at 04:15
  • Yea that is true. I've seen it before where exceptionally large integers are returned when implying something "out of the ordinary" is found...such as in directed acyclic graphs, I've had professors use max ints to indicate ∞ (or no path from (u,v))...could be considered sloppy in some instances. Regardless, I think the second option of returning some object that doesn't satisfy an 'intersection' is ideal in MOST cases... – stark102088 Aug 02 '13 at 04:21