Keeping stacktrace out of it, lets say that the idea of 'error' is a problem that you didn't want to occur, but did.
If I were to use a boolean system to check if the action successfully completed, it would look something like this:
String[] array = new String[10];
int i = 0;
public boolean accessValue(int id) {
if(id < array.length) {
//do something
return true;
}
return false;
}
while(true) {
if(!accessValue(i++)) {
//tend to situation
}
}
If I were to use Exceptions, it would look like this:
class InvalidAccessException extends Throwable {
}
public boolean accessValue(int id) throws InvalidAccessException {
if(!id < array.length || !id >= 0)
throw new InvalidAccessException();
//do something
}
while(true) {
try {
accessValue(i++);
}catch(InvalidAccessException e) {
//tend to situation
}
}
The only thing that matters to me is that when a problem occurs, I'm notified in some way, and I will have an option to handle the situation. Which way is more practiced? Does it just depend on the situation, or are there reasons for picking one over the other?
The first approach you mention, is more C oriented, in which you have functions yielding various integers to denote how did the function fair during its execution.
Although this worked it (in my opinion) introduced extra problems where the developer would need to go through other documentation or other developer code to understand why was the particular value returned.
In Java, as far as I know the way to go is always to throw exceptions when something goes wrong (even when you expect it to go wrong). The obvious advantage of using exceptions is that the code is more readable, just by seeing your method signature I know what potential issues could your method cause. This would allow me to code quicker since I do not need to dig through your own documentation or code just to see what the behaviour of your method is (although I could potentially need to dig through documentation/code to see if I can find a solution to why is your code throwing exceptions).
Also, since Java does not have an implementation of a tuple to return error codes and values you would need to create your own which could affect code re usability and readability, which in my opinion is always something you should avoid.
EDIT:
What if my intention isn't to go back into my code and find where the
error was thrown to fix it. just wanted to be notified that an error
happened, in a way I can easily handle the situation in some way.
Rather than me going into the code and fixing it manually, I want to
be able to trigger another set of code (like a handleError() method),
which has an algorithm that will even things out. (whichever algorithm
I may choose). Will handling with Exceptions give me any advantage in
this case?
Yes it should since exception handling will allow you handle exceptional events, so in your code, you could have this:
while(true) {
try {
accessValue(i++);
}catch(InvalidAccessException e) {
//Execute algorithms here
}
}
Having a stack trace is helpful when, as you are saying, you are debugging a problem since it provides information of which methods where called when your program crashed. That being said, they are not the only benefit of using exceptions (as mentioned above).
Another potential problem I see with using return values is when different developers work on the same function. So you could have something like so designed by one developer:
function int doSomething()
{
//if it worked, yield 0
//else yield some number between 1 and 10
}
Then another developer comes along which believes that errors should have negative numbers and extends the above method,
function int doSomething()
{
//if it worked, yield 0
//else yield some number between 1 and 10
//something else went wrong, return -1
}
The above would mean that you would need to go through all other functions calling doSomething() and see that they now handle the case where the return value is negative. This is cumbersome and is also error prone.
EDIT 2:
I hope I am getting your point. I see this issue when you return true/false:
Assume this:
public boolean foo(arg1, arg2)
{
if(arg1 is invalid) return false;
if(arg2 is invalid) return false;
}
In the above example, what does false mean? Does it mean arg1 is invalid or arg2? What if you need to trigger different algorithms for different parameter validity?
Related
Recently, I can across some code that made me a little confused:
I was always under the impression that doing return this way was bad practice. For one, there is no way to know if something went wrong other than looking in the logs. I asked around a bit and the general notion seems to be that throwing an exception would lead to bad code because people may catch the exception and do nothing with it. Is this really a good reason to not throw an exception? If so, is there any other way that this can be handled?
public void checkThisOut() {
String str = null;
str = someMethodThatCanReturnNull();
if(str == null) {
//log error
return;
}
}
Another example would be the following: What is the difference between break and return in this context? Is one preferable over the other?
public void update() {
List<Object> objects = SomeClass.findObjects();
for( Object o : objects ) {
if( o.getSomething().equals("some value" ) ) {
o.doSomething();
return;
}
}
}
Throwing an exception with the intent that it is used to control flow (e.g. if(a) then do b, else if exception then do c) in your app is generally considered bad practice.
However in your first example, if you're expecting a result to be not null and you do receive a null, and if this is an unexpected error condition from which you can't continue, then this is a good example of when to throw an exception.
When code throws an exception, the caller has the choice how to react. If errors are just logged but not propagated to the caller - then the caller does not even know about the error.
Therefore that argument to not throw is nonsense. When you are afraid that other people write bad code - then you educate them to do better. You don't start writing bad code yourself. But when throwing an exception properly documented why and when that happens.
For the second case: no difference in resulting behavior. So style only - do what your team does normally.
Throwing an exception is not bad code. You just should not use exceptions for regular controlflow.
For your second example, break and return are equal, but I would use return as it does make the intention slightly clearer. If you want to do something after the loop, you can change it to break then.
throwing an exception would lead to bad code because people may catch the exception and do nothing with it
I disagree with writing bad code to avoid other bad code. If the null return value is indicates an error, then you should throw an exception.
For your second question: break and return don't make any difference here because there is nothing after the for loop.
It would make a difference if you add code after the for loop, in which case return exits the method completely, while break jumps at the end of the for loop.
None is better than the other, it depends on what you intent to do. Return is probably clearer and quickier (simpler to understand), but many people think that a method should only have a single return at its end and having two or more is bad practice (because it makes the code harder to understand)
Think what would seem the most logical to you if you had to return a value in case the object you are searching isn't found, like indexOf which returns -1: store the found item in a variable, break the loop and have a single return at the end, or have two return statements in the method. Both are correct ways to go.
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.
I have this piece of code:
private void myFunc(){
obj = doSomething();
//If value is found, doX()
//If value is not found, doY()
}
private obj doSomething(){
//Do some stuff
//Hit database to get some value
obj = db.getValue(); //This func throws an exception if no value is found
}
Now, my question is:
1. Should I do: doSomething() throws ValueNotFoundException and catch it in myFunc()
2. Or catch it in doSomething() and return null? (a very bad approach though). And then check for null in myFunc()
Update:
1. Value not found is something which is probable and not an error.
Well, is value not found something exceptional (indicating an error) or probable? If it is absolutely not possible that doSomething() can't find what it needs, this is an error. I guess myFunc() is not the right place to handle such error.
If doSomething() sometimes can't find this or that (because the input is incorrect, misconfiguration, etc.) then it should not throw an exception and let the client handle this expected situation. However null is not the best return value. Instead consider null-object design pattern or some wrapper like Option[T] in Scala.
This is one of the reasons why InputStream is not simply throwing EOFException when it reaches end of file. This is not an unexpected situation.
In Java I try to follow some techniques/naming conventions to make null more obvious:
private Obj tryReturningSomething()
private Obj returnSomethingOrNull()
Also you can always use JavaDoc to document possible return value. I agree returning null is not the best approach (e.g. when method returns a collection, I always return an empty one instead of null) but in your case it is still better than throwing an exception to be caught one stack frame above. This is wasteful, harder to maintain and read. Consider having two version - one returning null and one throwing an exception, wrapping the first one.
Exception handling was invented to handle errors, not to control the program flow.
A database lookup is a case where "no value found" is an expected occurrence. Exceptions are for handling exceptional circumstances that do not happen in normal use.
The cleanest way is to change your database API to return null on no value found. Then you do not have to worry about try/catch blocks at all and just propagate the null.
A nice side bonus is that using exceptions for flow control is relatively slow, so you will see nice performance improvements.
It's 6 of 1 and 1/2 dozen of another. It really depends on what you want to do with the end result and if doSomething() is going to be used outside of this single use-case. The advantage of not throwing an exception is that you can return a known value when the exception occurs.
Either approach is acceptable. The most important thing is that you document the behavior of your function.
If db.getValue() cannot return null, then the second option is probably easier. If it can, however, then you want a way to know whether the value is null or there is none.
Some standard library classes do it both ways, implementing one function that throws an exception and another that returns null.
I am planning to do something like this (documented here):
public class NullUser extends User {
public static final NullUser INSTANCE = new NullUser();
public static NullUser getInstance() {
return INSTANCE;
}
#Override
public boolean isAuthenticated() {
return false;
}
private NullUser() {
}
}
public User getUser() {
if (/*some condition*/) {
return user;
} else {
return NullUser.getInstance();
}
}
if (obj.getUser().isAuthenticated() {
// allow
}
I am no newb on OO programming, but I am faced with a puzzling situation. I have been given a program to work on and extend, but the previous developers didn't seem that comfortable with OO, it seems they either had a C background or an unclear understanding of OO. Now, I don't suggest I am a better developer, I just think that I can spot some common OO errors. The difficult task is how to amend them.
In my case, I see a lot of this:
if (ret == 1) {
out.print("yadda yadda");
} else if (ret == 2) {
out.print("yadda yadda");
} else if (ret == 3) {
out.print("yadda yadda");
} else if (ret == 0) {
out.print("yadda yadda");
} else if (ret == 5) {
out.print("yadda yadda");
} else if (ret == 6) {
out.print("yadda yadda");
} else if (ret == 7) {
out.print("yadda yadda");
}
ret is a value returned by a function, in which all Exceptions are swallowed, and in the catch blocks, the above values are returned explicitly. Oftentimes, the Exceptions are simply swallowed, with empty catch blocks.
It's obvious that swalllowing exceptions is wrong OO design. My question concerns the use of return values. I believe that too is wrong, however I think that using Exceptions for control flow is equally wrong, and I can't think of anything to replace the above in a correct, OO manner.
Your input, please?
These are IMHO two completely different things:
OO-vs.-non-OO design
and
exception-based-vs.-return-value-based design.
You can combine them in any way (although most developers would say that a non-OO design is only good for special tasks like algorithms.
With regard to your code base: I would recommend a holistic analysis of the whole software, and then some careful thinking whether doing away with the return codes is a good idea. Will the software be expanded in the future? Or is it just some dead wood lying somewhere to do one specific task?
I would recommend reading up on "refactoring" and "legacy code". People around me say "Working Effectively with Legacy Code" by Michael Feathers is a very solid and recommended book. So this could help you a lot.
Good luck!
But this is Java (not C++). So if you work with `codes' like that you ought to work with Enums. And using Enums (or integers, incidentally) you can use the switch() statement to improve code like that a lot.
public abstract class Example {
protected abstract ErrorCode test();
public void run() {
ErrorCode code=test();
switch(code) {
case OK:
System.out.println("All ok");
break;
case OOPS:
System.out.println("Oops, an error occurred.");
break;
case OTHER_ERROR:
System.out.println("A different error occurred");
break;
case UNKNOWN_ERROR:
System.out.println("Yet another, unknown error occurred.");
break;
}
}
public static enum ErrorCode {
OK, OOPS, OTHER_ERROR, UNKNOWN_ERROR;
}
}
This can be extended to give it some more Continuation Passing Style flavour; by defining a callback method for ErrorCode and calling that method instead of doing the switch() statement.
Of course using exceptions for control flow is not the right thing to do. They need to be handled separated from your actual program control flow.
The fact that an exception occurred means that there was an exceptional event in you application and swallowing it or turn it into a return value doesn't change that (meaning that as soon as you turned it into a return value you kind of used it for the control flow). Usually it is possible to avoid return values that indicate both success states and exceptional states (first step: by using enums and then gradually improving the OO design).
According to if-else approach, I'll bring just a hint if you'd like to go more OO here.
You definitely could use state pattern.
Class State{
public:
virtual void showInfo()=0;
}
class Iddle:public State{
public:
void showInfo(){
std.cout<<"I've just initialized"<<std.endl;
};
}
class Wrong:public State{
public:
void showInfo(){
std.cout<<"Something goes wrong"<<std.endl;
};
}
main()
{
boost::scoped_ptr<State> mystate = new Iddle();
mystate->showInfo();
.....
mystate.reset(new Wrong());
....
mystate->showInfo();
}
You can implement anything you want in desired states.
This way you will throw out if-elses.
This is the way your generic "catch" function could set the states.
This could be of course used by regular system tasks, so any main component would know what is the state, and what action should be proceeded.
Simplifies:
if you'll have an exception, set a state to Wrong, then kill the thread, stop the action or whatever object responsible for the failure.
You'll still have the state, you handled the exception in proper manner, but still have some states, which could be a basis for taking appropriate actions in another thread.
Generally consensus is that exceptions shouldn't be used for control flow. However, the Python community seems to think differently.
However, I think the fundamental issue that you have is one of clarity; catching exceptions in one method and converting each condition to some arbitrary numeric value make it very unclear what the code is trying to do.
Without seeing the called code that you mention it's difficult to suggest how to improve it. If it is dealing with genuine exceptional conditions then I would consider allowing those to be handled by the calling code and possibly rethrowing as whatever exception fits the purpose of the method.
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.