I've heard that using exceptions for control flow is bad practice. What do you think of this?
public static findStringMatch(g0, g1) {
int g0Left = -1;
int g0Right = -1;
int g1Left = -1;
int g1Right = -1;
//if a match is found, set the above ints to the proper indices
//...
//if not, the ints remain -1
try {
String gL0 = g0.substring(0, g0Left);
String gL1 = g1.substring(0, g1Left);
String g0match = g0.substring(g0Left, g0Right);
String g1match = g1.substring(g1Left, g1Right);
String gR0 = g0.substring(g0Right);
String gR1 = g1.substring(g1Right);
return new StringMatch(gL0, gR0, g0match, g1match, gL1, gR1);
}
catch (StringIndexOutOfBoundsException e) {
return new StringMatch(); //no match found
}
So, if no match has been found, the ints will be -1. This will cause an exception when I try to take the substring g0.substring(0, -1). Then the function just returns an object indicating that no match is found.
Is this bad practice? I could just check each index manually to see if they're all -1, but that feels like more work.
UPDATE
I have removed the try-catch block and replaced it with this:
if (g0Left == -1 || g0Right == -1 || g1Left == -1 || g1Right == -1) {
return new StringMatch();
}
Which is better: checking if each variable is -1, or using a boolean foundMatch to keep track and just check that at the end?
Generally exceptions are expensive operations and as the name would suggest, exceptional conditions. So using them in the context of controlling the flow of your application is indeed considered bad practice.
Specifically in the example you provided, you would need to do some basic validation of the inputs you are providing to the StringMatch constructor. If it were a method that returns an error code in case some basic parameter validation fails you could avoid checking beforehand, but this is not the case.
I've done some testing on this. On modern JVMs, it actually doesn't impact runtime performance much (if at all). If you run with debugging turned on, then it does slow things down considerably.
See the following for details
(I should also mention that I still think this is a bad practice, even if it doesn't impact performance. More than anything, it reflects a possibly poor algorithm design that is going to be difficult to test)
Yes, this is a bad practice, especially when you have a means to avoid an exception (check the string length before trying to index into it). Try and catch blocks are designed to partition "normal" logic from "exceptional" and error logic. In your example, you have spread "normal" logic into the exceptional/error block (not finding a match is not exceptional). You are also misusing substring so you can leverage the error it produces as control flow.
Program flow should be in as straight a line as possible(since even then applications get pretty complex), and utilize standard control flow structures. The next developer to touch the code may not be you and (rightly)misunderstand the non-standard way you are using exceptions instead of conditionals to determine control flow.
I am fighting a slightly different slant on this problem right now during some legacy code refactoring.
The largest issue that I find with this approach is that using the try/catch breaks normal programmatic flow.
In the application I am working on(and this is different from the sample you have applied), exceptions are used to communicate from within a method call that a given outcome(for instance looking for an account number and not finding it) occurred. This creates spaghetti code on the client side, since the calling method (during a non-exceptional event, or a normal use-case event) breaks out of whatever code it was executing before the call and into the catch block. This is repeated in some very long methods many times over, making the code very easy to mis-read.
For my situation, a method should return a value per it's signature for all but truly exceptional events. The exception handling mechanism is intended to take another path when the exception occurs (try and recover from within the method so you can still return normally).
To my mind you could do this if you scope your try/catch blocks very tightly; but I think it is a bad habit and can lead to code that is very easy to misinterpret, since the calling code will interpret any thrown exception as a 'GOTO' type message, altering program flow. I fear that although this case does not fall into this trap, doing this often could result in a coding habit leading to the nightmare that I am living right now.
And that nightmare is not pleasant.
Related
I am writing code to find and intersection of 2 lines.
When slopes of the lines are equal they dont intersect. But on the other hand an input with slopes of equal value is completely valid.
public static Point calculateIntersection(Line line1, Line line2) {
if (line1 == null || line2 == null) {
throw new NullPointerException(" some message ");
}
if (line1.getConstant() == line2.getConstant()) {
return new Point(0, line1.getConstant());
}
if (line1.getSlope() == line2.getSlope()) {
throw new IllegalArgumentException("slopes are same, the lines do not intersect.");
}
int x = (line2.getConstant() - line1.getConstant()) / (line1.getSlope() - line2.getSlope());
int y = line1.getSlope() * x + line1.getConstant();
return new Point(x, y);
}
The question is throwing illegal argument exception the right thing to do ?
Since input is valid, it does not completely convince me.
Is custom exception the right thing to do ?
Sounds like a good choice but an additional opinion would help.
Thanks
The question is is throwing illegal argument exception the right thing to do?
There is no single "right thing to do". It depends on how you want / need to "frame" this condition; i.e. is it a bug, a user input error, or something that the program is supposed to be able to deal with?
If the case of two lines not intersecting is unequivocally a "bug", then IllegalArgumentException is fine. This is what the exception is designed for. (Note that it is an unchecked exception, so the expectation is that it won't be caught / recovered from.)
If this is a case that you expect the program to be able to recover from by itself, then a custom exception is the best idea. That way, you reduce the possibility of your code getting confused by (say) a library method throwing (say) an IllegalArgumentException ... than means something other than "two lines intersected".
If this case is something that you expect to report to the end user as part of input validation, then a generic "validation error" exception might be more appropriate than a specific custom exception. However, this method doesn't look like it is designed to be used (solely) for user input validation.
In some contexts, it may be better to not throw an exception at all, but (IMO) this is not one of those contexts.
The alternatives to throwing an exception are returning null or returning a Point value that means "no such point" to the calling code. The problems with these alternatives are:
If you return null the application has to deal with the null case ... or there will be NPEs.
There is no natural Point instance that could be used to mean "not a point"1.
This is not to say that you couldn't make these alternatives work. It is just that in this context, it will probably be more work to do that, and probably there won't be a tangible pay-off.
1 - I am assuming Point is java.awt.Point or similar. Obviously you could define and use a custom Point class which provides a "no such point" instance. But it will come at a cost. And you will need to deal with the case where code accidentally uses the "no such point" instance in some computation. And you are probably back where you started; i.e. throwing an exception!
This almost certainly should not throw an exception, because it makes perfect sense to invoke a method like this with any two Line values. You have already appropriately handled null values.
You have also, very reasonably, defined the behavior of your class in one of the ill-defined input situations, namely two coincident "constant" (horizontal) lines, where you return the point at x=0 on that line. You ought to similarly select return values for the other cases of ill-defined inputs: coinciding vertical lines, coinciding lines that are neither horizontal nor vertical, and non-coinciding parallel lines.
In my opinion, the most natural result for the last case - non-coinciding parallel lines - would be null, reflecting the fact that there is no point of intersection.
It would then be up to the client to decide whether a null intersection warrants an exception, an error message, or whatever. E.g. an interactive shell prompting the user for lines to intersect would probably print an error message and ask the user to try again. Some more complicated calculation, e.g. a linear optimizer trying to define boundaries for its search, might want to throw IllegalArgumentException if the constraints giving rise to the parallel lines contradict each other.
Of course, the return values in all these cases (coincident lines or non-coincident parallel lines) should be precisely documented in the method's javadoc.
I'd say you do the right thing: you catch the condition early. It is either that or people will complain that "your program is buggy, look at this input data, division by 0".
Given that there will be no such error in 99+% of situations, this is an exceptional condition and doesn't grant declaring a checked exception, so an unchecked exception looks indeed like the right choice.
Now, as to whether IllegalArgumentException is the "good one", it is at least the closest exception describing this case... You can, if you feel you have a better name, always create your own one inheriting RuntimeException.
IF, on the other hand, this situation is not that infrequent, then maybe the logic to reach that function should be reviewed so as to never hit this condition in the first place.
As #Andy-Lowry and #KamikazeCZ say, this should not be an exception.
This method should not concern itself with whether the client expects lines to always intersect or not; it should only bother with finding the intersection of two lines -- something which inherently might not happen.
If the caller gets back a result indicating no-intersection, then THAT code can decide whether it's invalid-input because the end-user was duly warned, or something they can handle (perhaps by re-prompting), or throw a customized exception.
So, back to what should this method return? Some sort of sentinel value, the same way that indexOf returns -1 in the collections library. Returning null is a reasonable sentinel. In Java 8, you can return an Optional<Point>, to help remind the caller that there might not be a proper Point.
You have an additional problem, too: what somebody asks for the intersection of a line with itself? (Mathematically, the intersection of two lines is either 0 point, 1 point, or infinitely many points.) You might need to be able to return two sentinel values, which is more involved, in Java. This method could weasel out of the situation this time, by saying "in the case of multiple answers, this method may return any of them", or (what I'd probably do) "...returns the Point nearest the origin".
Btw, this thinking largely follows from a unit-test mindset: start by defining the correct answer should be for a variety of corner-case inputs, before launching into code and kinda committing yourself to a certain return-type etc.
Finally: when comparing the results of getSlope() using ==, beware floating-point roundoff errors. It might be the best thing to do here, but it's still problematic. The way you assume (or round) the intersection to ints, though, suggests you might have very special constraints/assumptions going on in your problem.
Keep in mind that a more generic version of this question was closed as primarily opinion-based.
If it were me, I would return null. In most cases you should not use exception handling as a form of flow control. Returning null would help avoid that for any code consuming your method.
Related Discussions:
Dont Use Exceptions For Flow Control
Should a retrieval method return 'null' or throw an exception when it can't produce the return value? [closed]
Are exceptions as control flow considered a serious antipattern? If so, Why?
Arguments for or against using Try/Catch as logical operators [closed]
Exceptions should be used to catch errors in program flow ("what happens inside") , not for input validation. I wouldn't throw an exception at all.
Think about it, this is not what "exception" means as it is completely normal for the user to input two lines with equal slopes.
I have found myself using the following practice, but something inside me kind of cringes every time i use it. Basically, it's a precondition test on the parameters to determine if the actual work should be done.
public static void doSomething(List<String> things)
{
if(things == null || things.size() <= 0)
return;
//...snip... do actual work
}
It is good practice to return at the earliest opportunity.
That way the least amount of code gets executed and evaluated.
Code that does not run cannot be in error.
Furthermore it makes the function easier to read, because you do not have to deal with all the cases that do not apply anymore.
Compare the following code
private Date someMethod(Boolean test) {
Date result;
if (null == test) {
result = null
} else {
result = test ? something : other;
}
return result;
}
vs
private Date someMethod(Boolean test) {
if (null == test) {
return null
}
return test ? something : other;
}
The second one is shorter, does not need an else and does not need the temp variable.
Note that in Java the return statement exits the function right away; in other languages (e.g. Pascal) the almost equivalent code result:= something; does not return.
Because of this fact it is customary to return at many points in Java methods.
Calling this bad practice is ignoring the fact that that particular train has long since left the station in Java.
If you are going to exit a function at many points in a function anyway, it's best to exit at the earliest opportunity
It's a matter of style and personal preference. There's nothing wrong with it.
To the best of my understanding - no.
For the sake of easier debugging there should be only one return/exit point in a subroutine, method or function.
With such approach your program may become longer and less readable, but while debugging you can put a break point at the exit and always see the state of what you return. For example you can log the state of all local variables - it may be really helpful for troubleshooting.
It looks like there a two "schools" - one says "return as early as possible", whereas another one says "there should be only one return/exit point in a program".
I am a proponent of the first one, though in practice sometimes follow the second one, just to save time.
Also, do not forget about exceptions. Very often the fact that you have to return from a method early means that you are in an exceptional situation. In your example I think throwing an exception is more appropriate.
PMD seems to think so, and that you should always let your methods run to the end, however, for certain quick sanity checks, I still use premature return statements.
It does impair the readability of the method a little, but in some cases that can be better than adding yet another if statement or other means by which to run the method to the end for all cases.
There's nothing inherently wrong with it, but if it makes you cringe, you could throw an IllegalArgumentException instead. In some cases, that's more accurate. It could, however, result in a bunch of code that look this whenever you call doSomething:
try {
doSomething(myList);
} catch (IllegalArgumentException e) {}
There is no correct answer to this question, it is a matter of taste.
In the specific example above there may be better ways of enforcing a pre-condition, but I view the general pattern of multiple early returns as akin to guards in functional programming.
I personally have no issue with this style - I think it can result in cleaner code. Trying contort everything to have a single exit point can increase verbosity and reduce readability.
It's good practice. So continue with your good work.
There is nothing wrong with it. Personally, I would use else statement to execute the rest of the function, and let it return naturally.
If you want to avoid the "return" in your method : maybe you could use a subClass of Exception of your own and handle it in your method's call ?
For example :
public static void doSomething(List<String> things) throws MyExceptionIfThingsIsEmpty {
if(things == null || things.size() <= 0)
throw new MyExceptionIfThingsIsEmpty(1, "Error, the list is empty !");
//...snip... do actual work
}
Edit :
If you don't want to use the "return" statement, you could do the opposite in the if() :
if(things != null && things.size() > 0)
// do your things
If function is long (say, 20 lines or more), then, it is good to return for few error conditions in the beginning so that reader of code can focus on logic when reading rest of the function. If function is small (say 5 lines or less), then return statements in the beginning can be distracting for reader.
So, decision should be based on primarily on whether the function becomes more readable or less readable.
Java good practices say that, as often as possible, return statements should be unique and written at the end of the method. To control what you return, use a variable. However, for returning from a void method, like the example you use, what I'd do would be perform the check in a middle method used only for such purpose. Anyway, don't take this too serious - keywords like continue should never be used according to Java good practices, but they're there, inside your scope.
Let say you have a method that checks if the argument (Answer) is correct and check if the question already have answers in the list that is also correct:
public void addAnswer(Answer answer) {
if (answer.isCorrect()) {
...
}
}
However, I only want one answer to be correct in the list. I have multiple options. I could throw an exception, I could ignore it, I could return some boolean value from the addAnswer that tells me if the operation was ok or not. How are you supposed to think in such scenarios?
The rule is pretty simple: Use exceptions on exceptional, erroneous, unpredicted failures. Don't use exceptions when you expect something to happen or when something happens really often.
In your case it's not an error or something truly rare that an answer is not correct. It's part of your business logic. You can throw an exception, but only as part of some validation (assertion) if you expect an answer at given point to always be correct and suddenly it's not (precondition failure).
And of course if some failure occurs while checking correctness (database connection lost, wrong array index) exception are desired.
This entirely depends on what you want to achieve. Should the caller of your method already have made sure that it doesn't add two correct answers? Is it a sign of a programming error if that happens? Then throw an exception, but definitely an unchecked exception.
If your method's purpose is to relieve the caller from enforcing the one-true-answer invariant (I doubt that, though), then you can just arrange to signal via a boolean return value, which makes it only an optional information channel for the caller.
If there is no way to know in advance whether there are other correct answers—for example, the answers are added concurrently from several threads or even processes (via a database)—then it would be meaningful to throw a checked exception.
Bottom line: there is no one-size-fits-all best practice, but there is a best practice for every scenario you want to accomplish.
The exception police will be down on you like a ton of bricks, and me for this answer, with statements like "don't use exceptions for flow control" and "don't use exceptions for normal conditions".
The trouble with the first statement is that exceptions are a form of flow control. This makes the argument self-contradictory, and therefore invalid.
The trouble with the second statement is that it seems to inevitably go along with endlessly redefining exceptional conditions as normal. You will find examples in this very site: for example, a lively discussion where the police insisted that EOF was 'normal' and therefore that EOFException shouldn't be caught, despite the existence of dozens of Java APIs that don't give you any choice in the matter. Travel far enough down this path and you can end up with nothing that is exceptional whatsoever, and therefore no occasion to use them at all.
These are not logical arguments. These are unexamined dogmas.
The original and real point, back in about 1989 when it was first formulated, was that you shouldn't throw exceptions to yourself, to be handled in the same method: in other words, don't treat it as a GOTO. This principle continues to have validity.
The point about checked exceptions is that you force the caller to do something about handling them. If you believe, on your own analysis, that this is what you want, use an exception. Or, if you are using an API that forces you to catch them, catch them, at the appropriate level (whatever that is: left as an exercise for the reader).
In other words, like most things in the real world, it is up to your discretion and judgment. The feature is there to be used, or abused, like anything else.
#Exception police: you will find me in the telephone book. But be prepared for an argument.
An exception thrown from a method enforces the callers to take some action in the anticipation of the exception occurring for some inputs. A return value doesn't enforce the same and so it is up to the caller to capture it and take some action.
If you want the callers to handle the scenario to take some corrective action, then you should throw a checked exception (sub class of java.lang.Exception).
The problem here is that your API is error prone. I'd use the following scheme instead:
public class Question {
private List<Answer> answers;
private int mCorrect;
// you may want a List implementation without duplicates
public void setAnswers(List<Answer> answers, int correct) {
this.answers = answers;
// check if int is between bounds
mCorrect = correct;
}
public boolean isCorrect(Answer answer) {
return answers.indexOf(answer) == mCorrect;
}
}
because an Answer by itself is simply a statement, and usually cannot be true of false without being associated to a Question. This API makes it impossible to have zero or more than one correct answers, and forces the user to supply the correct one when he adds answers, so your program is always in a consistent state and simply can't fail.
Before deciding how to signal errors, it's always better to design the API so that errors are less common as possible. With your current implementation, you have to make checks on your side, and the client programmer must check on his side as well. With the suggested design no check is needed, and you'll have correct, concise and fluent code on both sides.
Regarding when to use a boolean and when to use Exceptions, I often see boolean used to mirror the underlying API (mostly low level C-code).
I agree with Tomasz Nurkiewicz's response. I cant comment on it because I'm a new user. I would also recommend that if the addAnswer() method is not always going to add the answer (because they already exists a correct one), name it to suggest this behaviour. "add" is suggest normal collections behaviour.
public boolean submitAnswer(Answer answer); // returns true is answer accepted
Your exact solution may depend on the bigger picture about your application that we dont know about. Maybe you do want to throw an Exception but also make it the responsibility of the caller to check if adding the Answer is valid.
It's all a rich tapestry.
I would implement it in this way:
public class Question {
private int questionId;
private final Set<Answer> options = new HashSet<Answer>();
private final Set<Answer> correctAnswers = new HashSet<Answer>();
public boolean addAnswer(Answer answer) throws WrongAnswerForThisQuestionException {
if(!answer.isValid(questionId)) {
throw new WrongAnswerForThisQuestionException(answer, this);
}
if (answer.isCorrect(questionId)) {
correctAnswers.add(answer);
}
return options.add(answer);
}
}
I've heard people advise that one should always use the Iterator pattern to control loops rather than throwing an exception (which is how it's done in Python iterators) or using the Sentinel pattern, whereby a special, sentinel value (often null) is returned to indicate the end of the iteration.
Does best practice advise against the sentinel pattern? If so, why? (other than it not working with the foreach syntax in Java 1.5).
Edit:
Code example 1 - Sentinel Pattern
Reader r = ...;
for( int val = r.read(); val != -1; val = r.read()) {
doSomethingWith(val);
}
Code example 2 - Iterator Pattern
for(Iterator<Thing> it = getAnIterator() ; it.hasNext(); ) {
Thing t = it.next();
doSomethingWith(t);
}
The issue with the Sentinel pattern is that it explicitly excludes the sentinel value from the set of values that are valid elements. I.e., if you have a list of objects which can validly contain null as an element, using null as a sentinel value is a fail.
Exceptions should only be used in "exceptional" situations. Concluding or breaking out of a loop is normal program flow, not an exceptional situation.
Additionally, when working in Java, (or any language for that matter), you want to use patterns and conventions that are common and well known in the community because other Java programmers may need to maintain your code. If they do, they will most likely expect to see Iterators, not the sentinel pattern.
I think they're both ok but the Iterator is more idiomatic in Java (particularly if you actually have an Iterable that you can use the for-each loop on instead).
The one place you do see the Sentinel version a lot in Java is exactly the case you've written in I/O code.
The mantra is "say what you do, and do what you say."
If you test the returned value for being a special value, that says nothing about why you test this. In your example:
for( int val = r.read(); val != -1; val = r.read()) {
doSomethingWith(val);
}
Does this say "if the returned value ever becomes -1, we can skip the rest", or "if the returned value ever is -1, an error has occurred", or "if the returned value ever is -1, the end is reached"? In contrast, hasNext is completely unambiguous.
By the way, I actually like the foreach and map constructs other languages provide (or allow to write) better than explicit looping.
The Sentinel pattern is used in the JDK for reading streams, so it isn't unheard of, but it is awkward to make a loop out of. All solutions have negatives that an iterator doesn't. Your solution requires a repetitive call to read (that is code duplication). A while loop forces the variable to be declared outside the scope of the loop. Other alternatives would be surprising and hard to follow.
So in the end the iterator is kind of the default that should only be deviated from for a reason.
I don't see how the Sentinel Pattern is different enough to be its own pattern. My only thought is that it would be useful for determining a stop value from streaming data. However, the interator takes care of this with the "hasMore" method requirement.
"Exceptions should only be used in "exceptional" situations. Concluding or breaking out of a loop is normal program flow, not an exceptional situation."
If a file read succeeds a million times and only the last time it says "I can't find any more records", you don't call that "exceptional" ?
I don't see the problem in using, say, EOFExceptions for control flow (if the System is sane enough to raise them, instead of returning that awfully stupid -1 integer saying that "-1 bytes were read"). You tell me if the following is unreadable/unmaintainable :
try {
r = readNext(...);
process(r);
} catch (EOFException e) {
...
}
Sounds like a stupid question with an obvious answer :)
Still I've ventured to ask just be doubly sure.
We are indeed using asserts like given below
ArrayList alProperties = new ArrayList();
assert alProperties != null : "alProperties is null";
Problem is that making a small & simple document to follow, on asserts is difficult. There are many books on asserts, but ideally I like to give a new programmer very simple guidelines on using something like asserts. Btw, does some tool like pmd check for proper usage of asserts?
Thanks in advance.
There's no sane reason to use asserts like that. If the object won't be created for some reason, your assert won't even be reached (because an exception was thrown or the VM exited, for example)
There are some fairly concise guidelines on using assertions in Sun's Programming with Assertions. That article advises that asserts should be used for things like Internal Invariants, Control-Flow Invariants, and Preconditions, Postconditions, and Class Invariants.
No , you don't want to check object creation.
If the object creation fails, the jvm will throw an OutOfMemoryError, and if that happens you're likely to be screwd beyond repair anyway.
that's like not trusting the JVM. Concerning what you take as a given, you got to draw a line somewhere...
This assert only clutters your code, it would be equivalent to this assert:
boolean a = true;
assert a : "A should be true"
You shouldn't be testing your JVM, unless that's the point of your program (say, it's a test suite for a JVM you are making). Instead you should be testing your pre-conditions, post-conditions and invariants. Sometimes these tests are too basic or too expensive.
Pre-conditions probably should only appear at the start of a method (if your have very long methods, then you should break that method into small parts, even if they are all private).
Post-conditions should make it clear what you have returned to the caller, you don't test that the sqrt function just returned the sqrt, but you might test that it was positive to make it clear what you are expecting (perhaps later code uses complex numbers and yours is not tested for that). Instead leave a comment at the bottom.
Invariants also often can't be tested, you can't test that your current solution is the correct partial solution (see below) -- though this is one of the nice things about writing things with tail-recursion. Instead, you declare the invariant with a comment.
If you are calling things externally, you would also use an assert, for instance in your example if you had ArrayList.Create(), then you might choose the assertion check for null. But only because you don't trust the other code. If you wrote that code, you could put the assertion (comment or otherwise) in the factory method itself.
int max(int[] a, int n) {
assert n <= a.length : "N should not exceed the bounds of the array"
assert n > 0 : "N should be at least one"
// invariant: m is the maximum of a[0..i]
int m = a[0];
for( int i = 1; i < n; n++ ) {
if( m < a[i] )
m = a[i];
}
// if these were not basic types, we might assert that we found
// something sensible here, such as m != null
return m;
}
In Java each call to new returns either a non-null reference to the new object or raises an Exception or an Error. In the first case your assert is true, in the second case the assert will not be reached, because you end in the next matching catch-block.
This assert tests if your Java-implementation is broken and in this case you can't even rely on the assert. So I would not make such asserts. Use assert for restrictions on objects, that aren't enforced by the language (for instance, if your method is passed a parameter that is null but shouldn't be).
I'm not sure of complete understand your question but i think that assertions of that kind aren't neccesary.
When you create an instance, if the program flow continue, the instance isn't a null reference.
You want ASSERTS to check properties or invariants of your program. A good document to teach this should encourage the programmer to think about such properties in a systematic/methodical manner.
if the assert fails, believe me, you're going to have bigger problems than just dealing with the assert.
If that assert fails I think it's time I look for another job because the computer is not behaving how it's supposed to and when that happens all hell is going to break loose!