Quantcast
Channel: Nicholas Hagen » Javascript
Viewing all articles
Browse latest Browse all 7

JavaScript as the Future? My Personal Opinions

0
0

I have long had mixed feelings on the future of JavaScript. Many people believe it is the future. Others believe it is the new VM of development (similar to Java). Others believe it as the sole language across server and client-side development (one language to rule them all). So, where do I stand? I stand somewhere between I guess. I believe the concept of JavaScript as a VM supporting new languages like CoffeeScript, Dart, TypeScript, etc. In fact, I applaud those efforts. JavaScript, as a language, moves at such a snail pace due to lack of quick browser integration. As a result, the language, syntactally, is out-dated, whereas the newer languages such as CoffeeScript, Dart, and TypeScript compile into JavaScript but provide several syntactic sugar syntaxes. My biggest issue is that these languages still have to compile into JavaScript and be at the mercy of server side providers (V8/Node.js) and browser vendors. I’m also not a believer in JavaScript as a scaling language, performance and development-wise, at least compared to other languages (Java, Ruby, Python, etc). JavaScript is definitely a great language, but it has several pitfalls that I believe the “cool-factor” simply ignores in order to tout its resurgence. JavaScript definitely has a place, but often times there are better choices that developers fail to utilize because they want to use JavaScript as the cool kid on the block. The right tool needs to be used for the right job to be successful.

I’ve been using JavaScript for years in various varieties. Every time, I end up having too many issues or end up in complexity to believe JavaScript is the answer. In contrast to many JavaScript advocates, I’m primarily a JVM-based developer and have seen the power of modern day languages on the JVM, notably Groovy. People often blame my JavaScript ignorance on lack of knowledge and understanding. There may be some truth there (I’m a backend engineer on the JVM, so JavaScript is not my day job), but it’s not the entire truth. JavaScript has pitfalls regardless if people want to admit it or not. Personally I think that die hard JavaScript developers just “deal” with it, ignore it, or have not seen the advancements of other modern day languages to realize the pitfalls.

My biggest issue with JavaScript as of late is the lack of threading. Many developers, including myself, develop libraries on both Node.js for the server and the browser as the client. This means you develop for the lesser of the two: browsers. This means you are bound by a single thread in the browser. Why is that an issue you say? Isn’t event driven programming far superior? Aren’t threading and multi-threading concurrent applications problematic and complex? The answer to all those questions is yes, as a developer (key part is “as a developer”). The browser and Node.js are not developers; they are libraries and systems that abstract away the complexity of development from the developer. This is especially true in request/response systems such as the web. Think about Java servlets or Apache’s http server or even Node.js/Vert.x clustering. As a developer you design code in a single thread of work, but the underlying system uses multiple threads (or processes in the case of Node.js). The system enforces, rightfully so, that single thread of work. Behind the scenes they concurrently process hundreds of requests. That means, as a developer, you have simplicity in your code and any pauses (ie: remote calls, database invocations, etc) do not block the world. In JavaScript, this is very much not true. If you block anything, you block everything, including the browser application, leading to poor application performance. The answer in JavaScript is event driven programming or callbacks. Fundamentally, there is nothing wrong with that. They are often times very strong design patterns for performance and simplicity in design. In fact, almost every modern day language (even Java), use them where they make sense. For example, many of the utility classes in Groovy heavily use the concept of closures or listeners. The problem is that JavaScript enforces it so heavily (because any minor pause is a stop the world pause), that you quickly end up in callback hell. I realize that there are improved ways of dealing with that such as deferrals and promises. Realistically, though, those are not solutions. Instead, they are bandaids to a broken problem in the first place: lack of threading. Callback hell in JavaScript only exists because every pause blocks everything. If that were not true and the browser still processed while the JavaScript application thread was paused, you would make far less callbacks. The truth is that whether you end up in callback hell or utilize some library such as promises, the result is always the same: far more complexity than is needed. Remember the notion of KISS? Any real world JavaScript application on the browser fails to meet that criteria due to having to ensure every operation is non-blocking.

I heavily realized this recently. I needed to write a generic iteration method that could accept a callback for writing data:

Utils.forEach(array, function(item, writer) { /* write stuff */ });

If you think about this, the solution is fairly straightforward:

Utils.forEach = function(array, callback) {
    var i;
    for (i = 0; i < array.length; i++) {
        callback(array[i], Context.writer);
    }
};

What’s the problem, you ask? Well, what if I told you that the callback was allowed to do anything, including make remote invocations:

var callback = function(item, writer) {
    $.get('/api/' + item.id, function(json) {
        writer.write(json.result);
    });
};

If you use this callback to the Utils.forEach method, it will fail to work as expected because the AJAX invocations will happen at some point in the future. The solution to this and keeping to simplicity, is to use a synchronous AJAX request. However, that means blocking everything, which is obviously not an option. That is where JavaScript fails. It requires you to take simplicity and over-complicate it. This is not just for AJAX, it goes for anything that could block, including I/O. For example, to fix our 6-line Utils.forEach implementation to support asynchronous callbacks leads to the following hard to read code:

Utils.forEach = function(array, callback) {
    var i, iterator;
    i = 0;
    iterator = function() {
        if (i < array.length) {
            i++;
            callback(array[i], Context.writer, iterator);
        }
    };
    iterator();
};

That’s now an 11-line hard to follow function doing weird workarounds like creating a temporary callback iterator and recursively invoking itself. If you did not catch it yet, this is not complete. We have to then modify our user callback to accept that third callback parameter and make sure it invokes the iterator callback. This requires a dependence on both sides, which is another no-no in computer science (loose coupling anyone?)

var callback = function(item, writer, iterator) {
    $.get('/api/' + item.id, function(json) {
        writer.write(json.result);
        iterator();
    });
};

In any other language that has multi-threads and application pauses do not block everything, the original method works just fine. This is very unfortunate in JavaScript. Although, I have plenty of other issues for the language, but that’s for another time and many of those are being solved by languages such as CoffeeScript, Dart and TypeScript or even by the upcoming EcmaScript 6 standard. Unfortunately, the latter won’t happen in browsers for a few years out. The threading issue will continue to be a hinderance for application simplicity and scalability (development-wise).

Will JavaScript be the next VM or the future of development? Time will certainly tell. Until JavaScript allows some form of true behind the scenes threading where the application does not entirely block, I do not buy into it even though I’m sure I’ll continue working in it. By the way, yes I know web workers exist, but again that’s another bandaid to the original problem and web workers have too many other issues and inherent complexity. Personally, I know other systems such as Groovy and Grails offer so many more advantages and I choose the language that offers the best advantages for a given use case.

As a last aside, one of the things I love about Grails (or Spring on Java) is AOP (aspect oriented programming). AOP allows loose coupling in a high degree by moving cross cutting concerns (logging, debugging, performance metrics, etc) away from the application. This is easy in Grails because you wrap the method in a proxy and detect the start and end of the function. With JavaScript, the end of the function is often times not the end of the function, because it has to invoke a callback. Take the AJAX example callback above. If I wanted to inject timing statements around that, it would be very fast because the AJAX call happens in the background. It would have to magically know that a callback was invoked and wrap that as well. That is near impossible which is why AOP libraries do not effectively work in JavaScript. This is yet another reason why I choose Grails over JavaScript. As applications become more complex, these options do not exist in JavaScript, because of the nature of the language. Hopefully this changes over time so JavaScript can become a better framework for real world applications while still maintaining their simplicity.


Viewing all articles
Browse latest Browse all 7

Latest Images

Trending Articles





Latest Images