Why ClojureScript Matters
blog.juxt.pro
blog.juxt.pro
I like Clojure and I am interested in learning ClojureScript but this blog post makes a poor case for it.
Backend and frontend concerns are completely different, and it's fiction that you can simply wave those concerns aside and write the same sort of software anywhere in your stack.
Too often I try to access Java or PHP web services from .Net, where the tooling is very strict, and it just falls apart. Or I'll have to use something via JS that is just excessively painful to use in practice for no good reason.
I've also seen time and again layers of indirection or other design patterns used without any consideration of why they are being used in that instance. You don't have to hide your data tier behind factories of repositories. You don't have to make everything an interface. If you aren't going to test anyway, make the code as simple as possible. I tend to favor only adding complexity if it makes those complicated pieces easier to use in practice, and even then not all the time.
Sorry for the rant, I just see time and again certain levels of complexity without flexibility or consideration for why.
On the other hand trying to use anything from .NET land that implements WS-Security from PHP or Java is also exceedingly painful. I recently had to integrate very similar APIs from 5 different companies into an internal application...
One used an HTTP(s) REST API written in PHP, it used mod_auth and I was done in 30 minutes.
One used SOAP with some custom extensions, I hacked around a bit with the PHP SOAP classes and was done in a few hours.
One used WS-Security, and after a few days of hacking around I ended up using Netbeans' tooling to generate a Java client that could consume the service and forward the results to PHP.
Another used a (more recent) version of WS-Security and the same trick wouldn't work, so I contacted their support who admirably tried to create a java client to consume the service, gave up, and created a regular SOAP bridge for us to use.
One company is still trying to get our AD credentials set up with their vendor software that uses Biztalk somehow (they've been scarce on the details) after two months of waiting.
RESTful services in PHP and Java may not have a pretty GUI configuration tool, but they are much simpler to get working than SOAP and any of the MS extensions in my experience.
That said, I've never really been a fan of SOAP in general, and WS-(death)* is painful in any system. Funny enough, I've found node.js to be the easiest middle-man to coerce into using different services as a gateway, and it's my go-to when a wsdl doesn't import cleanly into a .Net project, and just define my own JSON/REST interface in front of the foreign services for the parts I need.
AD integration is particularly painful, and pretty much only works in IIS, in that case, I'd lean towards writing a shim in ASP.Net MVC exposing JSON endpoints, in a similar fashion.
Typically, backend developers need to have specialized knowledge of the enterprise security system which needs to be invokoked for authorization requests. Also the backend developers need to worry about availability/clustering issues. They also have to be familiar with caching subsystems in place , observe or predict the api requests patternt and implement caching strategies. They have to deal with a 'different scale' of concurrency issues than normal ui devs. The there is the issue of api versioning: there will be clients/user who will not upgrade and the backend development team has to figure how to support multiple versions of the same API. Then there is the issue of deployment and packaging: not every development shop lets developer push deployment into directly into production.Then there is the issue of database queries : you will have to optimize those heavily in consultation with your database admin. If you are using JVM, you have to optimize that for your application. The frontend development work has its own set of equally vexing challenges.
There is no doubt that any competent developer can handle all these tasks but it won't be the kumbaya singing utopian happy habitable code paradise that this blogger is seeking. Division of labor between backend and frontend is a life saver for developers. I would actually want to go home and not spend my life in this "habitable" place.
We've got a large Node.js codebase. Some of the code runs only on the server, some runs only on the client, but the majority runs on both. Our code is split into modules for functional reasons.
To say that the client/server split is "arbitrary" is rather silly.
(That's not to say I'm not a fan of an end-to-end language. Meteor shows what you can do with this. Maybe ClojureScript can do this, but with a better language.)
Which is very reasonable, btw, as it allows you to have a static site that renders for those whoes browsers doesn't run javascript and a more dynamic page for those whoes browser does run Javascript. You are guaranteed that everything renders the same way only if you excecute the same code (this can't be replaced by e.g a sensible template system because rendering might also be affected by how you, e.g, sort comments).
What does this mean exactly? What kind of code needs to run on both?
You can optionally choose to include Meteor methods (ajax-style remote endpoints) on the client. Then when the method is called, the client-side version is run in addition to the real, server-side one being kicked off. If the server-side returns an error, such as due to insufficient permissions, the changes made client-side are rolled back. Combined with Meteor's client-side mongo implementation and reactive UI updates, it gives impressive "perceived performance" benefits.
A simple one is validation of forms, but also doing rapid UI updates without having to do network round-trips.
validation
routing
modular business logic e.g. - calculate total interest paid over the life of the loan provided the client pays x per month etc etc
Maybe breaking off a small piece of functionality in a Java project to try implementing in Clojure.
Maybe implementing a service with a REST API in Clojure accessed from clients written in other languages.
So I find it a little ironic, and maybe short sighted, to hear "write everything in one language" used as an argument for using Clojurescript.
It's an artifact of having competent developers, be they full stack or not.
I feel the benefits are worth it for my use case, but it's not all roses.
But hiding the client server architecture is just a bizarre criticism to me, because it's not at all what writing one of these projects is like, and I'm not sure how you're even getting that impression.
The degree to which you share code depends on how much functionality you are replicating, and is code that you would literally be cut paste porting if you were using another toolset. Or just avoiding writing altogether, like speculative updates.
Just because you can theoretically attempt an antipattern doesn't make a tool bad; you can write shit in any language. And many do.
Remote hardware just accentuates issues that are only obvious due to high latency. A local system for example could get away with a less sophisticated locking mechanism... until it doesn't.
Not having the backend developer/fronted developer split is good; while each will have its own specialities, they shouldn't be siloed into separate teams.
If you haven't used ClojureScript, it is definitely worth looking at.
With ClojureScript I always have probelems to get running, and how to devlop effectivly. All the information are old and outdated.
I love the idea of DataScipt/React but I have not really done to much until now.
Edit: I know of the creaters blog, but I would like more.
An emphasis on low-level tooling and not enough discussion around high-level architecture/examples has hurt the react+cljs combo adoption from my point of view. It's the nature of Lisp to come up with your own abstractions around application architecture, but the community would be wise to talk more about solving common web patterns and how to cleanly break away from those patterns when necessary.
https://github.com/levand/quiescent/blob/release/src/quiesce...
That said, I've really enjoyed Reagent for prototyping, and the magic is the good kind of magic. It's just that Quiescent feels so much like a clojure library, trading ease for simplicity — and is often a better brick to build your own abstractions on top of.
Look at this example code, apparently held in such high regard that it is referenced off the front page of OM: https://github.com/swannodette/om-sync To me that is a ghastly, inexcusably complected hairball.
Don't get me wrong. I really like clojurescript. I program in it daily, on purpose. It is just that I'm shocked at the level of devotion and adulation for OM when there are really lovely alternatives like Reagent and Rum.
If you don't like Om, that's really OK. The real goal of Om was always to inspire people to consider and research alternatives to traditional client-side MVC. 16 months in I would say with the large number of excellent alternatives, Om very much succeeded.
I hope Om Next accomplishes the same broad goal and convinces people to seriously consider the big ideas behind Relay/GraphQL, JSONGraph/Falcor, and Datomic.
And no message channels? Why then does the intermediate tutorial plunge straight into the use of core.async?
I have no problem with OM being considered a grand experiment. I wouldn't use it but it has been an interesting idea generator. Please remember context here - I was responding to someone who claims astonishment that OM could be considered difficult to understand.
But, in terms of grand experiments, let's remember that Reagent came out at exactly the same time as OM. And Hoplon lead the way on Reative (FRP) long before either. So, having lived through it, I'd feel very uncomfortable with any overreaching claims about OM succeeding in inspiring all the others into the alternative MVC holy land. The others were there already.
From the people that know it well, they all love it. But I don't seem to have the required knowledge to understand it. I feel somehow dumb by that. The docs aren't good also.
After that, I've tried reagent for 30 minutes and ended up with a lot of progress and I'm currently writing my first cljs small app. Everything seems to work and it's like clojure.
You have an atom and just have to write views in a hiccup style, everything magically works.
Maybe I will try Om later and get it, but it's not simple. I've been able to wrap my head around a lot of concepts with easy in my life, but Om felt too much.
When I get this feeling, it's often because I haven't yet experienced the problems the new thing is trying to solve. Is it possible Om is an attempt to solve problems you haven't encountered?
I have no personal experience with Clojurescript (love Clojure, though), so this is just a generic comment.
I looked at Om, found it too verbose, and switched to Reagent. I then found it too limiting, so I ended up using Rum, which I think is the most flexible and the most minimalistic. I think it's great that we have the choice and that we can cross-polinate ideas between various libraries.
The thing that helped my understanding most was a recent project where I got to work with React directly. Also, reading the source.
So yes, it's mostly because I'm a little lazy, but Reagent doesn't seem to punish me for that same laziness. 😆
EDIT: More details.
I find that Om has very strong opinions about doing state the clojure way, but is a very thin wrapper around the rest of React's API - which leads to a feeling of inconsistency.
Some of the stuff David's suggested will be part of "Om next" I think will address this.
This abstracts out all the reify stuff and makes for far cleaner component definitions.
Not to take anything from Om tho, people using it seem to enjoy it a lot! I guess I'm just less smart ;-)
I don't like that he seems to have to concoct that argument to sell ClojureScript. The argument seems artificial.
There's lots of reasons to decouple the front-end development from backend development. In fact, once you start using a client framework and use the backend as a service layer you can really decouple your layers. Doing web stuff, I primarily work in ASP.NET MVC and I'm trying to get rid of razor completely.
In fact, If I had my way, I'd have css/photoshop jockeyes (with a little angular/whatever knowledge) in charge of the client, a javascript/Typescript guy doing the client MVC, and a data guy doing Web API.
Agile tends to frown on these distinctions. I don't buy it , just like I don't buy a lot of the Agile dogma. Oh well.
But how about designers have 18,000 other things to deal with and maybe they aren't interested in learning (in their estimation) the latest wacky-ass way web developers invented to generate HTML. The point isn't that they couldn't understand it if they tried, the point is that they would have to try, perhaps to the exclusion of something they would consider more useful.
I can't wait for WebAssembly though... it will be a game changer for people that prefer strong static typing for managing logical complexity.
Also, The interactive REPL based workflow that a lot of the LISP languages utilize is extremely appealing. I've been thinking a lot about how to bring this back into the JS world. I have yet to find any good literature on it, but I will be exploring this area more.
For those curious, here are some blogs that convinced me to finally give Clojure a spin:
- http://rigsomelight.com/2014/05/01/interactive-programming-f... (seems like this is the stereotypical "you should try ClojureScript because... " post)
- http://thinkrelevance.com/blog/2013/06/04/clojure-workflow-r... (a bit code-heavy, but an admirable workflow)
- http://swannodette.github.io/2013/11/07/clojurescript-101/ (dealing with asynchronous code)
I'm curious HN, anyone out there making strides in interactive JS development, akin to the 2nd blog post I referenced above?
I appreciate the The CS team trying to work with 3rd party repl developers right now, but it doesn't seem to be helping much. It's pushed me back to simple gulp based es6 dev using ramda, rxjs, immutablejs, etc - basically the parts of clojurescript I like. The only thing I sort of miss from Clojure are macros and homoiconicity - it sure is nice to look so uniform, but the tooling just drives me away.
Clojurescript -should- be calming down soon. It is in a stage of changing constantly ATM but that should calm down once some of the underlying tech is stabilized (like clojurescript bootstrapped from clojurescript).
But I'm somewhat OK with it, as the changes generally seem to be positive, and I have hope that the stability will coalesce around a good, rather than rotten-but-papered-over, core.
The JS equivalent of figwheel is React Hot Loader[1]. There's a port of core.async[2] but I've also seen people using Babelized ES7 async/await for avoiding callbacks. The reloaded workflow is just a pattern around building objects with a topological sort for order initialization. I expect you could build a JS version in ~200 lines of code.
[1] https://github.com/gaearon/react-hot-loader [2] https://github.com/ubolonton/js-csp
I'm unaware of editor integration between an editor and browser runtime a la slime/nrepl. I think LightTable had a basic implementation but it's been a while and I could be remembering it incorrectly.
This is identical to what you'd be doing on react+node. With a macro or two, it's easier than anything node provides.
As an aside, isomorphic isn't a new anything. We were rendering pages on the server, rendering updates on the server with the same templates, sticking them in xml representing jquery dom manipulation, and pipelining those in a single request since at least 2007 (when I first encountered the technique and shipped with it, I believe we used a javascript library called Taconite, maybe since 2005 from looking at the sourceforge account). Progressive enhancements were rendered off the same templates and inserted asynchronously, automatically, based on whether the controller on the server detected it was an ajax request or a bare GET. This incidentally made things very cacheable.
You're being disingenuous, I read the ClojureScript mailing list, this subject comes up regularly. People are still figuring it out, Nashorn is not well documented and the use of it for this purpose is not well documented. Please don't pretend like something is a common thing when it's not.
EDIT: The example in the link provided builds on the now deprecated CLJX, so it's not entirely up to speed. (CLJX was the way to write clj/cljs in the same codebase until "reader conditionals" came along).
Wasm is definitely a good start, but it is only a start right now. It's a good target for AOT languages, but really not suitable for interpreted or JITed ones right now.
The perf may be slightly worse, but we've had good-enough perf forever.
The tooling still isn't quite ready yet. I've tried porting some `.cljx` code over, but it's not quite working for me yet with leiningen.
If nothing else it has added another unit of weight to the idea that I need to adopt CljS quickly before I am left completely behind. Now all I need is a project and more free time than I currently have... ;-)
Also, another thing to look at is eithe Facebook's flow or Typescript. It adds some type checking, really great. Especially if you are writing server side in Node.
I've used classes in CoffeeScript and regretted it every single time. Once your web project starts to grow in scale classes quickly become your first pain point. Especially given how functional JS libraries have become nowadays.
(edit: downvote for a typically well-thought-of idiom, especially with regard to a language like js? .. if you disagree, why not talk about it?)
If you need to write performance critical JavaScript, then allocating new objects will be just as slow as creating new closures. In either cases you should allocate them ahead of time and then closures are still the clear winner.
Actually... creating an object instance via a constructor lets the runtime use an internal class, which improves performance (as long as you don't modify its properties post-construction). This is a well-known aspect of V8 performance.
No, it won't. This code:
function createThing() {
return {
doSomething: function(){}
};
}
Performs much worse (at scale) than this code: new Thing();
And it consumes a lot more memory since Thing.prototype.doSomething is 1 function in memory and the former is N functions. function doSomething(obj){}
var objs = [{},{},{}];
objs.forEach(doSomething);
If I need late binding I'll use something like clojure's multi-methods. Both closures and prototypes aren't needed for this :)But if object instantiation / garbage collection is your bottle neck, you should be using an object pool, anyways.
You wouldn't put _every_ object in an object pool, though - only those which obviously impact performance after identifying them as a bottleneck.
I'd hope you optimize for maintainability before you optimize for performance, otherwise you'll end up optimizing bottlenecks that don't exist.
Also, how is ES6 more interesting than ClojureScript?