Hi,

I'm new to Cassandra and felt like exploring and hacking on the code. I
was surprised to see the usage of so many mutable/global state statics
all over the service package (basically global variables/singletons).

While I understand it can be practical to work with singletons, and that
in any case I'm not sure multi-tenant Cassandra (as in two different
Cassandra instances within the same process) would make sense at all (or
even work considering there is some native access going on with JNA), I
find static state can easily lead to tangled 'spaghetti' code (accessing
the singletons from anywhere, even where one shouldn't), and in general
it ties the code to the VM instance, rather than to the class.

I tried to find if it was an actual design choice, but from my
understanding this is more something inherited from the early Cassandra
times at Facebook. I just found this thread[1] pointing to issue
CASSANDRA-741 (slightly more limited scope) that was marked as WONTFIX
because no one took it (but still marked as open for contribution). The
current code conventions also don't mention the usage of singletons
except by stating:  "Do not extract interfaces (or abstract classes)
unless you actually need multiple implementations of it" (switching to a
"service"-style design doesn't require passing interfaces but it's
highly encouraged to help testability).

So, I'd like to try to make this refactoring happen and remove all (or
most) mutable static state. It would be an easy way in for me in
Cassandra's internals (maybe to contribute further). I think it would
help testing (ability to unit test components without going to the
storage for instance) and in general modernize the code. It would also
make hacking on Cassandra easier because people could pick different
pieces without pulling the whole thing.

It would definitely break backwards compatibility with current Java code
that directly embeds Cassandra / uses it as a library, but I would keep
the same abstraction so the refactoring would be easy. In any case,
backwards compatibility can be broken by many more changes than just
refactoring, and once this is done it will be easier to deal with
backwards compatibility.

Obviously all ".instance" fields would be gone, and I'd try to fix
potential cyclic class dependencies and generally make sure classes
dependencies form a direct acyclic graph with CassandraDaemon as its
root. The basic idea is to have each 'service' component require all its
service dependencies in their constructor (and keeping them as a final
field), rather than getting them via the global namespace (singleton
instances).

If I had it my way, I'd probably use a dependency injection framework,
namely Dagger which is as far as I knpw the lightest Java DI framework
actively developed (jointly developed by Square and Google's Java team
responsible for Guice & Guava), which has a neat compile-time annotation
processor that detects missing dependencies early on. It works with both
Android and J2SE and is very fast, simple and light (65kB vs 710kB for
Guice).

So, the question is: would you guys accept such a patch? I'd rather not
do the work if it has no chance of being merged upstream :).

Cheers,

-- 
Simon


[1]
http://grokbase.com/t/cassandra/dev/107xr48hek/creating-two-instances-in-code

Reply via email to