Hacker News new | past | comments | ask | show | jobs | submit login

> .. However, we had a strong aversion to using Java itself ..

Honestly, why? Seems odd given Java's great track record for exactly this problem and huge library and developer share. The code itself is forced to be static and explicit which makes for easy onboarding for new developers.

It's a bit strange to just dismiss Java in the context of the rest of the article. You're kind of staking your company on decisions like these, and making them because of some unquantifiable 'strong aversion' seems like a poor choice.

That said, Clojure or other lisp base definitely seems like the correct choice for a query language / dsl. That's the shining point of lisps after all.




I think the popularity of yesql (https://github.com/krisajenkins/yesql) calls your last point into question. Indeed in my experience, using korma (the most popular clojure SQL-DSL) provided no additional benefit, just additional documentation to read.

I've gone through the FP language snob mill over the last few years, and have to agree -- I don't love it, it doesn't make me feel all chipstered out, but Java is actually a pretty decent language for getting stuff done.


I built a system on top of yesql* and eventually threw most of it away because it was a lot more trouble than composing queries with honeysql. I prefer honeysql to yesql for the same reason I prefer hiccup to enlive. It's just easier to compose things with native data structures using the full clojure language.

* I even maintain a fork of yesql powering several of my production apps to use that has features that were never merged (such as making it possible to insert maps as jsonb into postgresql by deferring to the underlying jdbc libraries for serialization).


I'll have to give honeysql another look. Superficially it looked like Korma, which turned me off for the exact reason mentioned in yesql's "rationale" section, so I didn't investigate honeysql any further.


You can use it like korma if you want (it has a higher level dsl (but with functions that all return a map)) ala:

    (require '[honeysql.helpers :as sql])
    
    (def query-map (-> (sql/select :*)
                       (sql/from :foo)
                       (sql/where [:= :bar "baz"])
                       (sql/limit 5)))
This works because each of these functions has two arities, the lower one returning a map, and the higher one assoc'ing or merging (there are merge-* functions for building purposes) something into its first argument (which is presumed to be a map).

    (= (sql/from :foo) {:from '(foo)})
This means that if you just need a SQL AST, you have this handy map thing that honeysql can turn into platform-specific sql. But if you just need something quick and dirty, you can use something that looks very similar to korma. There is no ORM functionality, but with a query building toolkit, I haven't really needed it. Since honeysql's helpers are built as functions, I haven't even really needed to dive into the lower map representation much, although it was handy the one time I was translating a higher level query language into sql.


personally, i find java pretty painful to use; it's definitely capable of doing whatever job you have in mind, but when i use it i have the constant feeling i'm using a suboptimal tool. and then it leads to reams of boilerplate all of which has to be maintained, so it's not just a development-time cost; there's the depressing feeling of having to deal with it every time you want to read the code. clojure would be worth it just for the joy of using a tool that fits well into your hand.


It's kind of like building a model with clay or with sticks. The clay model is going to look nicer with rounded curves and no wasted points. The stick model will have bits sticking out.

However when you get 30 people working together to make a big model, the clay model is going to start looking very strange indeed. Different people will have different finger pressure and shape the clay differently. Some people will make more right angled parts with the clay which will clash with the parts of the clay that are carefully smoothed out. Someone might spend a week fixing a perfect parabola for a curve at the top of the model just for someone else to bend it off to the side with an ugly twist to fit with the other side of the model.

30 people on the stick model? Not really a problem. All the sticks look the same. Anybody who needs to attach one side of the stick model to something else just needs to grab a stick and tie it on. You won't see a perfect stick parabola, but then you also won't be stuck with a strangely twisted piece of clay.

You can always create a style guide for using the clay - always keep between a 30 and 60 degree angle on joins. Apply one finger of pressure when doing joins. And so on. Sometimes this works with very diligent reviews that keep everything in place, but as soon as a crisis comes up or the model needs to pivot urgently? Everyone rushes to touch up the model in the quickest way possible and your model starts to get a bit thinner on one side than the other, etc.

So there's nothing wrong with choosing a great clay model that fits well into your hand and you can shape effortlessly - but you need to remember that sometimes the 'painfulness' of using a model made out of sticks can be a big blessing when you're trying to massage a bit of clay that someone else pressed a bit too firmly on.

EDIT:

Also, when you've been making and using models for awhile, the stick models get an added benefit: you can browse through the stick models really fast based on only their outline and be able to understand very quickly how they work. Pretty clear why: the rigid sticks form a very distinct outline (think interfaces and forced directory structure in Java). Being a stick model expert therefore has very good job mobility and high demand.

Each clay model is generally more unique and requires some study to understand even if it does look nicer.


I will try to continue your clay/sticks parable, but in my limited clojure experience, you seldom create a clay model, it resembles more a creation of a custom clay brick-set.

Most of the time, all of the team is either building bricks or using those bricks.

The biggest plus of using clay instead of sticks is that when you find yourself in a corner, it is easy to invent a new brick shape that fits.

The drawback is, that without the style-guide, you can easily end up with brick-shape per developer. But I see a difference between "Hey, why did you invent a new brick type again?" and "Apply one finger of pressure when doing joins."

When crisis comes and model needs to pivot urgently, there are two possibilities. Either you just need to rearrange your bricks. Or you realize there is something fundamentally wrong with your bricks, and then you create a new brick-type and carefully replace old bricks with new bricks.

Ok, programming parables are weird. I might write a more concrete example, if I have time.


Nice extension! Feels right too, clojure does feel a lot like passing around similar clay bricks. When all the bricks line up, it's kind of like Lego?

The analogy also opens up another difference. In clojure, you often end up passing around a lot of maps with string keys. What are those keys exactly? You have to crack open the clay brick to take a look at how it works. With the stick model, you can often see how the sticks work if the bundle of sticks has been color coded nicely - eg, well constructed generics. Luckily cracking open a Clojure brick is as simple as ctrl-clicking, so it's not nearly as bad as it sounds!

Programming parables are definitely weird though - programming does not have true analogies with the real world. It's more of a superset of the real world and the use of programming languages is more akin to defining physical laws than building bridges with clay or sticks. I don't think we as humans have really come to understand exactly what we are unlocking with the development of programming and how vast it really is.


My experience is Java costs me around 10x the number of lines of code (and I mean code, not imports) to get the same things done. The brief syntax and higher-order programming eliminate so much from my screen that, in hindsight, served as little more than visual framing for sparse bits of code.


If there's no single language lock-in, then using polyglot approach, you can get best of both worlds: write DSL parts in Clojure and other parts in Java. We did this recently in one of our porjects (Clojure piece was responsible for interacting with ElasticSearch).




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: