1

I'm getting started with Android app development and I am extremely surprised that an API like android.database.DatabaseUtils does not throw exceptions upwards when using its methods. I wonder what is the reason for, what I consider, a bad design. (There must be a reason..)

As an example here

with the method long execute()

public long execute() {

  if (mPreparedStatement == null) {
    throw new IllegalStateException("you must prepare this inserter before calling "+ "execute");
  }
  try {
    if (LOCAL_LOGV) Log.v(TAG, "--- doing insert or replace in table " + mTableName);
    return mPreparedStatement.executeInsert();
  } catch (SQLException e) {
    Log.e(TAG, "Error executing InsertHelper with table " + mTableName, e);
    return -1;
   } finally {
   // you can only call this once per prepare
   mPreparedStatement = null;
  }
}

So this method is catching the SQLException and, instead throwing towards the invoker this or another wrapped Exception, it is simply returning -1 and logging the error with logcat.

As a developer I find this quite shocking as if I am using this API and I get a value -1 I know that something went wrong but I don't know why something went wrong unless I check the logcat logs.

Maybe I'm mistaken, please let me know, but an API with a method that returns -1 for an operation is a poorly OO design when it could simple throw an exception if something goes wrong and let the developer handle that exception in the way he/she wants extracting all the details from the Exception object. Don't you think?

Is there any reason to do it that way?

I have integrated logback with my application and I was hoping not to need to use logcat for anything. But after seeing this API I'm afraid I will have to, somehow, export a filtered logcat into a file to see what went wrong when my app received a -1 executing something on SQLlite.

Any advise please? Am I missing something here?

Much appreciated!

diegosasw
  • 13,734
  • 16
  • 95
  • 159

1 Answers1

3

First, we are not Google engineers who wrote the code in the first place nor mind readers. We cannot know for sure why a piece of code was designed the way it was. But we can make educated guesses. Consider the following:

  • The database APIs build on top of sqlite3 C library. C has no exceptions and exceptional error conditions are signalled by other means, such as returning a special value such as -1.

  • From design point of view, an API in android.database package throwing an exception android.database.sqlite package would be exposing unnecessary implementation detail. ( Though there are other methods that expose such detail by using SQL* classes.) Wrapping the detailed exception in an API level exception as you mention would be better.

  • "Utils" classes in general tend not to be designed really. They are just collection of methods the developers found to be needing often. You don't have to use them.

  • Exception handling is relatively expensive in terms of performance. Returning a special value is much cheaper. Avoiding exceptions can be a good idea especially in low level code that gets executed often. Though this point is not that relevant for the code you linked since it contains a try-catch block in it.

  • Overall, Android sqlite APIs are not particularly exemplary design. I've written about some of its oddities before, for example here.

Community
  • 1
  • 1
laalto
  • 150,114
  • 66
  • 286
  • 303