So I was all high on simplicity yesterday and of course Frank had to ask me the question that made me crach land again: “So, what do you mean by ‘simple’?” I almost didn’t hear this mornings talk from Brian Goetz about lambdas in Java, since me head was crunching that question. What is “simple”, what does it all mean?
It struck me that I need to be able to measure complexity to answer that question. I need some way of comparing to things and say, that one is more complex than the other. Looking at code, at a system, at a framework, we have en intuitive understanding of simple. But it is not only intuitive, it is subjective. If something is easy to do or easy to understand. Does that make i simple?
I’ve been doing karate for years and it is pretty easy for me to round house kick someone and kill them 3 times before they hit the ground. Does that make it easy to do, thus simple? Not really. Karate is hard and complex, I just practiced a lot. So easy to do, does not make simple.
What about easy to understand? I understood most of Brian Goetz talk about lambas in Java without a big effort. Of course I had to think really hard about some af the stuff, but in overall, it was pretty straight forward. But I’ve been programming for 25 years now in anything from assembler to prolog, and I’ve been a full time clojure programmer for almost 2 years now. I should know about lambdas and low level stuff by now. That gives me an edge. It is only easy because of all the other stuff I know about the subject.
That still leaves the question unanswered. Should complexity then be messaured by LOC? That’s at least a objective messaurement and maybe better. If I can express the same algorithm in half the lines of code, it is simpler right?
Here’s the Adler checksum algorithm in C:
const int MOD_ADLER = 65521;
uint32_t adler32(unsigned char *data, int32_t len)
uint32_t a = 1, b = 0;
for (index = 0; index < len; ++index)
a = (a + data[index]) % MOD_ADLER;
b = (b + a) % MOD_ADLER;
return (b << 16) | a;
12 lines of code
and here it is in clojure:
(def base 65521)
(defn cumulate [[a b] x]
(let [a-prim (rem (+ a (bit-and x 255)) base)]
[a-prim (+ b a-prim)]))
(derive clojure.lang.LazySeq ::collection)
(defmulti checksum class)
(defmethod checksum String [data]
(checksum (lazy-seq (.getBytes data))))
(defmethod checksum ::collection [data]
(let [[a b] (reduce cumulate [1 0] data)]
(bit-or (bit-shift-left b 16) a)))
11 lines of code
The latter should the be less complex, right?
I’ll leave this one open and hope for a discussion in the comments.