prose :: and :: conz


Web Development Principles: One Platform

Posted on June 3, 2015

All of that rambling last time about progressive enhancement has a natural consequence in my mind. There should be little-to-no difference between the client and server. I should be able to write an HTML template along with transformation functions which execute in either environment. As much as I love Lift, I don’t dig writing Scala to render a template on the server then JavaScript to modify it on the client. I want to write one function which takes as input my template and my data, and outputs the desired HTML. This should be available to run on the server at page load time, then re-run on the client if the data can change.

As it is today, we have to decide very early in our development where the code will run. I want to delay that decision as long as possible, even until runtime if needed. A good example of this could be the tweet button on Twitter. Let’s assume that pressing the button not only showed us the modal, but updated the URL. (Arguably when we press the tweet button, we should have another URL since it’s another resource, but that’s an argument for a different blog entry). Hence it would be possible to link directly to the tweet modal in addition to summoning it via the tweet button on the timeline. It should be possible to render the tweet modal on the server for when a browser directly links or render in the browser when the user clicks. Certainly this optimization would be overkill for the tweet button, but this is the idea. I want to build in such a way the content can be rendered in either place, client or server.

This inevitably leads me down the road of JavaScript. It’s unavoidable on the browser, so the only choice to realize this vision is to run JavaScript on the server perhaps with Node. It even turns out that we can use JavaScript in native iOS apps, as I learned today during a demo of clojurescript on iOS. If we can reuse our JavaScript even in native apps, then damn. Not to suggest I’m interested in write-once-run-everywhere apps, but having one common language for your browser, server, and native apps sounds fantastic to me.

So here we go. JavaScript love from the Scala guy. Well, no. JavaScript is an absolute terrible and broken language. Only two good decisions were made in the design of JavaScript with respect to using it for application development: (1) Functions/lambdas are first class (yet they still screwed it up by requiring too much ceremony). (2) The world is single-threaded. Everything else about it is crap. It is absolutely riddled with gotchas and I don’t care about the tools we’ve written to catch them.

We can do so much better. Thankfully, compiling good languages to JS is a thing. My team decided to use CoffeeScript to give us a slight boost in this regard. It greatly reduces the syntactic noise, provides a few higher-level abstractions, and gives us expression-based semantics (my favorite enhancement). While this was a good choice for my team at that point in time, the community as a whole can do much better than CoffeeScript.

The first compile-to-JS alternative that comes to my mind is Clojurescript. I like it primarily because it is a functional, expression-based programming language with default immutability. There is an awesome community around it with folks who I enjoy running around with.

I could also consider Scala.js. I got interested in Scala.js really early on when I wanted to play around with scraping Craigslist posts. Unfortunately, I abandoned the idea and never tried it. By the time Scala.js was announced as no longer being experimental, I had completely lost interest.

Why? I feel that neither Clojurescript and Scala.js are what I want to deal with. Neither one was designed to compile to JS. It was an afterthought. As a result, there are pages dedicated to stuff that does not work the same as on the original platform. Clojurescript has this page dedicated to the differences from Clojure. Scala.js likewise has its differences.

If I’m dreaming of all the webs from scratch, I’m not picking one of these two which had to deviate from the original vision to make the compilation to JS use case work. I want something that was designed with JS in mind from day one because that is my target platform. This is where I am gaining a lot of interest lately in Purescript. Although work is being done to target alternative back ends, the very description of the language is one which compiles to JS.

Furthermore, I see little value in supporting multiple platforms with my language of choice. The browser runs JS. Node lets us run the same code on the server. I know that Node is not a great runtime compared to the JVM at this point in time, but I strongly suspect this will greatly improve in the near term. Too many people are keen on it working well, so the work is being done. If my gamble on Node being awesome is right, then compilation to other platforms only benefits us by opening up more library reuse.

Having multiple platforms for the language may actually even hurt the community a bit. What I mean is that a new language’s success depends greatly on leveraging its parent platform’s existing libraries. Having multiple platforms means libraries and applications need to be mindful of where the code will run and hence which library to use. This code then isn’t portable between client and server the way I want it to be. If you want it to be portable, you either have to write adapters for the different libraries or rewrite them from scratch. Both exercises are expensive and counterproductive. I could see a community spending a lot of time on writing these backends, dealing with the portability problem, and not focusing on solutions which build on what is already available.

From what little bit of paying attention I have done, the only multi-platform success I have observed for languages are ones that initially supported a server-side platform and later added JavaScript. I would argue that Clojure/Clojurescript is successful, and the verdict is still out for the still-young Scala.js effort. Scala tried supporting both the JVM and .NET, but the latter eventually died. I Googled around to get an idea of why it died without any good hints. It just seems that no one cares enough to invest more into it. This makes sense to me. Once you have a solid backend platform, what is the value in having a second? So in my mind if you are a JavaScript platform language like Purescript, supporting a server-side backend is now redundant thanks to Node. I suspect that alternative backends will survive about as well as Scala’s .NET support.

Just to be clear, I don’t mean to be antagonistic towards writing alternative platforms for languages like Purescript. I’ll support doing so because there are other benefits which may be important to other people in the community. I just mean that my needs do not require multiple backends, nor is it likely I will apply much effort towards those efforts. Furthermore, I doubt the alternative backend will gain enough attraction in the community as a whole to survive long-term.

While I’m talking about Purescript, I should mention the implicit requirement I have here. The language of my ideal stack will fully embrace the functional programming paradigm. Although I understand it is possible to write functional code in any language, I want one which apologetically favors the paradigm. Furthermore, I want the entire stack to embrace functional programming, avoiding side effects and mutation.

I’m still on the fence about static typing, to be honest. Everyone here knows how much I like it, but there are always compelling arguments against it especially for web development. This is particularly true for the JS platform where we have to do something like TypeScript has to do in order to introduce the types it needs. It is a costly effort with maintenance and should be considered alongside the benefits of static typing.

Even if this ideal stack is written in and for another language like Purescript, I would hope that it is easily consumable from pure JS and other JS-targeting languages. Because Purescript compiles to clean and legible JavaScript, I feel it has much potential for fulfilling this goal. Although I am not a strong proponent for either Play or Akka, I like that the Typesafe Stack embraces using the frameworks from either Scala or Java. Both seem to be better suited for Scala, but they never preclude use by Java. I believe it is a good move to make the library innovation suitable for consumption by the wider community.

There you have it. I’m looking to make the jump from the JVM to Node for my long-term future web adventures. I think that the principle of having one platform for development is just too compelling to ignore. Add to that the fact we have some really strong functional languages targeting JS, I see no reason to continue avoiding it.

Leave a comment below, or send me a tweet.

Tagged with: functional-programming (31), web-development (19), web-development-principles (5), purescript (3)