Wednesday, July 22, 2015

Three Reasons You May Not Want to Learn Clojure

I've been coding in Clojure for over a year now and not everything is unicorns and rainbows. Whatever language you choose will affect how you think and work and Clojure is no different. Read on to see what some of these effects are and why you might want to reconsider learning Clojure.

1. You will write at least 10X less code than your Java counterparts
Often, the measure of a library or project is its size. Programmers like to compare the size of their projects, just like muscle car people like to compare the size of their engines. Here are some situations where this might happen:
  • Lunch with buddies
  • Job interview
  • Internal performance evaluation
Here's a typical conversation:

You: "Yeah, I just finished delivering the Awesome 2000."
Them: "Oh, yeah? Tell me about it."
You: "Well, it is this software product that simultaneously creates world peace, solves world hunger, and saves the environment. Zero carbon footprint, too."
Them: "Cool, how many lines of code was that?"
You: "Oh, like 2 million."
Them: "Wow, awesome."

You will now get a high five, a job offer, or a big raise depending on who you are talking with. However, if you stated that the number of lines of code in your product was 200 then the response might be more along the lines of "Oh, a toy program written in a toy language." For some reason, probably because it is easy, many people like to equate lines of code with programming ability rather than some other metric like, oh, I don't know, the actual features of the programs you've developed. Clojure, sadly, excels at implementing features but is very poor at being verbose about it.

If you want to demonstrate your ability to code by writing lots of it, Clojure is a terrible, horrible, no-good language. I can't think of another language that is worse in this respect. You will never be able to brag again, in an circumstance, about how big your code base is compared to someone else's.

2. You won't be marketable for certain jobs
True Story: Once upon a time I was at a job interview and the interview panel asked me to go up to the board and code up a Fibonacci sequence generator. I asked what language they wanted it in and they said they didn't care, but they were a C++ shop. Since they didn't care, I wrote a very short tail-recursive Scala version which I am sure they found incomprehensible. I used to program in C++ and at one time I think I was quite good at it. However, I am just not that interested in C++ any more. It was a great job interview because I didn't get the job. I am sure that the story would have ended the same had I done the exercise in Clojure, except for the parenthesis would have been in the right place.

If you want to be a professional Clojure programmer, there will be a smaller number of job openings for someone of your skills and interests than for the standard Java or C# developer. If you are interested in being part of a clone army doing widely-available boring work, Clojure is not for you.

3. You will get things done faster
Clojure makes you productive, really productive. So, if you can get a product to market 3-10 times faster than you once could, what does your employer do with all that extra time you just bought them? Fire you and pocket the savings, that's what! Just kidding. Mostly.

While it is true that a company might take advantage of their newfound savings in cost and time by eliminating the software team that just bought them the savings, the more likely scenario is that 1) they will reapply you to something else; or 2) if they are trimming fat, you aren't part of it. Often you will become the new go-to person for getting things done because you've demonstrated an ability to get things done. This does lead to problem 3a: You have too much work to do because you are a productivity magnet.

While you can't predict what your employer will do in a given situation, one constant you can be sure of in the current software job market is that you must be agile. If you demonstrate value you can be sure that will have the opportunity to continue to demonstrate value. If, on the other hand, you resist change you will eventually be phased out by your own employer or by another company that displaces yours entirely.

Yes, Clojure is an enabling and empowering language, but this is not without its down sides. I didn't even get into some of the other issues, like not having the opportunity to rewrite your Java code in JavaScript because Clojure compiles both ways. If these are the kinds of problems you like to deal with, you just might want to give Clojure a try.

Shameless Plug
Like this blog? Please share, subscribe, or follow it (just enter your email at the top right).

Tuesday, July 14, 2015

Quil, Clojure, and WORA

Since my last post, I've been playing with the excellent Quil library, a "Clojure/ClojureScript library for creating interactive drawings and animations." Prior to this, I was writing demonstrations using the following scheme:
  1. Develop all logic using cljc files (cljx before Clojure 1.7). In general, application logic is pretty platform-independent and can be wholly or nearly-wholly written in whatever language you are working in (Clojure in our case). Any slight variances (e.g. having to create a java.util.Date or a JavaScript Date) can easily be handled by Clojure's new Reader Conditionals.
  2. Decide on a UI technology (likely Java Swing with Java2D or HTML Canvas depending on what type of demo I wanted) and implement a front end using that particular choice.
  3. Optionally implement the "other" solution from #2 so that I now have a Java and JavaScript solution.
This strategy works pretty well, but I still have duplication of effort when it comes to the user experience. The awesome thing about Quil is that it allows you to launch your UI as either a Clojure or ClojureScript application targeting the JVM or JavaScript-enabled browser, respectively. Now, I can pretty much write everything as cljc files with a few reader conditionals and easily produce targets that run on the JVM or in a browser.

To get my feet wet with Quil, I re-implemented the renderer for my Lunar Lander project in Quil. I was so happy with the results that I removed the Canvas/ClojureScript renderer completely and now just use a single renderer for both the JVM and JS versions of the project.

By the time I was done with my new rendering code and refactoring of everything else, all of the cljs files were gone. I now have a single clj file that is nothing more than a (:gen-class) macro and a main function calling the application entry point in the cljc code. Everything else is written as cljc files. Only a small number of reader conditionals were used to make any Clojure or ClojureScript specific changes as required. Rather than go over every example of how I used reader conditionals, take a look at this file that demonstrates how to create a single Quil "Sketch" that works with both host platforms. Aside from the above linked file, the only other conditionals required were a couple java.util.Date vs. JavaScript Date conditionals used in the simulation namespace. The vast majority of the code was identical for all hosts.

I've been developing code for the JVM for over 10 years and have always liked the "Write once, run anywhere" (WORA) aspect of JVM languages, and have found that WORA works for the most part. However, you can't always rely on your host machine having a modern JVM, especially in the era of mobile devices. The browser is really the most ubiquitous host platform, and the ability to write a single application that can be compiled to run as a JVM app or a JavaScript app with very little effort is a huge advantage for Clojure and Clojurists.

The complete application described in this blog can be found here. Note that you will need to build and install my numerics project as well. Once numerics is installed, cd over to lander and type lein run for the Clojure version of the game. You can play the web version right here (Note that you will need a keyboard or some way to emulate the 'f' key and left and right arrow keys.).