Skip to content

Commit

Permalink
rationale in README
Browse files Browse the repository at this point in the history
  • Loading branch information
wagjo committed Mar 6, 2011
1 parent b91fc98 commit 2063292
Showing 1 changed file with 71 additions and 0 deletions.
71 changes: 71 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,77 @@ Purpose of this library is to provide intiutive access to commonly used
Neo4j operations. It uses official Neo4j Java bindings. It does not
use Blueprints interface.

## Rationale

I've decided to create my own Neo4j wrapper, because I was not happy
with the current state (01/2011) of existing ones. While I initially
forked from
[hgavin/clojure-neo4j](http://github.com/hgavin/clojure-neo4j), I
quickly realized that drastic changes will be needed. This chapter
summarizes my motivation behind changes and decisions I made.

I believe that wrappers are a sub-optimal solution. See some recent
Clojure talks on protocols where they compare wrappers, monkey
patching and protocols. Main problem with wrappers is that they are no
longer original types so you will not be able to use existing
functions which accept original type. That is why borneo works mainly
with Neo4j classes (Node, Relationship), and does not automatically
convert nodes to property maps.

It is tedious to provide a connection for every operation on
database. That is why I chose to have a dedicated Var for storing
current connection. That of course brings several problems to the
scene. Sometimes you want to have a connection which is shared between
threads and sometimes you want to have parallel connections to
multiple databases. (Embedded Neo4j does not allow for parallel
connections to single database). Both cases are supported in
borneo. You can use with-db! for a connection accessible from every
thread, and by using with-local-db!, you can have a tread local
connection. One drawback is that you cannot have both at one moment,
so be careful.

Because I like simple things (see Halloways talk on simplicity), I
tried to provide functions that do simple things, simple. That is why
properties handling function are divided into two separate ones, one for
reading and one for mutating. I also provide some "compound"
functions, like props, create-child! or delete-node!, but they are
here only for convenience and their simple counterparts are also
provided.

While mentioned in previous section, I'd like to stress that I
consider separation of mutable and immutable world very important in
Clojure. That is why all mutable functions in borneo are clearly
separated from their read-only parts and cannot be used in
transactions.

I have added support for custom Returnable and Stop evaluators through
protocols. I think it will allow for greater flexibility (see last
example at the bottom of this page).

Another thing I wanted very much in a Neo4j wrapper was to use
keywords instead of custom static types/enums, to feel more like you
are in Clojure and not in Java... It turned out to be fairly easy to
implement.

All mutable operations are automatically wrapped in transactions (read
only operations don't need transactions in recent Neo4j). By the way
Neo4j handles transactions, it should be pretty cheap to have nested
transactions so you can use with-tx to group mutable operations into
one big transactions if you need it. Needs some field testing to prove
this design decision though.

If you get properties for a node with props function, you fetch all
properties at once. This may be very resource intensive, when you have
large binary data stored in nodes properties. One big wish I had is to
have some king of lazy PersistentMap, where value would be fetched on
demand. I've thougt of using delay/lazy-seq on values to achieve that,
but user would have to manually deref the value, which is not very
intuitive and does not look good. I didn't have time to implement such
lazy map by myself yet. This data structure could also allow for even
less intrusive interface so you could work with data stored in Neo4j
more like working with traditional Clojure map, without serious
performance impact. Who knows. More hammock time needed.

## Usage

Add the following dependency to your project.clj file:
Expand Down

0 comments on commit 2063292

Please sign in to comment.