给出以下代码:我们需要锁定模型,然后启动一个事务(可能会抛出异常,所以我们必须确保释放锁),然后做一些类似于获取数据库连接的东西(可能抛出异常),然后做一些可能抛出异常的东西,要求恢复事务。这是Java 6,因此我们没有Java 7的好东西。
SomeClass someMethod()
throws SomeException {
acquireWriteLock();
try {
startTransaction();
try {
DBConnection d = openDBConnection();
try {
doStuff(d);
commitTransaction();
} finally {
d.close();
}
} catch (SomeException e) {
handleSomeException(e);
revertTransaction();
throw e;
} catch (Throwable t) {
revertTransaction(); // Error: method must return a value of SomeClass
}
} finally {
releaseWriteLock();
}
}
这可以改写为更具可读性和更简洁吗?
只是为了好玩:当你看到以下内容时,你会怎么做?
DBConnection d = null;
try {
acquireWriteLock();
startTransaction();
d = openDBConnection();
try {
doStuff(d);
commitTransaction();
} catch (SomeException e) {
handleSomeException(e);
revertTransaction();
}
} finally {
d.close();
releaseWriteLock();
}
答案 0 :(得分:2)
如果切换到Java 7,可以大大简化它。否则,你应该做的事情可能并不多。
你可以尝试以下想法:
将数据库连接+事务管理+锁管理重构为公共基类中的通用方法,每个事务类型都有一个子类
将数据库连接+事务管理+锁管理重构为最终类中的常规方法,其中包含事务类型的接口和每个类的实现类。
然而,除非这种特殊模式被重复多次,否则这种重构可能是一个坏主意。 (你将创造一个本地成语,读者必须在意义变得明确之前学习成语。)
答案 1 :(得分:1)
如果不升级到Java 7,您可以将其中的一部分结合起来,这样您只需要一个try-catch。
SomeClass someMethod() throws SomeException {
boolean committed = false;
DBConnection d = null;
acquireWriteLock();
try {
startTransaction();
d = openDBConnection();
doStuff(d);
commitTransaction();
committed = true;
} catch (SomeException e) {
handleSomeException(e);
throw e;
} finally {
if( d != null ) d.close();
if( !committed ) revertTransaction();
releaseWriteLock();
}
}
诀窍是确保revertTransaction()和DBConnection.close()不会抛出任何东西,但如果你不能这样做,那么你可以将releaseWriteLock()放在另一个finally子句中。如果你真的想要进一步改进,你可以做一些Stephen C提到的重构。执行诸如获取/释放writeLock,启动/回滚事务以及打开/关闭DBConnection之类的操作是在基类或一些抽象操作类中完成的。