Wednesday, 20 August 2014

I have released liberator-transit 0.3.0. The main new feature in this
release is the option to set write handlers for Transit. To do so, just add
them to the options using the :handlers key just as if you were calling
transit/writer. For more details, check out the README.

Sunday, 10 August 2014

It didn’t take long. I have released liberator-transit version 0.2.0,
which fixes one bug and adds some configurability. Now, the response will not
have a charset added to the Content-Type header. Furthermore, you can now
disable verbose JSON output, make verbose JSON the default, and change the size
of the initial buffer used in serialising the response. You can read the
details in the README. Most importantly, this work paves the way for
setting write handlers for the Transit output, currently planned for release
0.3.0.

Friday, 08 August 2014

As part of my prepartion for the core.async workshop I’ll be giving at Strange
Loop, I have come across the need for a RESTful API for a web application I am
creating. Naturally, I thought this would be a good chance to try out
Liberator and Transit. I was pleased to see how easy
Liberator is to use. Moreover, it was nearly trivial to add Transit
serialisation support to Liberator. Nonetheless, I thought it would be good to
wrap it all up in a library ready for reuse, which I have unimaginatively
called liberator-transit.

The default Transit/JSON encoding is the non-verbose format. By adding the
“verbose” to the “Accept” header, liberator-transit emits the verbose JSON
encoding.

Since the MessagePack encoding is a binary format, I pipe the output through
xxd. Otherwise, unprintable characters are output.

How it works

Liberator has a built-in mechanism for formatting output of sequences and maps
automatically depending on the headers in the request, as seen above.
Moreover, it’s possible to extend this easily by adding new methods to the
render-map-generic and render-seq-generic multimethods in
liberator.representation. These methods dispatch on the media type that has
been negotiated and take two arguments: the data to render and the context.

Getting the verbose output to work was just a touch trickier. The parameters
to the media type are stripped by Liberator. As a result, it is necessary to
actually examine the request headers that were placed in the Ring map.
Fortunately, this is easy to do as it is a part of the incoming context.

Further work

This library is really quite simple. I spent far more time creating
test.check generators for the various Transit types than I did on the library
itself. It mostly exists to provide an even easier way to add Transit to
Liberator.

Nonetheless, if other people find a need for it, there is possibly room for
improvement, such as:

Is there a better way to handle the request for verbose JSON?

Should the library be configurable? If so, what should be configured and
what is the best way to do it?

Monday, 04 August 2014

Over the past month or so, I have started dabbling a bit with writing code for
the web/front-end. In large part, I have done so in an effort to have a nice
interface for the workshop on core.async that gave at Lambda Jam and will give
again at Strange Loop. I am comfortable enough picking up what I need to know
for the back end, but how can I create a site that doesn’t look like it came
from 1997? I have used Twitter’s Bootstrap before, and it’s not a bad starting
point. However, this time I decided to try using Polymer.

In this entry, I briefly introduce the motivating principle behind Polymer, and
I share some of the lessons I learned in creating Polymer elements with
ClojureScript. Finally, I answer the question: Why use Polymer and not
something like Om/React?

A quick introduction to Polymer

Polymer is a technology developed by Google built atop Web Components, a group
of related standards such as templates, HTML imports, custom elements, and
shadow DOM. Ultimately, the end goal of this combine chunks of styling,
markup, and logic into discrete reusable components. For example, embedding a
Google map into a page is as simple as:

<google-map latitidute="…" longitude="…"></google-map>

It couldn’t get much simpler than that, right? Well, Polymer has a whole
series of UI components designed to help create web applications implementing
Google’s new material design. These looked nice, so I decided to put
them to use.

Using Polymer with ClojureScript

Overall, using Polymer has been a relatively smooth process. For my workshop,
I primarily just used the Polymer element libraries, but I did create a few. I
primarily used JavaScript to implement the logic behind my elements. However,
there is one component where I absolutely needed to use ClojureScript, as it
demonstrates the different types of buffers for core.async channels. Rather
than creating a simulation, I used core.async itself. Learning to use the two
technologies together correctly took a bit of experimentation, but here are a
few tips for you should you decide to go down the same path:

Tip 1: Beware of what you build in your prototype

The typical call to register a Polymer element with a few properties in
ClojureScript will look something like:

However, you may want to create an element with more complex properties such as
JavaScript arrays or objects or even ClojureScript objects such as a core.async
channel for managing callbacks. As such, you may be tempted to do something
like:

However, as the documentation will warn you, this is not the right way
to do it. The object created here is a prototype that will be used in each
instance of your element. As such, any complex types will not get deep copies
and essentially constitute global shared state. Instead, you need to
instantiate these in the created callback, as in:

Tip 2: Pass your element reference around

