Is JavaScript ready for serious development? – Part II

In my previous post, I made the claim that JavaScript is not ready for serious development. Now, it’s time to back up my claim.

I don’t care what anyone else says about how easy JavaScript is, how well it performs and so on because any gain one might get in one area is completely overshadowed by many fundamental features missing in JavaScript. Here are some very basic but fundamental features that you would expect from a modern language that JavaScript simply does not have.

No Visibility Control

There’s no notion of public, protected, private or constant/final variables in JavaScript. Everything is just a plain “var” or a “function” that everyone else sees and has access to and change. Ok, you can define vars in functions and that somewhat hides them but when a var is declared, I want to be able to say whether it’s public, protected or private. This helps in many ways that I don’t even think I need to explain and the lack of it turns me off as a serious developer. So, what do you do? You end up coming up with a set of rules on your own. In our project, we treated all upper case variables as constants, we treated variables that start with underscore as private etc. so you can deal with this problem on your own but it’s not ideal. I expect the language to enforce these rules because if a rule is not enforced, someone is certainly going to break it.

No True Object-Oriented Programming Model

In JavaScript, Object-Oriented programing simply means “Here’s an Object with a few key/value pairs and functions” and that’s it. There’s no way of defining a class like in Java or ActionScript, no way a subclass extending from a super class, no interfaces or abstract classes, not even function overloading for God’s sake! This is very frustrating because in 2011, you expect these from a serious language. Instead, you have bunch of frameworks or best-practices to mimic Object-Oriented programming. For example, in our project, we started using John Resig’s Inheritance Model which works OK but has a few bugs and quirks. We recently discovered Google’s Closure Library  that also has an inheritance model among other things. It’s good that there’s help out there but then again, language itself should provide these not random frameworks.

No Package/Namespace Support

Any serious project needs some way of organizing code, and in modern languages, this is done by using a file per class and then combining multiple files into packages. Unfortunately, JavaScript does not enforce a file per class rule and it has no notion of packages or namespaces. You are again left alone to deal with this on your own. For example, you can create “namespace objects” and attach functions/classes to it. For example:

var dev = {};
dev.echoservice = {};
dev.echoservice.Book = function()

You also need to manage dependencies, so if class A depends on class B, you need to make sure class B is listed earlier than class A in the JavaScript file. In our project, we used separate files for each JavaScript class, and then we used an Ant task to combine all JavaScript files into a single file with the right order. Recently, I discovered that Google’s Closure Library has some dependency support that looks useful but nothing in the language itself.

No Proper Hashtable/Map Support

In JavaScript, you can use Objects as Maps but the problem is keys can only be Strings. This works for simple applications but for many complex applications, you need Objects as keys. Fortunately, there are open source implementations like JSHashtable but the language itself leaves a lot to be desired for.

No Byte Array or DataInput/Output Support

Another major missing component in JavaScript is proper byte array support. There are many use cases where you simply want to send and receive a byte array. Unfortunately, there’s no native byte array support in JavaScript yet. Internet Explorer has a byte array implementation but it’s VBScript and not standard. People try to fake byte arrays by sending bytes as Strings and using String#charCodeAt and String#fromCharCode to interpret String as bytes but this is simply asking for trouble because many browsers mess with incoming/outgoing bytes. There are hacks (search for “charset=x-user-defined”) to deal with those or some browsers such as Firefox have non-standard ways of dealing with this (see Firefox’s XMLHttpRequest#sendAsBinary method) but nothing that feels non-hack.

As a related note, there are no DataInput/Output streams either, so even if you manage to send bytes as String, then you need to interpret those bytes on your own. For example, if you need to send/receive floats, you need to understand and implement IEEE-754 on your own instead of depending on the language. I did this and I can assure you that I lost good 2-3 days of my life during the process 🙂 Be ready to pull some of your hair out as you’re dealing with byte arrays in JavaScript.

No Syntactic Sugar

After so many fundamental features missing from JavaScript, I wasn’t holding my breath for syntactic sugar and soon it was clear that there weren’t any.

