
Clojurize the Data, Not the Database - mcav
http://anvil.io/2010/10/25/clojurize-the-data-not-the-database.html?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+anvilio+%28anvil.io%29&utm_content=Google+Reader
======
jwr
I disagree with the author. I've yet to see an abstraction layer that doesn't
end up as the lowest common denominator of all databases supported or becomes
a leaky abstraction.

Databases are different — accept it. I use PostgreSQL and Redis — there is
really little they have in common and I use them for completely different
purposes. I can't see how you could stuff all that into a single abstraction.
I mean, in my Clojure code I use SQL transactions in one part of the program
and Redis' optimistic locking (WATCH/MULTI/EXEC) in the other. They are
_different_ and they are supposed to be different.

I also believe that the whole story about how difficult it is to "switch
databases" is a red herring. If your code isn't a pile of spaghetti, then your
database access functions are grouped together, not spread all over the place.
This usually means that instead of abstracting the database with a generic
database API, you abstract the database with _your_ API, which only performs
the operations you need.

If you do that, then a) switching databases isn't that difficult, b) your
"database DSL" becomes _your_ DSL, not somebody else's.

As a practical example, my code has a namespace called "distributed" which
abstracts distributed synchronization using Redis. I can call
(distributed/register-server), or (distributed/dequeue-job). The functions are
very short, and really consist of redis-clojure calls with minimal database
logic. Now _that_ is a DSL I like.

------
lsb
If only there were a _mapping_ to make a _relation_ in my data store out of an
_object_ in my language.

ActiveRecord seems like a local maximum, and I'd be very curious to see what
comes up in the next decade.

~~~
arohner
I've written an ORM for clojure (unreleased). It's 1k LoC, which is _huge_ in
clojure.

Let me tell you, I'm sick of writing ORMs, I'm sick of using buggy,
abstraction-leaking ORMs. I'm sick of the need for ORMs. Relational DBs should
provide ORM as a native, first-class abstraction. The fact that every
programming language has ORMs, and that people are starting to adopt Mongo
over say, postgres purely because it doesn't need ORM and has a nicer query
interface is telling.

Relational DBs need to get with the times.

------
peregrine
This is a brillant idea and I'm interested that it hasn't been implemented for
other languages yet...

EDIT: It seems like a simple idea, but I'm wondering if the execution has
failed or if it was adoption or if this is truly an original idea.

~~~
philbo
I don't think the idea is original (still a great idea, though).

ODBC, for one, would seem to have had the same aims:

[https://secure.wikimedia.org/wikipedia/en/wiki/Open_Database...](https://secure.wikimedia.org/wikipedia/en/wiki/Open_Database_Connectivity)

~~~
bhickey
It's a bit old, but the Database Template Library is worth checking out. The
DTL presents ODBC records as STL objects, enabling the use of all sorts of
yummy STL algorithms!

------
mark_l_watson
For right now, I find Ruby's datamapper to be state of the art for providing a
uniform interface to many back end data stores. Definitely take a very good
look at datamapper to collect ideas for a Clojure library.

------
wccrawford
Different databases/formats/etc have different strengths. While it's nice to
say your program to store to any kind of datastore, it's much more practical
to have it optimized for the kind that's best for it.

~~~
alrex021
> While it's nice to say your program to store to any kind of datastore, it's
> much more practical to have it optimized for the kind that's best for it.

I think this is very arguable. For the cases where you want to do some query
optimization, thats what the Clojurize protocol's prompt function is intended
for.

    
    
      (prompt
        [adapter expression]
        "Execute a native database expression")

~~~
weavejester
But a more specific library would be better able to cope with the unique
features of a particular database. Why send commands via 'prompt' when a more
specialised library will have functions to do that job?

I think there's definitely a place for libraries that add things like
validation to models. But the more functionality you include, the more
specific your library needs to be.

~~~
alrex021
Correct me if I'm wrong here but isn't that the purpose of the adapter
implementations to also hold the different dialect and/or datastore specific
optimizations?

[edit] OT to this thread: didn't clojure-dbm have some similar ideas to
Clojurize? I remember forking it from your github repository early last year
some time and doing some cool stuff with it.

~~~
weavejester
All of the implementations you mention sacrifice specific functionality in
order to support a general interface. For instance, clojure-dbm was an
interface to key/value stores, so it supported a small subset of common
functionality: fetch, put and delete. It didn't support functions that are
specific to a certain type of database, such as setnx in Redis.

