Hi, I‘m Martin. You should follow me: @martinklepsch

August 2015 Parameterizing ClojureScript Builds

Just like with most server side software we often want to make minor changes to the behaviour of the code depending on the environment it’s run in. This post highlights language and compiler features of ClojureScript making parameterized builds easy peasy.

On servers environment variables are a go-to solution to set things like a database URI. In ClojureScript we don’t have access to those. You can work around that with macros and emit code based on environment variables but this requires additional code and separate tools.

With ClojureScript 1.7.48 a new macro goog-define has been added which allows build customization at compile time using plain compiler options. Let’s walk through an example:

(ns your.app)
(goog-define api-uri "http://your.api.com")

goog-define emits code that looks something like this:

/** @define {string} */
goog.define("your.app.api_uri","http://your.api.com");

The goog.define function from Closure’s standard library plus the JSDoc @define annotation tell the Closure compiler that your.app.api_uri is a constant that can be overridden at compile time. To do so you just need to pass the appropriate :closure-defines compiler option:

:closure-defines {'your.app/api-uri "http://your-dev.api.com"}

Under the hood

When compiling with :advanced optimizations the Closure compiler will automatically replace all occurrences of your defined constants with their respective values. If this leads to unreachable branches in your code they will be removed as dead code by the Closure compiler. Very handy to elide things like logging!

Without any optimizations (:none) goog.define makes sure the right value is used. There are two global variables it takes into account for that: CLOSURE_UNCOMPILED_DEFINES and CLOSURE_DEFINES. When you override the default value using :closure-defines the ClojureScript compiler prepends CLOSURE_UNCOMPILED_DEFINES with your overridden define to your build causing goog.define to use the value in there instead of the default value you defined in your source files.

For details see the source of goog.define.


July 2015 ClojureBridge Berlin

About two weeks ago something awesome happened: the very first ClojureBridge workshop in Berlin. After months of planning things finally got real.

ClojureBridge Berlin in it's entirety.

ClojureBridge aims to increase diversity within the Clojure community by offering free, beginner-friendly Clojure programming workshops for women.

Many of you probably got the “news”: there’s a lack of diversity in programming communities. Many communities acknowledge this and have created initiatives to fix it. The Ruby community has RailsBridge (and more) and other communties equally do their part in improving our industries diversity situation. Inspired by RailsBridge the Clojure community established ClojureBridge and has organized more than 20 workshops worldwide since.

Why Diversity?

There are endless amounts of research why diversity is desirable but one of the reasons that seems most intuitive to me is that software is, after all, for humans. If we want to make great software for everyone then it can only be made by all of us and not by one priviliged monoculture.

ClojureBridge Berlin

ClojureBridge workshops consist of one evening installing required software (Friday) and a full day of actually learning things (Saturday). Besides some problems with our pizza delivery both days went really well. We had great vegan and vegetarian lunch on Saturday, fun ClojureBridge cupcakes and after the coffee machine broke on Friday people brought lots of coffee making equipment to the event on Saturday. You could say we had a little third wave coffee workshop as well.

We got some sweet cupcakes!

On Saturday we initially had 2-3 coaches that “didn’t have a job” and we were afraid they might feel superflous but the need for some additional help quickly arised when some learners got ahead of the rest of their group. In the end we were very happy that we had the flexibility of not having assigned all coaches to groups. (We still had teaching assistants.)

Results

At the end of the event we had a fantastic demo time. A great amount of learners showed their Quil creations, from an Santa Claus to stroboscopic rainbow animations. It was great to see how in the beginning everyone was shy to show their work but as more people did others felt encouraged to do the same.

Takeaways

This was the first time we organized such workshop in Berlin. We were lucky to be a big team of organizers (six people) which allowed us to distribute the work.

The feedback we got during and after the workshop has been very positive. About a third of the attendees have registered interest in joining project groups to keep learning. Obviously the more the better but even ten people is a nice outcome overall.

Thanks

I’d like to take the opportunity to thank all of our coaches: Nils, Sean, Paulus, Jan, Johannes, Ben, Franziska, Luca, Txus, Kofi, Torsten, Tibor, Thomas, Stephan, Oskar, Kai & Matt thank you so much for being part of this. None of it would have happened without you!

Also I’d like to thank my fellow organizers for pushing through the finish line together and for just being an overall awesome bunch. Thanks Bettina, Malwine, Arne, Jelle & Nicola.

Last but not least I’d like to thank the companies that enabled ClojureBridge Berlin: Wunderlist, SoundCloud, GitHub, InnoQ, TicketSolve, Babbel & DaWanda. A special thank you in this regard to Andrei, who has done an exceptional job at hosting the event at Wunderlist!

ClojureBridge Berlin T-Shirts

If you’d like to be informed about upcoming workshops, follow @ClojureBerlin on Twitter. If you don’t have Twitter you can also send me an email and I’ll make sure you’ll be notified :-)