In Java, you can get your IDE create getters/setters for your property automatically. In ActionScript, getters/setters are built into the language which is very nice. In JavaScript, without visibility control, there’s no support or need for getters/setters. This is not as big a deal as other problems but it’d be nice to have ActionScript like getter/setter support built into the language.

Another one is annotations. Annotating code with useful information is becoming standard nowadays and they are useful in many ways. Unfortunately, JavaScript has no support for annotations in any shape or form as far as I can tell.

I’m sure there are other things missing that I can’t remember right now but if you’re not convinced that JavaScript is an inadequate language for complex projects so far, then watch for my next post where I’ll talk about how browser inconsistencies makes things even worse…

Advertisements

11 thoughts on “Is JavaScript ready for serious development? – Part II

  1. You seem to be stretching things a little but you make some god points.
    For one thing, you can mimic visibility using closures, so while it’s not part of the declaration of the variable, you can replicate the functionality if you’re serious about it.

    Your complaint about the “random frameworks” out there is a strength of the language, not a pitfall. The fact that these frameworks exist shows off the flexibility of its prototypical model.

    And the whole point on annotations is strange. That kind of stuff comes from the IDE, not the language itself. If you want an IDE to give you some sort of annotation support, they can in theory do that for you.

  2. Well, my point was that I shouldn’t have to mimic something simple fundamental like visibility with something that is not intended to fix visibility (i.e. closure). The language should have a way of enforcing that in a nice clean way for everyone looking at the code, i.e. public/protected/private.

    True that frameworks make the ecosystem around the language better, but again, I shouldn’t have to depend on a framework for fundamental things like inheritance, events, hashmaps, floating points.

    Regarding flexibility, it’s a good thing as long as it doesn’t cause ambiguity and I feel like JavaScript is too flexible in that sense. Everything being a “var” without any type information might be good for some projects but it’s a nightmare for large projects, I can assure you.

    Do you know about @Override annotation in Java or override keyword in ActionScript? These are part of the language not an IDE construct really.

  3. I agree that these are problems, but I think it’s a bit much to say that JavaScript isn’t ready for serious development. People have been doing serious development in C for years, and I don’t think anyone would argue that C couldn’t be improved.

    For me the biggest issue is with packages/namespaces. Modularity is absolutely fundamental to programming. Luckily things are improving on this front, just not fast enough for my taste.

  4. Your comment about flexibility misses the point. You can build rules on top of a flexible language like Javascript. In contrast, Java sucks when you want to do something simple. Show me anything that does the reverse for Java and allows you to do simple things easily.

    http://code.google.com/p/relief/source/browse/trunk/relief/commands/get_command.js

    Take a look at this JS file. It is written to utilize Google’s Closure Library, the type checking of the Compiler, and written to the style enforced by the Closure Linter. There are certainly tools to allow JS development at scale – Closure being chief among them.

    This file defines a namespaced class, “relief.commands.GetCommand”, that extends an abstract base class (“relief.commands.Command” – see Lines 51 and 71). It overrides super-class methods (look for methods annoted with “@inheritDoc”).

    It even includes a private inner class (“relief.commands.GetCommand.CacheValue_”) and a public inner enum (“relief.commands.GetCommand.ResponseType”). Notice the immediately recognizable difference between public and private names here.

    For another example of public/private naming, just take a look at the instance members defined in the constructor: “this.readFromCache” and “this.writeToCache” (public) and “this.type_” (private). Immediately recognizable and unambiguous.

    Java’s hash maps convert objects to integer hash codes to use as keys. Javascript objects convert themselves to strings to use as keys. The difference is superficial and inconsequential, in my opinion. For one you define a “hashCode()” method, for the other you define a “toString()” method.

    The next version of JS includes binary arrays. May browsers even have these implemented already.

    You showed how namespaces are used in JS. Claiming that having to type those three lines is excessive really comes across as simple laziness.

    ES5 has support for getters and setters (and even making object properties unchangeable).

    Annotations are extra-linguistic. They are there for tools to process; they’re not part of the language. @Override is used by the Java compiler as an added safety check – it’s not part of the language specification. If you use the Closure Compiler, there are many equivalent annotations available for JS code (the above file has tons of examples of these).

    Overall, this post comes across as though you wish Javascript were Java. It’s not. Different languages are different and just because one does not look like your favorite language doesn’t make it inferior. There are a lot of trade-offs between strongly typed Java and dynamically typed Javascript. In my opinion, I’ll take JS over Java any day.

  5. Nathan, yes, people use C for serious development even though it’s not an ideal language to work with but if you work on a new project with no low level dependencies or very strict performance requirements, the odds are you won’t choose C. Everyone understands and accepts that C is a legacy language with a specific domain.

    On the other hand, JavaScript is being promoted as the language of the web where the latest and greatest is supposed to be built with but my experience so far hasn’t convinced me that it’s that kind of a language.

    As I mentioned in my previous post, you can write complex software with JavaScript but the language itself does not really make you feel like it’s built for complex software. That’s why you see bunch of frameworks and tools trying to fill the gaps I outlined and that’s great but it also proves the gaps I’m talking about.

  6. Hi Mete,

    you’ve made very good points and I tend to agree with them all, but I disagree withe the conclusion that JS might not be ready for serious development.

    I think that there’s a balance and you’ve only put bad things in one of the sides. I think that there’re lots of incredible good things on the other side too. Something that I really like is the oop capabilities. while you might not have accessors or visibility built-in (I agree that the solutions sound hackish) you have a tremendous and very nice way to create interceptors, wrappers, mocks, mixins. There’re very nice techniques out there to do this that with other languages are terrrificly complex and require a significant amount of work or complex library as a foundation.

  7. Jay, neither you nor I should be building rules for a language but rather the language itself should enforce those rules. That’s the only way to make sure people write consistent code, otherwise, it’s 100% certain that someone else will come up with some other rule or break the existing rules you or I put in.

    I’m aware of Google’s Closure Library and it’s fantastic that Google is trying to make JavaScript developers’ lives a little easier by providing these tools but all the things you pointed out about underscore for private, namespaces etc. are rules enforced by Google’s tools. My whole point is that these are fundamental to a language and the language itself should enforce these. I’m certain one day JavaScript will turn into a more typed language with more checks (even if they are optional) because that’s really the only way to make sure consistent code is being written but it’s not there yet.

    Re. your laziness comment on namespaces, you completely missed my point. I’m not complaining that I need to type those three lines. I’m complaining that I’m simply creating an object of an object of an object and assigning a function to it to create the illusion of a namespace. I’m sure objects of objects are not designed for namespaces in JavaScript and that’s just one more example that shows how JavaScript was not designed for complexity in mind.

    Everything about the language smells like it was designed to add some interactivity to some UI elements that would otherwise be very hard to do with a markup language ilke HTML.

    I don’t really care about Java or ActionScript or C#, neither do I want JavaScript to be like one of them. Unlike what you think, I don’t want complexity just for the sake of complexity. I simply care about consistent and clear language that allows complex hierarchies to be represented in code and I feel like JavaScript does not provide me that. Tools like Google Closure Library and other frameworks somewhat try to fill that gap but JavaScript as a language leaves a lot to be desired for.

  8. Hi Xavi, I’m just speaking from my experience so far and maybe you’re right that there are many good things about JavaScript that I’m simply missing at this point. I’m keen to learn those techniques you mentioned. Could you share some links/info about them and hopefully they’ll help me to build a more positive image of JavaScript?

  9. Hey Mete,

    Here are some articles I found very interesting. They are framework specific but will give you a sense of what I mean:

    http://edspencer.net/2011/01/ext-js-4-the-class-definition-pipeline.html
    http://edspencer.net/2011/01/classes-in-ext-js-4-under-the-hood.html
    http://www.sencha.com/blog/countdown-to-ext-js-4-dynamic-loading-and-new-class-system

    I’d also highly recommend reading the
    “Secrets of the JavaScript Ninja” book http://www.manning.com/resig/

  10. I agree with all your statements and want to add more items to this list. Items that you may disagree with, but that are important for me as a developer:

    1. Integrity check (compiled languages have this check by design)
    2. Static typing. It turned out that static typing is a great help for really large projects. I prefer static typing with an ability to use dynamic typing at will.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s