ARM is trying to solve the age old problem of ensuring closure of resources when finished with your business logic. In C++ we would use RRID (Resource Release Is Destruction) to accomplish this. e.g.
template<typename T>
class LockEnforcer : public boost::noncopyable<LockEnforcer>{
T& lock;
public:
LockEnforcer(T& lock) : lock(lock) { lock.lock(); }
~LockEnforcer() { lock.unlock(); }
}
//Later in a method....
{
LockEnforcer(someLock);
//Do my business logic
}
//Lock is shut down here by nature of Destruction
This suffered from a few problems:
- Destructors should not throw exceptions! (Read Effective C++). This could leave you in a dangerous state potentially if you cared whether or not "close" threw some exception.
- The destruction behavior ALWAYS happens. If you wanted to change whether or not cleanup occurs, you have to put state into the class and some more complex logic in the destructor. You also need to make calls on the class to inform it *not* to do the usually cleanup.
Java steps in lacking destructors, and forces developers to take a new paradigm. Let's look at a typical Java JDBC connection usage paradigm.
Connection conn = null;
try {
conn = getConnection();
//Business Logic
} finally {
try {
if(conn != null) {
conn.close();
}
} catch(SQLException e) {
//Ignore - that way if we already had an exception, we don't lose it on close.
}
}
Now, I have potentially buggy code everywhere I need to use connections. I'm also not able to re-use code easily. Now, the Spring framework truly does solve this problem (see any of the *Template classes), but we'll get to how and why it's useful later. For now, assume we're stuck with pure java (or we're in a domain that isn't covered by Spring yet). Coin proposes the following ARM syntax:
try (Connection conn = getConnection()) {
//Business Logic
}
This would be equivalent to the above block. It is much nicer, and certain helps in the general case of resource management. Using multiple resources would of course imply multiple try blocks.
The problem is that this doesn't solve the more general problem. The general problem is that you have code that is duplicated across several methods. This code needs to run before and after some non-duplicated section. Take for example the following:
try {
if(isNewMessage(msg)) {
handleMessage(msg);
}
sendMessageAcknowledgement(msg); //Note this is *not* in the finally
} catch (Exception e) {
//Do something with exceptions
}
I'm unable to use ARM because I want the final code (before the catch) to be run if the above code passes without exception. The other problem here is that I have 5 methods with this same boiler-plate (except same isNewMessage function), and different handleMessage functions. Typically, Java encourages you to create a base class, with abstract handleMessage. Then you extend classes with different handleMessages. That's pretty much the only way to reuse code here. What if I don't really want other classes?
Well, Scala comes to the rescue (slightly). Scala will let me write the above code using functional composition, and behind the scenes it's desugaring to multiple classes that inherit the "Function" interface.
Note: That the Spring *Template classes take this approach, only with less generic interfaces. Instead of "Function1", it's SqlRowMapper.
Here's an example in scala.
//Helper function
def processMessage(msg : Msg)(handlerFunction : Msg => Unit) = {
try {
if(isNewMessage(msg) {
handlerFunction(msg)
}
sendAcknowledgement(msg)
} catch {
case e => //TODO - Handle
}
}
//My actual method
processMessage(msg) {
msg =>
//Business Logic
}
As you can see, I've removed duplicate code, and without a lot of boilerplate. ARM would not be necessary if Java had closures, and the entire set of problems (not just resource management) revolving around repeated code at start/end of blocks would also be solved. Personally, I would rather just wait for Java to have closures.