If you don’t grab onto the this reference inside the scope of your prototype,
it can be very hard to get it later. As such, when calling your own functions from
a callback, be sure to pass the reference in. For example, the previous example could
be rewritten as:

When using ClojureScript’s advanced compilation mode, it will munge the
property names if you use the first method. The result will be a broken
element featuring lots of null or undefined values. Unless you are sure
you will never use the advanced compilation mode, just use the second syntax.

Tip 4: Accept mutability

As a Clojure/ClojureScript programmer, it maybe very tempting to try to store
your application state in an atom and deal with it a nice, sane way—just the
way Om does it. Well, to do so in Polymer while supporting Polymer’s two-way
data binding is just a pain. It can certainly be done, but I am not sure it is
worth the effort. Let’s take a look at a simple example to see what I am talking
about:

On line 3, we set up the mutable cell that will be visible to Polymer.

On line 4, we set up the immutable cell for our Clojure code.

On line 5, we set up a handler so that we can update the Clojure atom when
the property is changed from Polymer. For example, this may occur if the
property was bound to the value of some user input.

On line 8, we create our atom.

On line 9, we set up a watcher on the atom so that if a change comes from
the Clojure side, i.e. from a swap!, the change will be pushed into the
mutable cell that Polymer will see.

Finally, on line 13, we add the atom to the element’s state.

This is a lot of overhead for just one property. You can try to manage this
more easily by just having one atom with all application state in some sort of
map/object. This does mean you have fewer atoms to watch, but otherwise it
doesn’t help too much.

The reasons for this are twofold:

Now your template code has to reference a bunch of nested properties. What
used to be {{property}} now looks like {{state.property}}.

You must now use an observe block to get notifications of
property changes, and you must specify each path through your state map.

This is an awful lot of boilerplate. I suppose it may be possible to automate
much of it using a macro, but the question that remains is what does this
additional complexity buy you? In my opinion, though it may be a bitter pill
to swallow, just accepting and using the mutability of Polymer element seems to
be the most pragmatic route. Doing so allows things like Polymer's two-way data
binding to just work.

Tip 5: Properly include the ClojureScript in development mode

There are three ways to register a Polymer element that has logic:

Inside the element definition in the body of a script tag,

Referencing an external script inside the element definition, and

Loading the external script before the element definition.

With ClojureScript, we can choose from the latter two. Most of the time, the
second form is the most convenient:

However, this only works when one of the ClojueScript optimizations levels is
used, i.e. whitespace, simple, or advanced. If you are in development mode,
you would might be tempted to do something like:

However, if you are importing your element, e.g. <link rel="import"
href="my-element.html">, you will run into problems with the Google Closure
library. It doesn’t like this since it will attempt to inject your script’s
dependencies after the main page has loaded. Instead, while you are in
development mode, place all of your script tags in your main HTML page.

Tip 6: Be wary of processing the component HTML

This isn’t ClojureScript-specific, but I thought I’d include it nonetheless.
During development, I use some Ring middleware that injects script tags into
the served HTML to connect to my browser REPL environment. This generally
works well, but sometimes I saw some really bizarre behaviour. For example a
paper-input component refused to take focus, or a core-submenu component
hid its icon.

It turns out that Polymer uses a conditional attribute syntax:

<span hidden?="{{isHidden}}">You can hide me!</span>

If the expression is false, then the attribute will be omitted from the markup.
Some HTML parsers such as Enlive or htmlmin cannot process that. At least in
the case of htmlmin, it caused a mysterious hang. I received no warning at all
from Enlive.

The bottom line is: don’t try to process a component’s HTML unless you are sure
your processor can handle it.

Why bother with Polymer?

So given the existence of ClojureScript-friendly frameworks like Om/React, why
bother trying to write Polymer elements in ClojureScript? That’s a great
question. Here’s my take on it:

The two are not mutually exclusive. You can easily use both Om/React
components and Polymer elements on a page.

However, nesting them in each other proves a lot more tricky. I don’t think
there is any reason why you couldn’t embed Om/React component inside of a
Polymer element. Unfortunately, I am not sure it’s possible to go the other
way around. As best as I can tell, React expects to be React all the way
down to the DOM.

With the core and paper elements libraries, Polymer offers a compelling case
for using it. As I am not a web front-end developer, the ability to easily
use nicely-styled widgets and declaratively define animations is
particularly nice. I am not an HTML/CSS/JavaScript wizard, and it would
take me a long time to implement what Polymer provides. Using Polymer, I
can instead spend my time working on my application.

Frankly, I don’t think that ClojureScript is the ideal fit for Polymer. If
you need to use ClojureScript, as in my case where I needed to use
core.async, it’s certainly an option. However, if ClojureScript isn’t
absolutely necessary, consider sticking to JavaScript. In the end, it’s all
about choosing the right tool for the job.