Friday, January 21, 2011

Real Life Clojure?

This morning I had my first "real world" clojure script working. I have to say, that I'm doing this in the worse possible scenario.
  • I'm working with Java libraries under heavy development
  • My own project is partly in clojure and partly in Java: specifically I both call Java from Clojure and Clojure from Java
  • The framework I'm working with (which is the one under heavy development) heavily relies on dynamic loading and such
  • I never grokked Java build/deploy models; that is to say, I was doing what I strongly advise people against: I don't know the build tools I'm using.
Right now, I did not fully automatize the build system. That is to say, I don't have a nice "build" button on the IDE which does everything for me. Following Uncle Bob's advice I have a compile.clj like:

(set! *compile-path* "../out/production/ModuleName")
(compile 'it.unipr.aotlab.netsym.actors.NodeActivator)


This heavily depends on where IntelliJ puts the compiled files. However, this way, using the right preamble in the clojure programs, everything works:

(ns it.unipr.aotlab.netsym.actors.NodeActivator
  (:gen-class
   :extends it.unipr.aotlab.hds.application.process.AbstractActor
   :state state
   :init init)
  (:import [it.unipr.aotlab.hds.application.process AbstractActor]
           [it.unipr.aotlab.hds.model.application Message]
           [it.unipr.aotlab.netsym.messages Tick]))

I rather hate:
  1. such verbose boilerplate code (apparently LaClojure does not "auto import" stuff)
  2. Explicit compilation stages (that is to say, I found barely acceptable pure-java "run" button which compiled and then executed the module, having to compile clojure, than compile and run Java is heavily sub-optimal)
I'm afraid I can't do a thing with 1. However, I expect I should improve things for 2. For example, I'm exploring the possibility of using Leinigen (tutorial here). Not sure it is the right tool though... I have not a clear idea on how much Java and how much clojure it will be. The basic library is very well crafted with a strong functional lispish bias in it and I like it.
The other road I could take is using ant... I started writing the ant scripts, but that is rather embarassing. However I'm kind of figuring it out how things work (wondering how is verbose XML... I believe that XML designers would definitely not pass the turing test). Uff... the "build using ant" feature of IntelliJ is not where I'm expecting it, though.

I have made some updates here.



2 comments:

skuro said...

You're the very first other Italian Clojurian I get to know, that's definitely a pleasure for me :-)

About this blog entry topic, let me share with you my (limited) experience.

I was part of a team making a brand new web application based on Liferay Portal on the frontend and Clojure components on the backend. We initially had:

- Maven handling Liferay customizations build

- Leiningen creating JARs filled with AOT compiled clojure code

We *engineered upfront* the interface between Java and Clojure, and implemented the clj protocols to expose as Java interfaces. This guaranteed a baseline for the integration to be clearly defined.

As leiningen and maven meet together at dependency management, it was fairly easy to let each side see updates on the other. This approach proved to be bad when the project grew in complexity, as we had to keep both project.clj's and pom.xml's in sync, which was both a suboptimal approach and an error prone procedure.

We eventually mavenized all our clojure modules (Java/maven skills were the most available cross-team skills) and now everything is a module under a master pom.xml. Using Maven build ordering and dependencies between submodules new code is always immediately visible where apt.

Does this help a bit?

Keep on with Clojure, I hope to read more from you and other Italians about this awesome language!

Unknown said...

> You're the very first other Italian Clojurian I get to know, that's
> definitely a pleasure for me :-)

It's a pleasure for me too. However, there are a few Italians I know
which use or plan to use Clojure. One of the blogs in my blogroll
is written by such a person.

I also heard a lot of clojure among participants of Python.it mailing
list. We are rather open to new languages (where new does not
necessarily refer to language age, e.g., there were liaisons between
Python programmers and Haskell programmers some years ago. I also
remember something like an Europython almost co-located with an Haskell
conf.

I'm basically outside the Java community, though. It may be that clojure
did not have lot of resonance there. I'm one of the guys following
more the functional heritage of clojure than the Java heritage.

> About this blog entry topic, let me share with you my (limited)
> experience.

Thank you very much, then.

> - Maven handling Liferay customizations build
> - Leiningen creating JARs filled with AOT compiled clojure code

This looks like a good solution, indeed.

> We *engineered upfront* the interface between Java and Clojure, and
> implemented the clj protocols to expose as Java interfaces. This
> guaranteed a baseline for the integration to be clearly defined.

Your engineers must have been remarkably good. It is rather hard to
do this kind of things upfront.

> As leiningen and maven meet together at dependency management, it was
> fairly easy to let each side see updates on the other. This approach
> proved to be bad when the project grew in complexity, as we had to keep
> both project.clj's and pom.xml's in sync, which was both a suboptimal
> approach and an error prone procedure.

I understand. I suppose that leiningen was not able to simply substitute
maven. Just to know... have you tried to generate both maven and
leiningen files from the very same "proprietary" conf file?

I understand this looks like lot of work, and I'm not very familiar with
maven. But afterall it's just XML, which should not be too hard to generate
with clojure, afterall. Perhaps I'm underestimating something, though.

> We eventually mavenized all our clojure modules (Java/maven skills were
> the most available cross-team skills) and now everything is a module
> under a master pom.xml. Using Maven build ordering and dependencies
> between submodules new code is always immediately visible where apt.

This is the other natural route. I suppose that this was easier.
Team skill are an important criterion and Maven is far more mature and
tested than leiningen.


> Does this help a bit?

Yes, indeed. I understand that the problem is real. I could not support
such a solution. Clojure in my projects is meant to ease development.
This makes me wonder if in the context of having the two languages
essentially live together is worth it.

I can see that having a pure clojure module (both calling and being
callable from Java) is far easier.

> Keep on with Clojure, I hope to read more from you and other Italians
> about this awesome language!

We are few, but not *so* few. I think that we are just divided.
I plan to hack with clojure more: I don't love it as I do love Lisp, but
I am quite fond of it nonetheless.

Waiting for your Sproutcore + clojure post, by the way. ;)