7

I have some function works with database. I have set a try/catch for error handling here, and display a message, It works fine.

Now the class calling this delete function need to know if there is a error or not. In my case : refresh the GUI if success, nothing to do if fail (as there already show up a message message dialog).

I come up a idea to return boolean in this function.

public static Boolean delete(int id){

    String id2 = Integer.toString(id);
    try {
        String sql = 
                "DELETE FROM toDoItem " +
                "WHERE id = ?;";
        String[] values = {id2};
        SQLiteConnection.start();
        SQLiteConnection.updateWithPara(sql, values);
    } catch (SQLException e) {
        Main.getGui().alert("Fail when doing delete in DataBase.");
        System.out.println("Exception : "+ e.getMessage());
        return false;
    }
    return true;
}

Don't know if this is good or bad, please tell.


EDIT :

Here is more detail for How do I use :

Let's say the code above is inside Class A, in Class B :

public boolean deleteItem(int id){
    int i = index.get(id);
    if(theList[i].delete()){  //<---- here is the function from Class A
        theList[i] = null;
        index.remove(id);
        retutn true;
    }
    retutn false; 
}

I need to pass the boolean in more than one class, I don't know if that can better through...

in Class C :

public void toDoList_deleteItem(){
    MyButton btn = (MyButton)source;
    int id = btn.getRefId();
    List toDoList = Main.getToDoList();
    if(toDoList.deleteItem(id)){  //<-------function in Class B
        Main.getGui().refresh();
    }
}

Edit 2 :

I have notice the question is somehow more likely asking "What should I handle a Exception at database Layer that affect to GUI Layer ?"... Something like that. Please correct me if the question title should be edit.

user3662467
  • 163
  • 1
  • 2
  • 7

5 Answers5

11

It looks like you are returning a boolean status to indicate that an exceptional condition had occurred. Generally, this is not a good practice, for two reasons:

  • It encourages an error-prone way of handling exceptions - it is very easy to miss a status check, leading to ignored errors
  • It limits your API's ability to report errors - a single pass/fail bit is not always sufficient, it may be desirable to pass more information about the error.

A better approach would be to define an application-specific exception, and use it in your API. This forces the users of your API to pay attention to exceptional situations that may happen, while letting you pass as much (or as little) additional information as you find necessary. At the same time, your code does not get polluted with if (!delete(id)) { /* handle error */ } code on each API call, shrinking your code base, and improving its readability.

Can you tell me more about "define an application-specific exception", or show some code example please?

Here is how I would do it:

public class DataAccessException extends Exception {
    ... // Define getters/setters for passing more info about the problem
}
...
public static void delete(int id) throws DataAccessException {
    try {
        ... // Do something that may lead to SQLException
    } catch (SQLException se) {
        // Do additional logging etc., then
        throw new DataAccessException("Error deleting "+id, se);
    }
}

Note: It is common to give custom exceptions four constructors mirroring the constructors of the Exception class to allow exception chaining. The constructors are described here.

Community
  • 1
  • 1
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Perfect answer. +1 for pointing out *why* this is a bad idea. – Duncan Jones Feb 25 '15 at 14:32
  • Can you tell me more about "define an application-specific exception", or show some code example please? while there is no `if (!delete(id)) { /* handle error */ }` what I need is add `throws MyOwnException` in the first line of function, is that right ? – user3662467 Feb 25 '15 at 14:34
  • @user3662467 Why don't you research that topic? There will be a lot of information online. If you opt for a checked exception, you'll need `throws MyOwnException` in every method up-the-chain where you don't want to handle it. – Duncan Jones Feb 25 '15 at 14:36
  • +1. I agree.. In most general scenarios it is better to use an app specific exception..provided we use it in some way :P – TheLostMind Feb 25 '15 at 14:46
  • Nice. I suggest you modify the example to give `DataAccessException` a constructor so that the exceptions can be chained. – Stuart Marks Feb 25 '15 at 15:00
4

As long as you do not want the caller to know what happens, just that it fails (and that failing is part of its intended behavior) you should be fine.

That being said, I am noticing this: Main.getGui().alert("Fail when doing delete in DataBase.");.

It would seem that you are accessing the GUI layer from some other place. This might cause issues should you decide to multi-thread your application. Also, it is usually considered good practice to have your layers not intersect.

npinti
  • 51,780
  • 5
  • 72
  • 96
  • Thanks for telling me calling `Main.getGui().alert()` should be consider more. – user3662467 Feb 25 '15 at 14:48
  • Ideally, your method would still return an exception. If you do not want to provide extra data, you could create your own exception and throw that. This way, the calling layer (presumably the UI), can handle and show what ever messages it would deem fit. – npinti Feb 25 '15 at 15:00
3

Don't return a Boolean, return a boolean. Since this is not an exception / error condition, it is fine.

TheLostMind
  • 35,966
  • 12
  • 68
  • 104
  • +1 for the 1st part, -0.4 for the 2nd part. It is maybe not an error condition, but if it must be dealt with appropriately (that depends on the program), an exception might indeed be appropriate. – glglgl Feb 25 '15 at 14:24
  • @glglgl - His edited code is `if(theList[i].delete()){ ` it makes sebse to return true or false instead of throwing an exception. He is eventually doing the same thing in the caller as well – TheLostMind Feb 25 '15 at 14:32
  • 2
    I disagree with your "since this is not an exception / error condition, it is fine" statement, hence my down-vote. To me it seems clear that the OP is misusing boolean return values in lieu of proper exception handling. – Duncan Jones Feb 25 '15 at 14:34
  • @Duncan - **In my case : refresh the GUI if success, nothing to do if fail (as there already show up a message message dialog).** . The OP is actually handling an exception but not *propagating* it which is fine.. Why send it up put another catch block and do the same thing in the caller? .. BTW +1 for actually telling me why you down-voted :P – TheLostMind Feb 25 '15 at 14:37
  • I am a beginner (dont know if i am correct ) but I may concern that's a error somehow ... – user3662467 Feb 25 '15 at 14:39
  • 1
    @TheLostMind That's true, I guess. But then I'd argue that it's not best practice to reach out to the GUI from within the database layer. I also don't think it's great design to have the application keep limping on when potentially all further database access is borked. – Duncan Jones Feb 25 '15 at 14:40
  • @TheLostMind so whenever all things about the exception is handled/done , It's ok for return boolean ? – user3662467 Feb 25 '15 at 14:41
  • @Duncan - We would not have had this argument if the *exception meant something* and was being handled in some *particular way* :P. But in this case, I think it is better to abstract the exception because there is nothing to be achieved by allowing it to go to higher levels – TheLostMind Feb 25 '15 at 14:43
  • @user3662467 - Considering your current design, I think it is fine.. But *Duncan* and *DasblinkenNight* are not wrong :P – TheLostMind Feb 25 '15 at 14:44
3

Exceptions should be used when you don't expect a failure.

In your case, if it's fine for you that a SQLException is thrown and does not affect your program, it's ok to return a boolean.

If the SQLExcetion causing the delete to fail can cause problems in another part of your application it's better to throw an exception.

Edit:

Based on your edits, it seems that you are doing some maintenance and cleaning when an error happens. In such a case I would recommend to use Exceptions better than using booleans to control the execution.

antonio
  • 18,044
  • 4
  • 45
  • 61
1

This question is primarly opinion based. Personally I would prefer not to catch the exception at that point.

Depending on what the caller of delete() should do, you might need other resulutions. So you should better add a throw statement and let the calling method decide if the error is critical - or if it can proceed.

Just true and false is not necessary enough to let the caller decide correctly. He won't know if deletion fails due to database errors, due to foreignkey constraints, or something else.

letting the exception bubble up the call stack will provide the caller with the exact error going on, increasing the chance to handle the error in a proper way, or just displaying a custom error message helping the user to take proper actions.

dognose
  • 20,360
  • 9
  • 61
  • 107