Friday, February 11, 2011

When you feel frustrated, you are doing it the wrong way.

At the moment I'm working on a project where clojure and java have to tightly inter-operate. I write very functional oriented Java code and integrate it with clojure; clojure code calls low level java code, but as the whole thing is essentially built over a Java framework, clojure code has to be called from Java as well.

Consequently, I have been essentially using clojure as a DSL to generate Java code. I find very hard this kind of setup, as I really have to keep an eye on both sides of Java integration and the whole thing is constrained in a very javish structure (and in fact it is far more similar to the way I would have coded in Java than to the way I would have coded in Lisp). Now, this wouldn't be an issue if it weren't that more than once I considered writing the whole thing in Java.

The essential question is: if I have to write more code to inter-operate with Java than the code I would have written using directly clojure, is it worth it? I'm talking about getting attributes from the .state hash-map.

In fact, I feel like (:some-value @(.state this)) is a big step backwards with respect to just having a someValue field. The point is that writing Java classes in Java is more comfortable than writing them in clojure. Which makes sense. The point is that, in order to leverage the clojure advantages, I have to build my abstractions over the Java framework. In fact, this also makes sense. I understood looking at my clojure code, which was too javish. Well, it was even more javish than the Java code I tend to write.

In fact this is one of the worst pieces of code I ever wrote.



Well, as a partial justification, I have to say that I translated that crap directly from Java. That is Java in clojure. It is essentially imperative code (and that is acceptable, as after all we want to mutate state), but it totally lacks abstraction. In Java that method takes an Object[] (and really, it can't be implemented otherwise).

Changing the number or the order of the parameters I get completely breaks everything and needs a complete rewrite of the method. That is not open for extension at all. And it lacks abstraction.

I decided to change approach: after all what I want is a hash map. I just need to write a function taking the parameters array, the (ordered) keys and a dictionary providing default values. I also found out that sometimes I want to specify all the defaults (and in this case the keys are just redundant, as I can take them from the map, as long as it is an array-map).

This way, things are much easier. In fact the code is far from perfect: there is some redundancy (keys must be specified in two places). Part of the reason is that some objects may have keys which not only are both optional and do not have a default value (and consequently are just not to be in the dictionary).

This is essentially due to some bad design in other parts of the project and is going to be eliminated in time. Right now, the code is (some key names changed as well):



Essentially, as long as I manage to write lisp in clojure the frustration is minimal.

, ,

No comments: