Re: How to initialise a final static String array
Arne Vajh??j wrote:
Lew wrote:
Static JDBC connections, and especially static JDBC statements, are a
very bad idea.
Very bad.
Statements should be local in scope, not even instance level. (Usually.)
Even connections should only be instance members if you have rather
short-lived objects holding them.
At least in the server world with connection pools.
For a desktop app I would say that it depends on the specific app.
Fair enough.
The overarching point being to consider thoughtfully the various issues of
scope and lifetime as you construct your implementation.
Even with connection pools the usual perspective for connections' consumers is
virtual exclusivity. The client pretends it has exclusive access to the
connection as if it were brand new from the time of the client's acquisition
of the connection and unsullied by anyone else until its release. The pool
manager works hard to give the client this illusion.
In such a world view, the client holds the same responsibilities to manage
connection lifetime regardless of the underlying mechanism.
In most practical systems, a connection is a rather precious resource. The
very word "resource" in computer systems means something that must be managed,
of limited availability, that must be released when not needed, in short,
something precious.
That's why a static resource is often poisonous. It lasts as long as the
class, and might never formally be released. And it risks reuse in
inappropriate scenarios.
An instance-level connection that lives as long as its containing object is an
interesting idiom. It works to hide messy acquisition/release mechanics from
its own clients. From a lifetime standpoint. it only defers the timing
decision to the next client up the chain.
At some level, the connection must be acquired. Like matching parentheses,
each acquisition must pair with a resource release, somehow, somewhen.
The guarantee of such release is the province of the 'finally' block. Making
the proper guarantees can be rather verbose at times, but are worth it in
system reliability and scalability. (When such considerations apply. But even
when they don't, the same idioms are simple enough that there's no reason to
avoid them.) Such pairing of resource acquisition with reliable release is
best done (again, usually) with local variables.
You control lifetime to the time of the service, from request to response. (I
just laid a whole world of assumption about service architecture under that
one sentence.)
Sure, the notion isn't truly universal. But if you understand this
architecture, you can readily understand Arne's comment and why the scenario
he proposed doesn't need the safety of such idioms. He understands lifetime to
know why class-level works in that situation.
I have a ritualistic approach to certain programming layers. For resources
it's what's officially called RAII (Resource Acquisition Is Initialization),
but I call RRID (Resource Released If Destroyed). Java doesn't support this
intrinsically, so to use it you wrap resources in a guaranteed
release-when-done idiom.
Here's a rough, never-compiled example. It's rather formal, but it does seem
to guard against the crap. (All the missing stuff left as an exercise for the
reader.)
package eegee.query;
import apache.log4j.Logger;
import static apache.log4j.Logger.getLogger;
import eegee.connection.Connection;
import static eegee.connection.Connection.getManager;
import eegee.entity.Entity;
import eegee.entity.Key;
import static eegee.entity.Entity.ENTITY_QUERY;
public class RridIdiomizer
{
private static final Connection.Manager manager = getManager();
private final Logger logger = getLogger(getClass());
public Entity lookUp(Key key)
{
final Connection cxn;
try
{
cxn = manager.acquireConnection();
}
catch (IOException exc) // no need for RRID if nothing acquired
{
final String msg = "lookup() connection failure";
logger.error(msg, exc);
throw new IllegalStateException(msg, exc);
}
assert cxn != null; // I love assertions, but they're subtle
// here's the RRID - perforce release 'cxn' ere it leave scope
try
{
Entity entity = cxn.prepareQuery(ENTITY_QUERY, key).execute();
return entity;
}
catch (IOException exc)
{
final String msg = "lookup() query failure";
logger.error(msg, exc);
throw new IllegalStateException(msg, exc);
}
finally // the RRID part
{
cxn.close();
}
}
}
--
Lew
Honi soit qui mal y pense.
http://upload.wikimedia.org/wikipedia/commons/c/cf/Friz.jpg