June 2015 Managing Local and Project-wide Development Parameters in Leiningen

Little tip. Long headline.

In any project there are often settings that are specific to the context the project is run in (think of an environment parameter) and then there are parameters that are specifc to the developer/workstation they’re run on. This is a guide to separate these two things nicely in Leiningen-based Clojure projects.

So you have a project setup that uses environ to determine the context the project is run in (development vs. production).

; in project.clj:
(defproject your-app "0.1.0-SNAPSHOT"
  ; ...
  :profiles {:dev {:env {:environment "development"}}})

Now you also want to use environment variables (or anything else thats supported by environ) to store AWS credentials to access Amazon S3. You don’t want to commit these credentials into version control, therefore you can’t add them to project.clj. The way to go is to create a file profiles.clj in your project to store workstation specific information. Naively this could look something like this

{:dev {:env {:aws-access-key "abc"
             :aws-secret-key "xyz"
             :s3-bucket "mybucket"}}}

If you run your project with this profiles.clj you will be able to access your AWS credentials. You might also notice that (environ/env :environment) is nil. That wasn’t intended.

The problem here is that Leiningen will override keys in profiles defined in project.clj if the same profile has also been defined in profiles.clj. To recursively merge Leiningen profiles combine them like so:

; in project.clj:
(defproject your-app "0.1.0-SNAPSHOT"
  ; ...
  :profiles {:dev [:project/dev :local/dev]
             :project/dev {:env {:environment "development"}}})

; in profiles.clj
{:local/dev {:env {:secret-key "xyz"}}}

Now both, :envrionment and :secret-key should be defined when you retrieve them using environ.

This is largely inspired by James Reeves’ duct Leiningen template.


April 2015 Formal Methods at Amazon

I saw this paper being mentioned again and again in my Twitter feed. Basically not even knowing what “formal methods” really means I was intrigued by the claim that it’s easy to read. And it has been.

The paper describes how Amazon used a specification language to describe designs of complex concurrent fault tolerant systems finding bugs and verifying changes in the process.

The specification language (TLA+) is not focus of the paper, rather the authors concentrate on describing benefits, problems and the path of adopting formal specification of system designs in an engineering organization.

TLA+, stands for Temporal Logic of Actions and “is especially well suited for writing high-level specifications of concurrent and distributed systems.”

Reading how they use it at Amazon I’m under the impression that it works very similar to generative testing dumping a ton of basically random (according to some rules) data into a system and checking if the desired properties are maintained. Often the term “model checker” is used.

Download the original paper or a copy of it with some passages highlighted that I found particulary interesting.


February 2015 (lisp keymap)

A while back I wanted to setup hotkeys for the various apps I use. Mostly because I was annoyed by the cognitive effort you need to make to figure out how often you need to press Alt + Tab exactly to get to the app you want.

It seemed like a good idea to use Capslock as a modifier key. This way I could be sure I wouldn’t override any other keybindings. Figuring out how to do this I stumpled upon an excellent post by Steve Losh “A Modern Space Cadet”. It’s described in detail how to set Capslock to Hyper - a fifth modifier key. I then created bindings like Hyper + S which will focus Safari etc. Exactly what I was looking for.

Then I found something in his post I wasn’t looking for: instructions to map my shift keys to parentheses. It sounded crazy at first but doing mostly LISP-y stuff these days I tried it anyways.

Now I wouldn’t want to live without it anymore. It’s just so much easier than Shift + {9,0}. Also the Shift keys still work as they do usually when pressed in combination with other keys.

A few days ago I was typing some stuff at a collegues computer and it immediately felt cumbersome when having to type a parenthesis.


« 1 2 3 4 5 6 7 8 »