This past week, I had a fantastic time travelling over to Warsaw, Poland for Front Trends 2010 conference. I was very honored to be invited to speak, and I gave the most recent incarnation of my talk on middle-end UI architecture, Rise of the Middle End (slides).
Overall, the reaction in discussions over beer, feedback/ratings, and tweets has been pretty positive. Even for those who seem to strongly disagree with my thoughts on this topic, I’m pleased that people are talking about it, which means they’re thinking about it, which means I accomplished my real goal: get people to start asking the right questions.
After a few twitter conversations on the distinct differences between those two messages, I felt like it would be a good idea for me to write up a quick post to clearly state what I think about the sync/async debate, as I’m not sure it’s been well understood thus far.
Crockford is right
If I wasn’t clear enough, let me say it this way: async is better than sync.
What you really need to understand is that just because you run code synchronously doesn’t mean that such code will only run in a synchronous environment. If you write the code correctly, which I’m trying to do, then synchronous vs. asynchronous execution concerns become rather moot. More on that later below.
Again, let me be clear: BikechainJS is not intended to replace or compete with Node.js.
BikechainJS and my synchronous per-request POC code/demos for the middle-end are merely side shows to the main attraction: the importance of middle-end architecture in the web stack.
The back story
So now, let me explain why I still am showing middle-end code demos using synchronous approaches.
Considering the variety of web application stacks I’ve worked in over the last several years, these architectures have ranged from Java to Grails to .NET to Python to PHP. The code bases have spanned from decent to horrible. Web performance optimization is always a tuning after-thought rather than a key business-driver feature. And the applications have all been built from the back-end up rather than the front-end down.
In all cases (and indeed for most of my 10 year web dev career thus far), some things have been true across the board:
- Universally, when I attempt to re-factor the front-end for web performance optimization, I run into the hassles of not having adequate control over the middle-end pieces (buried deep in the platform/framework guts), and moreover, I often have to deal unnecessarily directly with how the back-end works just to make changes to the front-end.
- And most importantly, they have all been 100% in the synchronous, per-request paradigm of the web stack. They all used synchronous, single-threaded (process-oriented) web servers like Apache or IIS.
That reality may not be your reality where you work. And if not, great. But having had a dozen jobs so far and seeing the same patterns repeated consistently, I’m willing to believe it’s more the norm than the exception that synchronous per-request is the overwhelmingly common paradigm, and that no matter how hard platforms/frameworks try to keep front-end and back-end separate, they all fail to do so well, when the rubber meets the road.
So, mentally walk in my shoes for a moment, in the types of jobs and environments I’ve been in for the majority of my career. The web application code bases are well established, and for the most part working ok. The boss(es), and 3-8 other devs on the team, are all pretty familiar with that paradigm. The IT support staff are all very familiar with the quirks and behaviors of that stack, and are in some cases quite experience/certified in how to manage it and ensure production up-time.
More than anything, stability and status-quo rule the pack.
The plot thickens
Reality check: It is not particularly easy to introduce asynchronous code into a synchronous environment. It requires some very careful planning and often times some complicated and risky changes to existing architecture. In short: it messes with stability and the status quo.
Swim with the current
Is it possible to use Node.js in this way? Theoretically, yes. You can run Node.js as a separate server instance, and from your synchronous code (PHP, Java, etc), make a blocking I/O call over to Node.js to ask it do something, and block the process waiting for the response. You can run Node.js like a proxy server in tandem with Apache, etc.
But notice what we’ve done: we’ve taken something whose almost entire value-proposition is performance from asynchronous eventing, and handcuffed it in an awkward and inefficient way to make it fit into our synchronous world.
Switch into an easier gear
BikechainJS is not designed to replace Node.js, it’s designed to run in all the other places where Node.js is too awkward, risky, or difficult to implement.
Sync vs. Async
Most of the code I’m writing, I’m using Promises as a way to cleanly express logical steps which are reliant on each other, even if one of the steps is not immediate/synchronous. Using Promises, code can easily be written that will either work synchronously or asynchronously with little or no code changes at all.
You see, I obviously don’t want to needlessly tie my code to having to run in a synchronous way. I just want to execute my code synchronously, for now, so that it’s easier to integrate with the rest of the synchronous stack. That’s not so evil, is it?
Putting it into practice
Since the tasks it’s doing are very small and focused, it takes practically no time/overhead at all to do so (certainly way less than constructing and transmitting an HTTP request, even on-server, to a socket server instance).