我开始使用Android应用程序开发,我非常惊讶像android.database.DatabaseUtils这样的API在使用其方法时不会向上抛出异常。我想知道是什么原因,我认为是一个糟糕的设计。 (必须有理由......)
作为示例here
方法 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;
}
}
所以这个方法正在捕获SQLException,而是向调用者抛出这个或另一个包装的Exception,它只是返回-1并使用logcat记录错误。
作为一名开发人员,我觉得这很令人震惊,好像我正在使用这个API而且我得到一个值-1我知道出了什么问题,但我不知道为什么出现问题,除非我检查logcat日志。
也许我弄错了,请让我知道,但是一个带有返回-1的操作的API的API是一个糟糕的OO设计,如果出现问题可以简单地抛出异常并让开发人员以他/她想要从Exception对象中提取所有细节的方式处理该异常。你不觉得吗?
有没有理由这样做?
我已将logback与我的应用程序集成在一起,我希望不需要使用logcat进行任何操作。但在看到这个API之后,我恐怕不得不以某种方式将过滤后的logcat导出到一个文件中,看看当我的应用程序收到-1在SQLlite上执行某些操作时出了什么问题。
有什么建议吗?我在这里错过了什么吗?
非常感谢!
答案 0 :(得分:3)
首先,我们不是谷歌工程师,他们首先编写代码,也不介意读者。我们无法确切知道为什么一段代码按原样设计。但我们可以做出有根据的猜测。请考虑以下事项:
数据库API构建于sqlite3 C库之上。 C没有例外,异常错误条件通过其他方式发出信号,例如返回特殊值,例如-1。
从设计的角度来看,android.database
包中抛出异常android.database.sqlite
包的API会暴露不必要的实现细节。 (尽管还有其他方法通过使用SQL*
类来公开这些细节。)
如您所述,将详细异常包含在API级异常中会更好。
"的Utils"一般来说,课程往往不是真正的设计。它们只是开发人员经常需要的方法集合。你不必使用它们。
在性能方面,异常处理相对昂贵。返回特殊值要便宜得多。避免异常可能是一个好主意,尤其是在经常执行的低级代码中。虽然这一点与您链接的代码不相关,因为其中包含try
- catch
块。
总的来说,Android sqlite API并不是特别典型的设计。我以前曾写过一些奇怪的事情,例如here。