JavaScript is not suitable for large web apps
blogs.adobe.com
blogs.adobe.com
When faced with a project in which code modularization was a problem, his proposed solution was to port the code? Seriously? Port Javascript to Actionscript because the .js was organized into too few modules?
mmmm-okay.
First of all, put a comment at the top of your function that says what to expect about the return value. You should be doing this anyway because the return type alone is often not sufficient for future programmers reading your code.
Secondly, every time you write the word "return", look up at the top of your function and make sure you are in accordance with what you said the function would do. If you end up with a paragraph comment about what the return value will be like, refactor.
Right, and you can do structured programming in assembly. But when the language or tools don't help you do that, there are examples like the one the author points out where developers don't.
Don't mistake utility (what can be done) for usability (what is easy to do). Usability always matters.
> First of all, put a comment at the top of your function that says what to expect about the return value.
I want a language that gives me a nice pleasant syntax for doing that.
> Secondly, every time you write the word "return", look up at the top of your function and make sure you are in accordance with what you said the function would do.
As a programmer, you should be trained that when you see "every time", you think "automate this". If you and everyone on your team and everyone who has ever been on your team has to remember to do something every single time, your code will accumulate a pile of instances of forgetting.
Fixing that is exactly what tools and languages are for. It's a hell of a lot easier to make a disciplined tool than a more disciplined programmer. (And when you have made a more disciplined programmer, they typically evidence that by asking for more disciplined tools.)
I want a language that gives me a nice pleasant syntax for doing that.
And I want a magic pony; but as I said, declaring the return type doesn't tell users anywhere near all they need to know in many cases. Truly self documenting code doesn't exist, and will probably never exist. And since you can't usefully discuss the return value without implicitly disclosing its type in the comments, declaring the type in the code is redundant.
Now granted, there are a few nice features that you get in terms of debugging by declaring the type in a way that the computer can read. But I don't think I have personally ever actually run into a bug in a dynamically typed language that would have been avoided by a static type system.
Conversely, there are some nice things you can do when the compiler isn't breathing down your neck to make sure that all of your types are consistent. If we had a static type system that allowed me to do elegant, type-agnostic things without getting in my way, that would be lovely. Haskell comes close, but even it falls short of the ideal. Ultimately I have never found the trade off to be worthwhile.
As a programmer, you should be trained that when you see "every time", you think "automate this".
I think that's pretty specious. You do need to consistently check to make sure that your code matches your comments and documentation. You simply can't automate that because humans and computers do not speak the same language.
This magic pony exists. That's what the author is trying to say. You can write magic pony code, and it can be run as JavaScript. Magic Pony -> JS Conversion!
Also, the OP doesn't have an issue dynamic languages as much as weak typed languages. It just happens that JS is weak and dynamic, while AS is strong and static.
Having switched between Java, ActionScript and JavaScript for the last four years, I can assure you that bugs happen all the time in weakly typed languages that wouldn't compile in strongly typed languages. Sure, it doesn't make it past refreshing the browser, but it's not uncommon for a coworker to check in changes to a JavaScript class that completely breaks a part of the application that the dev wasn't thinking about.
For instance, I've seen return objects switch from strings to ints because of how the strings were concatenated (return "Item " + x/returns string/; -> return x/returns int/;). Somewhere else in the function it returns early with "". Now you have other functions in other classes that check someFunction().length... error... sometimes...
The point is, you now have to write unit tests to check the TYPE of each value, and in many cases, it's not easy to tell. To check if an item is an array in JS, you have to do: Object.prototype.toString.call(obj) === '[object Array]'...
Since this checking needs to be done anyways, I'd rather it be done by the compiler rather than by a dev remembering to write a test for each possibility.
You don't need to write unit tests to check the type of each value, you just need to have a decent set of integration tests to make sure you aren't breaking other parts of the app. If errors in the browser after a refresh don't help you catch it, failing integration tests will. This is how we do things on my large scale javascript project and it works out just fine; we have development challenges, for sure, but weak/dynamic typing issues is not one of them.
It doesn't declare all they need to know, but it covers a good fraction of it. As a really nice bonus, it's machine checkable.
> And since you can't usefully discuss the return value without implicitly disclosing its type in the comments
I don't seem to have this problem. I have lots of comments that are like:
// Copies [from] to [to].
copyFile(File from, String to) { ... }
Note that the comment didn't redundantly point out that "from" is a File and "to" is a String.> But I don't think I have personally ever actually run into a bug in a dynamically typed language that would have been avoided by a static type system.
I actually get to perform this experiment all the time. I work on Dart. Dart has fully dynamically-typed runtime semantics, but also an optional static type checker that the Dart Editor uses to give you static warnings.
Up until recently, I've mostly write my code in a plain text editor. I do write type annotations, but I get no static checking whatsoever. They're basically comments.
Now that I'm using the Editor more, I can open up codebases I've written that were blind to static type checking and see what kinds of warnings it finds. I get some false positives (i.e. the bug is in the type annotation, not the code), but I also find a disheartening number of legit bugs, and this is in code with good test coverage.
I like dynamically-typed languages, but it turns out the static typing people aren't crazy: it really does find bugs.
Then you're doing it wrong. Write types that encapsulate all the information you need. Don't allow construction of invalid instances. It's not rocket science.
Great, so now the documentation for the function will promise to return a motorcycle, but instead return either a bunny or a toaster.
There are lies, damn lies, and boilerplate code comments.
Not if you follow the second part of my above advice.
>There are lies, damn lies, and boilerplate code comments.
Since when is a comment that explains what a function does "boilerplate"? I think you are confused.
I also don't like the idea of having to comment each and every single function. If you have to write a comment to explain what it does, maybe you haven't named it properly?
Is it? And even if it is, why? Because dynamically typed languages are in vogue? Java does fine as a server-side webapp language, as does Dart (on the client too!), as does Go, etc.
This is the problem, and as you implicate, the exact sort of thing we need to stop doing.
Hint: the best developers aren't the ones who can recite the API off hand.
Anyone who thinks they are going to do nothing but hire above-average programmers at any scale is downright naive. Design your system around an "average" employee, and you'll be far happier.
It's easier to grow them.
> This is the problem, and as you implicate,
> the exact sort of thing we need to stop doing.
You do see the absurdity here, right? Banking on substantially above-average developers doesn't work at scale, by definition.See, this is how I knew you knew nothing about JavaScript.
My bets, you're a manager that manages shitty Java coders who "used to code" and is an obnoxious know-it-all.
Scale of 1-10, how close am I?
Edit:
From your website: "currentlly: BofA" (sic).
Feeling pretty warm on my bet so far.
This is why I don't ask for a "jQuery" guy, I ask for a frontend engineer who's a solid programmer and likes working on interesting products.
What's your point about JavaScript?
I'm not happy that somebody who very evidently doesn't have a clue what they're talking about is the top comment.
When people stop upvoting complete and utter tripe (which is nutritious btw), my response stops being necessary.
I'd react the same way to any sort of ignorant pontification on clearly foreign (to them) material.
Raise a fool on a litter and I'll tackle the people carrying the litter.
I'm quite open to being proven wrong, but I don't expect to be.
Just to be clear: I don't like this situation at all.
Replacing swing UI's seems like a reasonable thing to tackle using HTML/CSS/JavaScript. You could just pass data back and forth over HTTP if you are talking remote client/server or bundle a local webserver if running host only.
In the case of a platform like Windows 8, you can write actual apps using JavaScript (no server) but you can also write libraries in native code and access them directly from the JS.
I think this is just a classic case of "use the right tool for the job".
"JavaScript is not suitable for large web apps.
I am serious: Don’t write large web apps in JavaScript."
I don't know how the first flows from the second. Certainly I wouldn't write a large web app in Javascript! I might write Javascript in a large web app though.
So I agree and think the original article overreached.
I would contest, GWT is used by some people who sort of already grokked some of the points made by this article, some years back. For example, coding in JS giving a feel of coding in assembly, particularly without the help of any good editors.
Another example to break the Enterprise only narrative: 'Google Flights' is done in GWT. And you and me can guess, there won't be 200 avg developers coding that product.
I came from an Enterprise background before our Internet Startup. Few of us coded up our app, in 3 months flat out using mainly Java and GWT.
One of the reasons we chose GWT was that, when we started out IE 6 still had a considerable share, and GWT generated JS which ran on it very well (although slowly).
He uses an example of someone committing a classic mistake in software design. This error would be the same in JavaScript or Java. I'd like to see how his ActionScript translation magically fixed it.
However, the remedies for the mistake differ in each language.
It is somewhat difficult to fix it in Java's statically typed straightjacket (which I assume is similar in ActionScript). The easiest answer might involve a Feedable interface. I looked this up and it's not clear if ActionScript classes can implement multiple interfaces. So if you want your Toaster to be both Feedable and Heatable, get ready for interfaces extending each other.
In my experience most Java developers don't even do that. They don't think about revising their approach to the problem. They going to write a method that does what they want in the class that they want, come hell or high water. They'll create the BunnyOrToaster class which has methods which all contain if/else clauses testing if this in 'bunny mode' or 'toaster mode'.
In a language like JavaScript, you have other, simpler options, and often more powerful ones. I don't know for sure, but the mere fact that there are fewer tricks to learn might mean that it's better for naive to intermediate programmers. The typical JS way would be to rely on duck typing. If that disturbs you, you could implement a 'getFeeder' method on both kinds of objects that returns a closure, which can be executed later. That's what Java might call a 'Strategy pattern', but it's baked right into the language in JS.
Interfaces are a different concept. In functional programming, an implementation of an interface would extend the domain of polymorphic functions that use that interface. The same can be said about Java, if you tilt your head funny and don't need to communicate with other Java programmers, and if you only care about single argument dispatch.
It's awesome how, on Hacker News, people whose job require them primarily write code in Java are some sort of stupid luddites ready to be easily generalized as the worst kind of programmer. Way to stay objective, guys.
It's obvious that (in the OP's case) using JavaScript didn't help the problem either -- but that was my point. Bad design is bad design. I am not making a strong claim that JS is better.
So the comment is less about the developer than it is about the mindset and the 'easiest path' that emerges from the language design.
A more real-life example is that it's very easy to accidentally return a number when you meant to return a string.
But yes, AS does support multiple interfaces.
I have to say after writing "large" web apps in PHP and also in 100% JS, I much prefer JS for front-facing stuff. I've not found organization to be a big issue...but maybe this is due to the fact that I use a JS framework for most of my larger apps (but then again, I did in PHP as well).
Like C "feels" like a language for low-level programming and PHP "feels" like it should be running on a webserver, javascript "feels" like it's right at home in the browser. And now that browsers are powerful enough to be the entire front-end, I've come to completely embrace JS for this task.
Javascript is not a bad language. It's a very powerful language. Just like any other language, if it's poorly organized it's going to be a mess. I can tell you, from my experience, it is suitable for large web apps!!
Also, you can't ignore that this is hosted by Adobe...
The problem might not be you. Once you are done with your organized code and are moved to another project, some 'junior' dev gets a hold of your stuff and makes simple mistakes that static-typed languages could've avoided.
I'm not anti-JS btw, just throwing out one possibility.
This may be true, but it's an ad hominem attack.
http://en.wikipedia.org/wiki/Ad_hominem#Questions_about_the_...
His main example of why javascript isn't suitable is an anecdote about a badly developed code base written in javascript. Seriously?
Yknow, most every language ever.
If you had read the article, you'd see that the author made this comparison.
Sure, it's the "assembly language of the web," but Javascript certainly cannot be compared to assembly language in this way.
To illustrate his point let me show you my cross-compiled and optimized JavaScript code of SpriteExample, which is included in Adobe’s online documentation about the Sprite class. As you can see the JavaScript code is extremely dense and no longer readable.
This links to http://jsfiddle.net/bparadie/cbU2X/
This contains some minified JavaScript... Of course it looks dense & no longer readable. Run the ActionScript Sprite class through gzip compression and I'm sure it'd look funky too.
The author also advocates the use of CoffeeScript - which would have the vast (all?) of the same complaints he's raised against JavaScript.
All in all, a pretty terrible article.
> I don’t know why but JavaScript programmers tend to put all of their code into few files. That’s not so useful, though, if you want to have multiple developers work on the same project. Splitting up the code into multiple files enabled us to scale the project.
Let me rephrase that:
"I don’t know why but incompetent programmers tend to put all of their code into few files."
Last time I checked JavaScript does not have a file count limit.
The author should learn to talk in first person. I'm pretty sure I could write a horrible ActionScript app, if I wanted to, but that would not make ActionScript horrible in general.
- if function A and B are always used together, than they are one file.
- if linecount gets to big, split A and B into separate files
- if function C is shared between modules than it belongs in it's own file
So far it worked out great.
While you can use a module loader library you still have to choose one, learn it and its quirks and adapt other external libraries to use it (some of which might be written for another module loader or - horror of horrors - use their own half-arsed module system).
As for "file-stew" mentioned by the sibling comment, small units are good if you like code reuse. For example, I get sick of writing very basic classes like 'Rect' and 'Vector' (for graphics) over and over again.
The Flash codebase had become unmanageable. We found that the majority of Flash developers were used to coding up some advertising banner or something of that ilk and that individuals with experience making large applications didn't know Flash. Our team was mainly Ruby and web front-end guys and we had no clue what the Flash guys were up to.
After the change, our web designers could work directly with the markup and CSS in order to make changes, something that was a nightmare before we switched over.
Was it just Flash? No, it wasn't, it was a number of issues, mainly poor architectural decisions and a lack of vision from the technical leads.
All of these issues disappeared mainly because a CTO was brought on who really knew his stuff.
In summary, it's not the tech, it's the people putting the pieces together, and most importantly, knowing how to organize the people who are putting the pieces together.
I, too, once believed the mantras that "multiple languages present a maintenance nightmare" and "it's better to keep a common language for the sake of acquiring new hires" and on and on... But after some years, I disagree with that rationale.
In my experience, it's been more productive to have some sort of service-oriented architecture, built around your preferred protocol and data format. Then you can choose the languages that best suit your project needs (a decision most often based on the best available libraries). Popular languages are very similar, and it's easy to cruise between them...
I recognize the need to strike some balance in an organization. You don't want 50 services each in some emerging/obscure language, but I think that most folks (at least those who frequent this site) are savvy enough to know when you've hit that threshold. In our organization, we have developers who are globally distributed, and we write services in a variety of languages. We tend to standardize on the JVM: Java, Clojure, Groovy, but we've got some C# services, a lot of XSL, PowerBuilder (yuck), and even VB. I typically have discretion to use the language of my choice.
ASIDE: I always emphasize the "script" in JavaScript and rarely use it in any type of OOP style (except for the occasional lightweight library); the examples in the OP link made me cringe.
ActionScript, Dart, Java, PHP, node.js, Ruby, Go... ;)
That said, the bulk of Google's web applications, for instance, are not written in GWT or Dart, but rather in JavaScript using Closure Library, and compiled using the Closure compiler. So I don't think the answer here is to not use JavaScript (although I can understand why people at Adobe would argue for that), but rather to use tools like Closure or Angular that make the process more straightforward.
This resource has been invaluable: http://js2coffee.org/
1. JavaScript isn't a very readable language. (I think this is untrue. I've seen some incredibly well written / structured JS) 2. Not everyone knows CoffeeScript, so when you put a project up on GitHub and it's written in CoffeeScript, it's difficult for people who only know the syntax of native JS to understand what's going on. (To counter this - a lot of projects that are written in CoffeeScript are bundled with the compiled JS code as well - which also happens to be very readable IMHO).
Try using `coffee --watch` instead.
However, this article isnt advocating CoffeeScript (well it is, but it doesnt actually make a case for it), its advocating using a statically typed language. CS gives you classes, but thats not a big deal (module pattern makes it trivial to implement classes in JS).
To scale your web app, the author is advocating writing your apps in Java, C# and actionscript.
Now that I think of it, this is a really poorly laid out argument. It spends most of the time arguing for static typing, then throws in CoffeeScript as a sop to the people who will flame him for advocating Java/C#/AS.
His arguments have to do with the semantics of JavaScript, which are identical to the semantics of CoffeeScript.
If you stop relying on instanceof and start using duck typing it would probably work out better.
Or maybe you should just never write a function called doThisOrDoThat. Seems like a code smell.
Despite this, there is some truth to the assertion that JavaScript projects can be unwieldy. The main issue with large scale JavaScript development is the lack of a built in module system. The naive style of using a global namespace and script tags is prone to resulting in difficult to maintain code. Thankfully there are frameworks that can solve this issue.
It’s too bad that you inherited a poorly written Javascript project, but that doesn’t mean the language you’re most familiar with was the best language for the job. This is a common response. “I know X, let’s use X!!!”
Also, Javascript is a high level language.
But I don't think that follows. Assembly language (the article's metaphor) is something that most OS kernels will use from time to time and in moderation. Similarly I don't see anything wrong with Javascript for some pieces of a large web app.
Also, a little bit OT, I've been a professional programmer for 7 years now (i.e. getting paid to write code) and to this day I'm not sure 100% what's the difference between "0", "NULL", "None" or an empty string. What type does "None" belong to? Can I compare it to the integer 0?
been doing PHP by any chance? ;)
Here is that study: "An Experiment About Static and Dynamic Type Systems", by Stefan Hanenberg, University of Duisberg-Essen, 2010.
http://www.cs.washington.edu/education/courses/cse590n/10au/...
However, they didn't use existing languages; they created a brand new language and IDE that had a typed and untyped variant. Whether this confounds or strengthens the case is unclear to me.
In any case, I think any survey of static type systems that doesn't include a language with type inference is very flawed. Java's type system is an annoyance in the small, and is a mixed bag in the large. Haskell's type system is a totally different story.
What experiments could be done to test these beliefs?
Concerning the first aspect, the most important advantage I see in static typing is not that is finds bugs (tests are better in that discipline), but that it leads to much better IDE support. Only in a statically typed language, the IDE can definitely find out which class, method or field your code actually refers to, which allows for code navigation, documentation lookup, and last but not least intelligent refactoring support.
Concerning ActionScript versus JavaScript, I must say that I like and respect JavaScript a lot and want to keep its "good parts" (a la Crockford), but I also want to be able to take advantage of static typing for the reasons given above. Thus, although the company I work for is not affiliated with Adobe in any way (rather on the contrary), we were looking for the statically typed language that is closest to JavaScript and finally chose ActionScript 3. We then built a cross-compiler from ActionScript to JavaScript years before Adobe/Bernd Paradies did. We have improved and been working with this tool since 2004 (starting with JavaScript 2/ECMAScript 4) and never regretted following this approach. In contrast to Adobe's tool, "Jangaroo" is Open Source and ready to use now. It focuses on integrating with, not replacing JavaScript, and we help solve problems like dependency management for JavaScript and reuse such solutions for generated JavaScript code. Jangaroo's generated JavaScript code does not look like assembly language, but as much as the AS3 source code as possible.
It's not always black or white, I believe we can use the best of both worlds!
Instead just use a base library to give you a cross-browser wrapper and few more utils, then develop the whole application core layer on top it to separate it from your sandbox. Write all processing in core JavaScript unless you are trying to access DOM where the library (usually jQuery) wrappers would come into picture. This would give you immense power to control what you develop; will be highly scalable and of course, not to forget, performance.
Don't even complain if you have server side frameworks which will generate JavaScript for you; that will never work and is only good till your project is in Mock-up (prototype) stage.
The problem seems, you don't have good UI guys.
JS is a great and flexible language that runs on more devices than practically any other language. But it is hard to write large web apps in it.
At a certain distance you can swap the approaches anyway (but for syntax):
static as dynamic: Use Thing = HashMap<String, Thing> instead of objects. dynamic as static: Put assert(type(x)=="int") everywhere.
As to building large apps. If you need to build a large app (ie you cant divide it into isolated subsystems) then your goose is already well and truly cooked :)
that is why things like Ember.js are springing to life - to give the structure necessary to build large web apps without them devolving into spaghetti.
Klout.com -- same as above
More examples if you are interested:
https://github.com/joyent/node/wiki/Projects,-Applications,-...
Good JS programmers don't. Classes and inheritance work fine in JS.
>Just to be clear: You can write bunny-and-toaster code in ActionScript, too.
Right. This rant isn't about a bad language, it's about bad development practices.
pyjs works great now, and makes one highly productive. it just needs a bigger community of users (and developers?). so anyone asking the types of questions raised here should try it. then you can bash it on hn, right? :)
This reminds me of a blog post by @izs
http://blog.izs.me/post/10213512387/javascript-is-not-web-as...
Yes, I love Haskell and I do some CoffeeScript but JS is a fairly decent language to me : )
http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012/Dar...
I really don't get this at all. More files == more scalable? Someone more knowledgeable about ... whatever topic is relevant here care to explain this to me?
Generally, I'll write a little build script in Node that concatenates and minifies all my JS and CSS before actually deploying to production to keep the number of HTTP requests down.
He's basically saying that if you have 10 files and 2 developers the chances of collision (or merging issues) is small, but having 20 developers working from 10 files makes things more sticky.
To some degree, he's not incorrect, in that over time, you'll spend more time managing the merging and conflict process than you will writing code.
Obviously, there are modern tools that will help alleviate this problem, but the deeper you go, the worse it is. This was the reason that "old" VCS had exclusive locks.
Managing essential merge issues relates to success at dividing work up into highly cohesive, loosely coupled units. The accidental merge issues are not a big deal in good environments.
Shitty programmers should not work on large javascript projects.
by the same token, you can always get the work done with compiling-js approach, but don't expect it to be the winning product.
It should have the HN equivalent of reddit's NSFW tag..
The title is true BUT for another reason.
It is not suitable because there are so many great languages and language experts - but relatively few who are JS experts.
Why does javascript have a monopoly on browsers? Why can't there be some kind of WBVM (web browser virtual machine) that X language can be compiled down to? Why does JS have to be the assembly language of the web? This fact only makes things difficult and messy to have most languages cross compile to. I think that the W3C are a bunch of idiots for not pushing for something like this. They are stifling innovation more than Microsoft (or anyone else I can remember) ever has IMO. There SHOULD be an open standard for this.
Only very high level JS experts could pull off a large web application in JS. This accounts for maybe 5% of US businesses. Throw in High level experts for X language and now you probably have 60%+ of businesses who could accomplish such a thing. The Same goes for the browser UI as well (HTML and CSS pffff) How about the VM having the ability to draw all these elements instead of merely pushing HTML/CSS in our faces as an only option). We could use superior technologies like Flex, XAML, ETC. instead of HTML/CSS.
You love Javascript? great, but don't push it in my face. I have 3 favorite languages and JS is not anywhere near them.
The web browser is a platform (though it lives inside another platform) but one which is among most proprietary ever.
Why aren't more people pissed off about this?
I thought it would be clear by now that we do not need Java Enterprise in our web browsers. The web seems to be moving the other way - we have lightweight libs such as jQuery, underscore, backbone etc... and they seem to provide JS with the necessary building blocks for larger, maintainable systems.
I would consider the AWS management console to be significant.
Wait, you don't work for Amazon, so I'm confused...
If you want to dismiss GWT because it's java that's ok, but there are alot of good reasons (some non-technical) to choose java instead of CS or whatever. In fact, if you look at the history of GWT, they had all these "enterprise" patterns such as EventBus or Composite Views, or any other thing that the backbone/spine/etc camps are re-writing right now.
But I think people try GWT once, realize that the built-in widgets and panels look terrible and never look back. But some of the features that they don't get to trying are the features that really makes GWT worth using (the EventBus, RequestFactory, UiBinder, the excellent localization support, etc.).
GWT also doesn't preclude using any other JavaScript libraries. JSNI (writing native JavaScript within GWT Java source) is relatively easy -- I don't think it is uncommon to pull in JQuery in a GWT app for its effects, for example.
However, the whole "just write a desktop app and we will turn it into a web app" philosophy doesn't seem very web-oriented to me. Yes, it works, it's easy, but if one day you want to change your client-side code (i.e. use a different framework or something) you'll most likely have to change the server side as well. It just seems to be too RPC-centered and too monolithic. But maybe I'm wrong.
Anyway, you can check what the jBoss guys are doing with GWT, looks good even for Java: http://www.jboss.org/errai I think that if Java ever gets proper closures it will may be more of an acceptable solution for some cases.