Hacker News new | past | comments | ask | show | jobs | submit login
Anders Hejlsberg: You Can't Maintain Large Programs in JavaScript. (dzone.com)
96 points by tszming on June 4, 2012 | hide | past | favorite | 166 comments



And, once again, this is why WE NEED A BROWSER BYTECODE STANDARD. Let us all go to hell in our own way.

There is no reason to lock the browser in a cage half-designed and half-implemented by an engineer under a tight deadline over a decade ago.


Or at least a JavaScript AST standard, like this one proposed in 2010:

http://research.microsoft.com/apps/mobile/publication.aspx?i...


There are problems with this idea in that- every js engine will have a different AST structure for optimisation reasons, and making the AST a standard rather constrains optimisation efforts- or forces implementors to include two seperate parsers.


A bytecode standard is a decent idea, but I worry that it would be "good enough" for nearly everyone. What I think we really want is something more akin to what we have for native development: choice.

We should have things like JVMs for the browser (cached on the client-side, no doubt), but we should also have non-portable code for people who want to do things that cannot be done portably. A bytecode standard cannot be all things to all people, because some people need to do things that can't be done on some platforms.

If you really want everything to move to the web you need to expose vector math instructions for video encoding, you need to expose CUDA for scientific applications and so on. You need to be able to ship machine-code to the client where it can run (properly sandboxed, no doubt).

Of course, if you want everything to move to the web there are bigger problems to overcome - HTML and CSS aren't really suited to application development, the filesystem APIs are not sufficient, and there's still the problem of getting GUI applications to compose well...


There are a thousand really good reasons why this is a terrible idea. Just do a search of the ecmascript mailing list for bytecode . https://encrypted.google.com/search?hl=en&q=site%3Ahttps...


No, there aren't. There is an entrenched bureaucracy and a load of fanboys who can't see past what is to what could easily be, all attempting to justify the current sorry state of affairs or ignorant of what's what.

Look, if javascript, with all it's insanity, can be standardized across browsers, for the love of pete, a simple stack-based VM can be too. And then everyone can go to hell in their own way.

Admittedly, people will stop using Javascript the second there is a viable alternative. I regard that as a feature.


Ignore reality if you want to. It's just never going to happen. Java had its chance. Java had every possible chance. Java had the advantage of making a deal with Netscape to purposefully cripple javascript to help promote Java. Sun tried for a decade, trying and trying to make Java the defacto web application language. Sun tried and tried to put its java VM in the browsers. And it lost. Java lost. Javascript won. End game. Being in denial about it won't change it. Trying it again isn't going to change the undeniable reasons that Java did in fact lose. Insisting that a VM is the best way to make web apps won't change the reality that we explored for years and years that it just simply isn't. It didn't work. It can't work.

Get over it already.


here is what is more likely to happen.

Brendan Eich:

"If I wanted a safe intermediate form, I would look at arithmetic coding techniques that self-verify (so that you can't express other than well-formed programs), not bytecode and not JS source. It's IMHO very unlikely that TC39 will standardize a bytecode for JS. An AST encoding has better chances and better properties including self- verification and view-source-ry."


look, Javascript creator Brendan Eich giving a whole talk on why this won't happen. http://www.slideshare.net/BrendanEich/splash-9915475


Brendan Eich talking about why javascript will never be replaced? That's like Bill Gates giving a talk on why Windows will never be replaced.


We need a standard wire format for code to be run on browsers. Fortunately we have one: it's called JavaScript. If you look at the internals of that format, it happens to be designed to be written directly by humans, but if you find that design suboptimal (and it would be surprising if it wasn't, considering it was put together on a ten day deadline with contradictory requirements) you can ignore it and just treat it as object code to which your favorite language can be compiled.

Doesn't Google make some internal use of a tool chain that compiles Java to JavaScript? And then of course there's Dart and CoffeeScript. I'm sure there'll be more.


You can compile anything into anything, but for the vast majority of languages, the easiest thing to target with sane semantics is a virtual machine, not a crazy half-baked language (that I end up coding in for about 40% of my day.) A bytecode standard would free us from the crazy design decisions of javascript, give us source-level debugging, etc. And it wouldn't be that hard, given all the fine examples of VMs sitting around.

My sense is that the people that suggest javascript as a compilation target really don't want competition for javascript in the browser.


> A bytecode standard would free us from the crazy design decisions of javascript

Not really, because most of the complication and mess is in the document object model, not the language syntax. How do you propose to solve that problem?

> My sense is that the people that suggest javascript as a compilation target really don't want competition for javascript in the browser.

You sense incorrectly. I'm not working in that area, I don't have a dog in that fight. I just think it's a good idea to point out problems with a proposed solution before somebody goes off and puts a lot of work into trying to implement it.


Using JavaScript as object code is particularly efficient though.


I'm 99% you're missing "not". 0.9% it could be an "in".


You would be quite wrong about that.


The problem with JavaScript is, somewhat paradoxically, too much flexibility. There are no standard language features for very basic things like namespaces and modules, also what it provides for OOP is so confusing that it makes people want to roll their own OO system from scratch. Objects as dictionaries and first-class functions make it possible to implement those features in hundreds of ways and almost every JavaScript program tends at least in some places to use some own, original solution for one of the very basic problems of structuring programs, because it is so easy to built one. It is good that this is possible, it is bad that people _have to_ do this (or choose one of the countless existing solutions) before they can actually write the program they want to write.

A lot of the problems would go away if the following was part of the language and present in every browser:

* namespaces/modules

* a sensible OO system people would actually enjoy using

* the ability to require/import/include a file/module

* the functionality Underscore.js provides

Then, at least the basic structure of the code would be consistent across programs from various people, and I wouldn't have to work out the details of yet another OO system, yet another way of just laying out the code across functions/objects each time I want to read another JavaScript program or yet another way of doing function () {}.bind that works across the browsers (here the problem is also the long time it takes for the majority of people to install a browser new enough to adopt the revised standards). And it's not only about reading code, how do you write an object-oriented refactoring tool if every program realizes OO in its own distinct way?

The situation is probably slightly better with server side JS where you are free to adapt the newest version of the language/runtime and also the server-side frameworks at least to some extend tend to encourage to use a common structure for all the modules.


Your 4 points are exactly why I always use Require.js, Backbone, and Underscore in all my large projects.

Require.js solves point #1 and point #3. Backbone solves point #2. Underscore solves, well, point #4.

In my experience, the other important thing to maintain coherence and sanity while creating large JS apps is to have a system that makes dependencies between modules very, very clear. Require.js basically also does that for me; it requires every module to define their dependency on other modules on top of its file.

I highly recommend people creating large JS apps to at least check it out : http://requirejs.org/


What's your largest project that uses these?


Let me explain to you the two large projects that I'm currently working on that are both using Require.js (it's hard to explain one without the other):

The first is basically a web framework that lets you compose a fully working website from a whole slew of independent, pre-built, unique components. Each component is made of Require.js modules (like its own HTML, CSS, JS). This isn't exactly the largest project, but Require.js really comes in handy with its ability to conditionally load modules (or components, in this context.) because you simply won't use all the components in the system, and also its ability to treat pure text file as regular modules (for HTML and CSS part of the components).

The second is a visual drag-and-drop web builder that lets you visually build a working end product of the first project that I mentioned. This is a large project simply because there's usually quite a lot of that you have to do in order to make a completely visual system work. I simply can't imagine building this system without explicit module dependency that require.js enables.


But how large are these? E.g. in LOC?


I think a better starting point is defining how large does something need to be to be significant. Otherwise we are nothing better than the guy in the back of the room shouting "Does it scale?", which given the amount of context in the question renders it impossible to answer.


Because you're not being productive unless you're adding at least 2000 lines of code to your code base every day.


well we have ES6 to look forward to https://wiki.mozilla.org/ES6_plans yep, we'll only have to wait about 5 or 10 years.


CoffeeScript seems to be what you want for.


CoffeeScript does the functional stuff and class system, but it doesn't do the module-loading. Is there even a module system for JavaScript?


Javascript has no native module system that I am aware of. But there are formats+libraries such as AMD (used by Require.js) or CommonJS.


The ability to enforce and optimize modular Javascript is one of the primary benefits of Google Closure Compiler, I've seen. I've only used it for one project so far but I can't envision writing another Javascript project without it.


I believe an underrated factor is the quality of tools (IDEs) available for the language. E.g. imagine refactoring a 50mb source code C# or Java application without the help of tools like Visual Studio/Resharper or Eclipse? I remember trying to write a java app in java 1.0 with just a text editor and the command line compiler - it was painful as hell, but things have progressed massively since then..


There is also several mentions in the excellent video of how types help refactoring etc.


IDE won't help you beyond a certain code size. Good explanation here http://steve-yegge.blogspot.fi/2007/12/codes-worst-enemy.htm...


Being an OOP language, the interaction between modules is very explicit. This helps weed out bugs, since "what you wrote" may look close to "what you meant", but is ultimatly violating some rule of the system. This is one of the reasons why I find OOP languages good for large, complex systems, but not for small, hacky programs, since I can't hack around things to implement "just what I want". Javascript defintely fits into the latter category, and requires some good engeering for large projects.


I know what you mean and I agree that when used correctly OOP can achieve great modularity, but an OOP-capable language by itself can't protect you from spaghetti code just as horrible as any other non-OOP language could produce.


> Being an OOP language, the interaction between modules is very explicit.

This is true in any language that supports modules, not only OOP languages.


I wonder if we all agree what "large programs" are. Our team, for example, we are developing a "large program" in Java (Spring, JSF). It's 13'200+ .java files and total 54mb of source code + about 90mb of third party .jar (open source) library dependencies.

I don't think you could grow to that size codebase with Javascript.


Not that I disagree, but in my experience a lot of the code in a Java application is just a workaround for the poor expressiveness of the language. A lot of the stuff one has to do in Java to get halfway decent encapsulation/abstraction is just not necessary if you use a more expressive language and write code in a more functional way. Not that JavaScript makes that particularly easy or that it's even a nice language, but it is more expressive than Java. With first class functions and closures alone a lot of the Java boilerplate just vanishes. Not that I want to defend JavaScript, I personally think it's a horrible language, especially for large programs. But I think Java seriously suffers from lack of expressiveness which results in an explosion of classes to implement convoluted design patterns and such. I hope it gets better with Java 8.


I always found this argument lacking. In any language you can build the necessary abstractions for higher expressiveness. Sometimes these reach things like auto-generating code from a DSL, but in the long run if a good team is working on a large project, I can believe the amount of code can be 2-5x vs a more expressive language, but not 100x.


I agree with the 2-5x comment, but I don't think this is the right way to look at it.

Taking it to an extreme to demonstrate the point - a good team working on a large project could also just implement a new, more expressive programming language than Java and use that to implement their application.

The whole point of language selection is to begin with a more capable toolset.


Yes, if you include autogenerating code from a DSL, of course this is true. See Greenspun's tenth rule. But if you have to implement a custom DSL to achieve your goal obviously the language isn't expressive enough to do it. But I agree that the factor is probably not as high as 100x.


I don't HATE Javascript. It is a rather limited language. Especially if you're used to the standard Java/C#/C++ way of doing OO programming. Then again, sometimes I just want to instantiate a new object without having to say:

Dog dog = new Dog();

I'm lazy and I find that sometimes expressing myself in JS is just what the doctor ordered. But with the lack of a type system, I can get pretty frustrated.


As a couple others have said, you likely wouldn't need a codebase that size in JavaScript, even for an equivalent functionality, because of the type of programming the language allows.

A bit OT, but it might prove the point. I'm a Groovy enthusiast, and have done this exercise a few times. I'll give a presentation of Grails - basics of Grails, basics of Groovy, then demonstrate a Grails app. I'll walk through all the functionality of the app, then ask the Java developers in the audience for a guess as to how many lines of code they expect the app takes.

I clarify I'm asking for lines of code that I had to write, not necessarily in supporting libraries and such. I still get estimates from the Java devs of 25-30k LOC most of the time. Sometimes someone will be brave enough to estimate 15k. The real answer is closer to 6k.


I agree that JS code will generally be shorter than Java code because 1) you don't explicitly describe your types, and 2) JS is more expressive and there are things that you can just do more neatly.

However, there are many classes of code and #2 applies more to some than others. If you are writing something algorithmic like Peter Norvig's famous spell checker[1], the primitives of your language make a big difference. On the other hand, if you are writing something that is larger but of lower complexity where your code is more like configuration of a bunch of pages, this makes less of a difference.

Also, it's at least possible that the people who see your code assume a higher standard of maturity than your 6kloc has. We've all tried creating an apparently complete app rapidly, only to work on it for ages afterwards, implementing fault tolerance, graceful degradation etc. etc.

[1] http://norvig.com/spell-correct.html


anyone has evidence of similar projects done in java and javascript showing how js is much more expressive?

Sure, the lines end up less wide, but while you gain something by using function() over inner classes, you also end up reinventing package declarations and visibility all the time, so I don't see a clear advantage of one over the other.

(notice: I do understand people will generally do things in Java that they won't in JS, such as adding setters and getters, but I have seen that done in plenty of "big" js libraries, so I doubt that counts.)


This may just mean that Java developers are poor at estimating LOC, or that you are a much better Groovy developer than they are Java developers.

Have you asked Grails/Groovy developers the same question? Have you written equivalent Java code to compare outright?


Good questions, and no. Anecdotally, talking to other Grails developers - ones who have switched from Java - they all acknowledge that they write fewer - often far fewer - lines of code.

I agree on the point that people may just be bad estimators, but I was assuming at least some of them have done approximate LOC counts on their own code from time to time to get estimates. I do.


"This may just mean that Java developers are poor at estimating LOC"

Surely he must have a FactoryOfFactoriesFactory class in there to make factories of his factory factories. That's at least 1k LOC right there!


Agreed. And given that he's just taught the basics of Groovy to the audience, the likelihood of them being able to accurately project how many LOCs it will save them seems pretty low.


That's part of the point, in a way. Not to prove to people how much they don't know in a negative way (but maybe it comes across that way), but to provide a hopefully fairly shocking number to get them to rethink some of their basic assumptions about development. Using even a moderately different toolset can yield dramatically different (and I'd argue usually better) results.


Is there any rigorous study more recent than Lutz Prechelt's "An Empirical Comparison of Programming Languages"? That estimates a factor of two difference in lines of code between Java/C/C++ and Python/Perl/Tcl, albeit for a rather small project.

So I've been using "factor of two" as a rough benchmark. Of course, this assumes appropriate library support; if most of the C code implements a priority queue while C++ has that as part of the standard library, then the comparison is invalid.

I don't know if for this Grails comparison if the extra factor of two comes from Groovy or from the effectiveness of Grails over whatever the Java programmers would use for web app development.


Yeah, I don't want to weigh in the JavaScript side of things but I've worked with a ton of "large" Java applications. All of them have been large because...

> Everything must be an interface/impl/dao/controller so you get 4 files + hibernate mapping (if not using annotation) + view files. Eventually you have 10 files for every object.

> Mid-stream decisions (we need to go from Struts to Spring) that effectively create two separate in-process branches of the code base.

> Java developers building their own castle. Some guys "owning" a side of the application and not communicating therefore creating solutions their own way instead of using common libraries.

Specifically to your description I would argue whatever you are doing must be in multiple projects or it has been poorly engineered. If it is in multiple projects why couldn't another language take it on?


> I don't think you could grow to that size codebase with Javascript.

I disagree. Any substantial JavaScript application can reach this size and more. It all depends on the level of abstraction you choose and the functionality frameworks and libraries provide out of the box.

I have written numerous mobile applications in JavaScript and they quickly sprouted to 10-30kloc. The majority of this being API functions to speak with our robust REST API, custom controls extending those provided by the Ext framework, and controller logic.


IIUC, its not 13000 lines, its 13000 files...


You wouldn't need that size of a codebase with JavaScript...

Java was created (or adapted to) for the benefit of consultants. Therefore it requires complicated frameworks and you can not manage coding Java without an IDE. All this makes it easy for consultants to get long paying gigs.

Edit: thanks, downvoters! You are incredibly naive...


Therefore it requires complicated frameworks and you can not manage coding Java without an IDE.

Nonsense. I write a lot of java in emacs and use no frameworks at all. It's a simple systems programming language with an excellent standard library and great concurrency support.

While many people do abuse Java by plugging AbstractFactoryFactory objects into their framework for procedural programming, that's an issue of bad programmers rather than the language itself (which Java has lots of).


Then I guess you use your own frameworks and have a very special use case that shields you from the typical pains.

Maybe it is possible to use Java in a sane way. But there are for example best practice guidelines by Sun/Oracle. If you try to follow all that stuff, it will be painful.

Also most libraries for Java were written other Java developers. For example the other day I tried to send a simple Twitter update with Twitter4J (I think that was the name, might mistake it with another one). After an eternity trying to figure out how to configure OAuth with the AbstractAuthenticationProviderAuthenticatorCredentialsMessUpperInterfaceImpl (which requires clicking through several levels of the API dopcs to get the hang of), I eventually gave up and just used a 10 lines Ruby script instead.


A twitter4j update, taken directly from their webpage:

    Twitter twitter = (new TwitterFactory()).getInstance();
    Status status = twitter.updateStatus("hello from Twitter4j");
You also need a 4 line twitter4j.properties file containing your assorted tokens and secrets. It's a bit longer than 10 lines, but still pretty straightforward, even with the use of a (probably unnecessary) TwitterFactory.

By the way, I said java is a simple systems programming language. It's not what I would reach for if I wanted to update twitter either.


Maybe they updated their homepage since then (it was a couple of months ago).

What do you mean by "systems programming"?


"Systems programming" is a poorly defined term, but it generally refers to building operating systems, databases, event buses, that sort of thing.

Redis <- systems programming

Aggregating your tweets in redis <- application programming


I had a similar problem - also dismissed Twitter4J etc. as too complicated and wrote a 50 line Java method to send a tweet (signature: tweet(tweet, consumerKey, consumerSecret, accessToken, accessTokenSecret) ).

So presumably it's the culture you don't like, rather than the language.


Google and a few other companies manage to do this with Closure Library and Closure Compiler. Compiler's static analysis detects a large set of errors that you might introduce after a broken refactoring, or just during normal development. Among the most useful are the missing properties check, and the type mismatch check.


I watched the video. Just to clarify, his argument is that it's hard to refactor large programs in javascript. In other words, it's likely that large web-applications written in javascript will be having difficulties to innovate. Only time will tell though...


Definitely agree with this. I've re factored large C# apps, moving thousands of lines of code into different places and have had it up and running again very quickly with no bugs.

Contrast this to refactoring huge javascript or python programs because the compiler isn't going to check if what you refactored 'fits' into the place you put it. It's always very nerve racking for me when refactoring large pieces of javascript or python because even if it runs, often many bugs remain lurking that won't be found out until the unit tests are re-written.


Umm.. in my personal experience using IntelliJ IDEA for Java and JavaScript code, the refactoring experience is the same.


How could it possibly be? Refactoring a dynamic language will always be more difficult because you never know exactly what an expression refers to.


In Java you have dependency injection, which is fancy name for calling constructors/methods with reflection, depending on some XML file or annotations.

Which makes Java more dynamic at the cost of making it as hard to refactor automatically, as any dynamical language.

The part of code that doesn't use reflection is the part of code, that would be easy to refactor, even if it was written in javascript.


This comment packs a lot of confusion into very few words. You're conflating a factory abstraction like Spring with dependency injection.

void foo(Reader r) { /do stuff with r/ } ... foo(new BufferedReader(new FileReader("/log.txt")));

There, I just did dependency injection without a trace of reflection. Additionally, since everything is statically typed in Java, refactoring is still vastly simpler than with a dynamically typed language. The few spots in the code where you might be trying an invalid type cast are just that - a few spots. Such problems don't permeate the entire codebase as they do with a dynamic language. And I'm saying this as a huge fan of Clojure and Groovy, preferring them over Java on the JVM.

[edit: changed "strongly" to "statically"]


Just try it. I have no complaints when it comes to refactoring any code (Java, Python, JavaScript) with IntelliJ IDEA.

Scala with IDEA was tricky. But then I'm pretty poor with Scala, so it must be me!


If you write the IDE in the language itself, you can use reflection to access, query and manipulate the program's structure directly, while the program is running.


This is theoretically true and I am excited about LightTable but even then, there are many situations where automated refactoring simply isn't possible.

    var decoration = { topmargin: 10, bottommargin: 10 };
    ...
    function setMargin(where, value) {
        decoration[where + "margin"] = value;
    }
    ....
    setMargin("top", 20);


This is a hazard in pretty much any language though. At some point you're going to want to do something dynamic at run time just to get a particular feature to be possible- whether it's by using a built in feature of a language, or by importing an aircraft carrier to do it for you in Java. It's simply Godel's curse- every sufficiently powerful formal system has an escape port. Otherwise known as Greenspun's 10th rule.


Possibly he just uses the most obvious refactorings in the most straightforward js.


> In other words, it's likely that large web-applications written in javascript will be having difficulties to innovate.

Do you mean "iterate"? Because refactoring has little link to innovation.


Because refactoring has little link to innovation.

What about rapid prototyping? Perhaps the biggest strength of the lighter, more dynamic languages is that they require much less work to play around with ideas in the early days. On the other hand, if you can’t then tidy up the code that sticks, to make it into something that is more systematic and maintainable over the long term, you’re either going to waste effort rewriting it or you’re going to take on ever-increasing levels of technical debt, and either way your progress will be slower.


> What about rapid prototyping?

Refactoring really, truly and absolutely has nothing to do with rapid prototyping, nor does rapid prototyping has any use for refactoring.

> you’re either going to waste effort rewriting it

Throwing one away isn't "wasted effort", it good practices: you created a turd the first time around and learned a lot, polishing that turd would be wasting time.


JavaScript lacks a real library/module system, namespaces and OOP facilities. I usually spend more time maintaining a JavaScript program than a program written in Java/C# with equivalent size. That being said, my skills in JavaScript are limited.


Umm .. On the server, node_modules / NPM driven modular system (AMD) works quite well. RequireJS can be used on the client as well.


I especially like the fact, that "importing" module in node returns imported module, instead of putting it into namespace like it does in Java. It's much better design.

   var myModule = require('./module');
instead of

   import com.company.module.Sth;


What's wrong with using dojo for a module system, namespaces and OOP?


You can do OOP in any langage and there is nothing wrong with dojo. But from my limited experience, maintaining large programs written in JavaScript is a tedious job (each program reinvent it's own OOP semantics)


I think it's very good that javascript discourages writing large programs. Large programs are not a desirable goal, and it's rather a disadvantage of java that it allows and encourages such awful behaviour.


Have you written mainly todo-apps or do you have by any chance experience writing payroll software or stock keeping applications for a retailer?


Okay so may I ask what is the point of this question? (edit; I guess asking for clarification is looked down upon here?)


As for my reply to your deleted reply:I thought you were tongue-in-cheek.

As for my reply above: "you should not have that problems" does not make them go away: some problems solved by software are inherently complicated and cannot be reduced to some simple API calls or a 5kloc code base. Composition of 100 multiple 5-kloc code bases still makes them a 500-kloc code base with all mutual dependencies.

Just saying "you should not write so much code" might display inexperience with problems which fall outside of the currently common javascript apps ...


It perhaps depends on how those 100 multiple code bases were written. I won't lie and say I have experience with inventory systems. But I will take the position of the young upstart dipshit and suggest perhaps the reason you end up writing such huge tangled messes is you just haven't thought of a better way to do it. Javascript might not be the best tool for such jobs though, the way the number type works- on its own, makes it impractical for accounting tasks.


I'm completely with you that messiness is best tackled by loose-coupling parts early on. It's only that I found the combinatorics of many small systems not so much easier to tackle than their monolithic counterpart.

The worst is even that you (or somebody else) begins with good intentions ... and then , 4 software generations and law changes later, the complexity starts to smell.

Heijlsberg argues, that javascript will be harder to refactor in those cases. I can't really disagree with him.

So it find it's not so much lacking thought. The current thought for some is "let's use javascript", let's see what comes of that... :-)


I couldn't watch the video. I am starting to think though, that the sweet spot is to not just simply use javascript for everything and hope for the best- or to use java or something else and enjoy the sweet refactoring IDE glory, but a synthesis of making well tested components in a static language that you orchestrate with a scripting language- (if I have a choice, I actually would probably choose lua). In my experience so far, a lot of tangle often comes about by a confusion of library code and application code- the two styles of programming are very different. A module is very structured and regular, while application code seems to be ad hoc, specific, and irregular. There's nothing stopping both from being written in the same language, but if you decide that libraries go in one language, and application code goes in another, there's smaller risk of the two accidentally forming interdependencies. Then you set the goal that the dynamic portion of the program is to never exceed 2000 lines of code- and you have the basis for --- an experiment at least. Since really that's kind of what we are all doing. It's pretty well known by now I think that nobody has discovered a One True Way of doing this software stuff.

We haven't really figured out how to write large complicated applications- Static analysis is no magic bullet, and neither are dynamic languages. I think what we are seeing is just a kind of physics of the mind- reactions and re-reactions to unpleasant experiences we've all had, and are trying to avoid, which leads us to polarise on the static/dynamic divide.


[deleted]


In the end everything is an API!


Steer clear of "enterprise scale" ExtJS 3.x projects - tens of thousands of lines of javascript code that just duplicates server logic and absolutely positions text boxes and buttons on the page.


I downloaded the Flow app JavaScript to see how they handle relations and composed views etc. I swear I could be commiting fixes and new modules to that codebase a few hours later. With OO, TDD and established conventions you can achieve reasonable maintainability.


Posts like this make me wonder why OCaml isn't much more popular.


Functional programming is difficult and the large majority of developers haven't even heard of it.


OCaml is multi-paradigm - the O is for object. Type inference is a huge productivity win.


I'm not super familiar with OCaml but I have written a fair amount of code in F# which is supposedly based on / very similar to OCaml. In the end I had to convert it all to C# because none of the others developer at my company could grok it. I agree with you that the type inference is really neat but writing F# (and probably OCaml too) consistently in an imperative style is a bit of a pain in the back; it feels like the langauge is simply not meant to be used like that. And, as I said, functional programming is difficult and most programmers never even heard of it. (I wish I could use FP at work but jobs like that are really rare here in London.)


If you are able to use C# 4.0 then you have most of the FP concepts already at your disposal.


> Type inference is a huge productivity win.

When writing code, sure. When reading and/or maintaining code, not so much. Especially when it stretches across function or method boundaries. Languages like C++ and C# have the right happy medium in my opinion: `auto`/`var` keywords for type-inferenced local variables, but explicit parameters and return types for all methods.


I think of type systems much more as a static analysis mechanism the compiler can use to identify programming mistakes rather than a concept that helps reading or maintaining code. In my opinion, in well written code the types of various symbols should be obvious due to the context, names, etc. without having to look at type names.


In theory, perhaps. But there is a lot more information in syntax than in names in my experience, such as the number of arguments to a function.

For example, suppose `f` is a function of type `int -> int -> int -> int`. In python, semantic differences are obvious between:

    a = f(x, y, z)
    b = functools.partial(f, x, y)
Where as in OCaml this difference is glossed over:

    let a = f x y z;;
    let b = f x y;;
Even though the names "f" and "x, y, z" are relatively evocative of their types, the two expressions are very different without any particular indication as to why.

That's why I think that there is a happy medium, where syntax is very helpful in determining types such that there is no need to give explicit types to "a" or "b" in these examples, but there is enough information explicitly available to declare that "f(x, y)" is an invalid function invocation, not a curried function of the type `int -> int`.


Different, not difficult. On the whole functional programming is no more difficult than imperative/OOP. It's just a big switch for programmers used to imperative programming (i.e., most programmers).


I believe that tail recursion is a more difficult idea than a for loop. Not much more difficult, but more difficult none the less.


At some point you have to also consider why most programmers are used to imperative programming.

It could be you're rationalizing from a first principle ("it must be equally easy, so if it has not caught on it's because programmers are not used to it").


> why most programmers are used to imperative programming.

Probably because that's the paradigm of the most popular languages, the first paradigm everybody learns in college and university and likely the first language a person will encounter? Because most programmers are despite what they would say about themselves in public, actually stubborn language bigots? I would think about that because it puts functional programming (or logic programming (or proof-based programming (or stack-based programming))) at a disadvantage and a fair conclusion cannot be derived from uneven exposure.

Consider the actual research done in this area, classes have demonstrated that whatever the language, there is always the same distribution. Those that excel (small group), those that succeed through hard work and do good (most of the group) and those that just don't get it and fail (small group). This has been shown to be true for C, Visual Basic, Pascal, ML, LOGO, Scheme (SICP!) and even Coq!, which is a proof-assistant. Probably Prolog, too, but I haven't looked at that. You can easily google this, just search for things like "lecture/semester findings" and "student reactions/performance" and insert your language of interest.


>Probably because that's the paradigm of the most popular languages, the first paradigm everybody learns in college and university and likely the first language a person will encounter?

That is just a rephrasing of "they are used to imperative programming". The question is why.

>Consider the actual research done in this area, classes have demonstrated that whatever the language, there is always the same distribution. Those that excel (small group), those that succeed through hard work and do good (most of the group) and those that just don't get it and fail (small group). This has been shown to be true for C, Visual Basic, Pascal, ML, LOGO, Scheme (SICP!) and even Coq!, which is a proof-assistant. Probably Prolog, too, but I haven't looked at that. You can easily google this, just search for things like "lecture/semester findings" and "student reactions/performance" and insert your language of interest.

How does that work in real life though -- when pragmatic issues get into play that are absent from "implement this algorithm in whatever language".


> That is just a rephrasing of "they are used to imperative programming". The question is why.

I answered it. They are used to it because it's the first paradigm there was and being the first thing gives you a good leg up.


It probably has its own problems as well. Like nostrademons said in another post about Haskell: http://news.ycombinator.com/item?id=2620002

I personally didn't use it because there is not enough people using...

Some OCaml: https://github.com/kig/preludeml/blob/master/src/prelude.ml


Oh surely that's because it has too much static typing to be practical, it's not like there is much thought put in the argument or any desire to pursue the argument to its logical conclusion in these things.


I kinda feel strange when people tell me Python is bad because it does not have static typing but when I tell them about OCaml or whatever else I'm fine with, they try to find another excuse why Java is good.


The video link for anyone else unable to access the site (it's down at the moment) http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012/Pan...


Language wars erupt again!

Should it be titled: "Anders Hejlsberg: I Can't Maintain Large Programs in JavaScript." ?


The same has been said of almost every language in existence.

Let me maintain my larger program in JavaScript. It will require smarter staff, but the application will be more flexible and change more quickly than that same large program written in Java or C#.


smarter staff == higher salaries, not welcome in big companies.


If where you're working has a big company mentality, someone in the decision making process screwed the pooch when they decided on JavaScript as an application programming language.


I already answered on a previous post that I only work in big projects where we stay away of languages like JavaScript for application development.

For us the proper place for JavaScript is the browser, just to do some DHTML stuff.


Shame the link only talks about the JS part. So much other great stuff in this video.


My favorite thing about JS now coming into wider use is how it drives a certain class of older hackers bonkers.

It has 0 and -0! The default namespace is global! It has a === operator, for crying out loud!

For folks who spent a bunch of time writing AbstractPatternVisitorHandlerFactory classes, it probably looks like the end of the world at the hands of a bunch of freakin' degenerates.


It's not that at all. I use JS almost daily and the unfortunate conclusion is that it's just poorly designed.

The data structures are lacking and have bizarre corner cases. I don't know if what it features as OO can be called OO and I don't care much, but the abstraction mechanisms are inferior to what I'm used to. Performance is unpredictable and sometimes I'm forced to write less readable code. Refactoring is a scary adventure, debugging is subpar, code navigation is cumbersome..

The things that I do like about it are availability and that it's cross-platform.


Re "poorly designed", in fairness, its original designer (Brendan Eich) had to put the whole language together by himself in ten days under a mandate from his overlords at Netscape corporate that he make it look kind of like Java while not looking too much like Java (see http://www.computer.org/csdl/mags/co/2012/02/mco2012020007.h..., http://www.jwz.org/blog/2010/10/every-day-i-learn-something-...).

Given those circumstances, the amazing thing is that JavaScript has held up as well as it has.


Or folks to just don't like hidden surprises when trying to do trivially simple things?


If you take an hour to sit down and understand the type coercion, all of these "hidden surprises" magically disappear.


1. Understanding JavaScript type coercion correctly, including (emphasizing!) all of the corner cases that actually matter, is not an hour's task.

2. The fact that pathological-condition-X of a language is in theory understandable with sufficient study is a total red herring in a broad discussion of that language.


Understanding all the corner cases of how C deals with integers is a huge undertaking, as the C Integer Quiz thread showed us. But in practice, it's not actually a problem since you just learn to avoid using features of the language that involve type coercion. Just simply don't mix types. only use === and !==, use a templating library instead of the + operator to construct strings. jslint can catch the rest. If you truly find the way javascript behaves surprising- in the sense that you are trying to do something reasonable, and it surprises you, I have to wonder what on earth you are trying to do that would invoke type coercion to begin with, and why you need to do it that way.


I think there is a bit of an issue with _the code you don't write_ , because you rely on third parties.

Today, I spent five minutes tracking down a

    SyntaxError: Unexpected token u
It was honestly hard to read this as "don't give an un-itialized value to this function or it will end up being passed to JSON.parse that will happily treat undefined as a string".

I'd take a NullPointerException with a proper stacktrace everyday.


in chrome, error objects have stack traces attached. All you would have needed to do is wrap the problem code in a try/catch, catch the error, and print out the stack trace, assuming you can't figure out how to find the stack trace just using chrome's web debugger. https://code.google.com/p/v8/wiki/JavaScriptStackTraceApi


You are missing my point, the issue is not that the error does not have a stacktrace, it's that it looks like:

    SyntaxError: Unexpected token u foo.js:123
    h foo.js:456
    g foo.js:789
    f
The issues are

* no reference to JSON.parse which is where the error occurred

* the error is not "object has no attribute toString", which would have made it clear what it's happening, but something else derived from having silently coerced "undefined" to string, which obscures what is happening.

As I wrote, it was a five minutes thing, not hours, but it's five minutes I would not have spent if it had been:

    TypeError: Cannot read property 'toString' of undefined: [native code]
    JSON.parse [native code]
    h foo.js:456
    g foo.js:789
    f


If parts of the language are so confusing that they should be avoided, arguably they should be removed completely.


They should, were it not for the backward compatibility requirement.


While I share your "just sit down and learn something instead of complaining" sentiment, in this case I think it's pretty difficult to memorize all the different ways that javascript does type coercion. Sure you get to know the most common pitfalls, but it just feels like even experienced JS programmers get bitten every now and then.

By now I'm sure everyone has seen the WAT talk (https://www.destroyallsoftware.com/talks/wat) which illustrates some of the more obscure (and funny) coercions.

It's ok to say that JS's type coercion is a misfeature, good programmers learn to not throw out the baby with the bathwater.


If you take [time-span] to understand the [x], all of these "hidden surprises" magically disappear.

Rewritten as a general programming language "smell". (That said, I do enjoy me some Javascripting, and I have a side-project with it.)


These things, like default global namespace, aren't just bad to a particular class of gray-beard enterprise developers who build AbstractFactoryFactories and are correspondingly easy to ridicule. They're _bad_ bad, net-negative properties of a language. I'm not sure why you would (appear to) defend them. Can you please clarify?


I imagine the OP isn't defending them, but just remarking about how sick they are of hearing people bitch about javascript.


I struggle to think of someone who considers themself as a "hacker" and would use "AbstractPatternVisitorHandlerFactory classes."


I had a lot of respect for Anders in the Borland days. Now he seems more and more to be just a Microsoft shill.


This is how people that think in oop and love java think, everything that does not have classes is unmaintable, this is very subjective.


It's about the type system.

Dynamic, weak typing makes writing static analysis/refactoring/etc tools extremely hard, but more importantly makes nearly any compile-time guarantees impossible. Having your app crash because of a small typo of a member name is impossible in C++/C#/Java. It happens to me almost once a day with Node/JS.


This rings very true to me too, as our entire application is written in Perl. As much as I do like the language, the lack of just about any static guarantees mean we regress an awful lot. Yes, we have unit tests, but until we have 100% coverage we have gaps for regressions that a compiler could have picked up.


Anyone doing a large project in an weakly-typed language will eventually spend more time writing unit tests than features.

No-one should even be thinking about unit tests if they are not already using a language in which all code paths can be evaluated and type-checked at compile time. Why get a dog and bark yourself?


This is not why you write tests. You write tests to be sure nothing breaks when you make changes.

And you should do this with any language, typed or not.


Using a language with static typing means that there are a lot of tests you don't have to write. Do you remember the units trick from physics? If you forgot which equation you're supposed to use, keep on using identities until you're in the units you're supposed to be. Static typing checks that your units are correct for free.


Well, not entirely for "free", but I do agree that the price is much lower than what you end up paying eventually for the convenience of dynamic typing.


I don't ever have to write a test in OCaml to tell me what I need to fix if I change a function signature, or add another item to a struct or an enum, or change a function to return something else, or anything like that. The compiler does it all. Every code path is evaluated at compile time. 90% of unit testing is just not needed in OCaml or Haskell (and that which you do need, there's QuickCheck for).


I had the same experience when writing Haskell. I would start by inserting a function call at the top level referencing a function I hadn't written yet, and then start hacking on the function and all its helpers. Without fail, as soon as the program compiled it was basically correct. The only thing that could go wrong were legitimate algorithmic errors, such as using the wrong base cases for recursion or something.


Except that to work around the pesky types, Java people started moving everything into XML. Now they have a horrible solution to being able to work typeless.


Apparently you haven't looked at Java development in the last 5 years, so you may want to stop making statements about it that make you look like a fool.


I just did a three month enterprise Java project. I admit that I hadn't used it in a while, so I picked Spring like in the old days (+Hibernate at first, but had to kick it out eventually). And hell it turned out complicated (even with Spring). What is the new mantra that makes Java suddenly usable? Playframework?


It doesn't look like you're interesting in anything except following your own mantra of "Java suxx", but XML configuration files (which were never really about working around the type system) have been almost universally replaced by annotations.


I know about annotations, but I admit to not being the biggest fan. And they lead to even more files...


How so? I've only ever seen them eliminate external configuration files. Hell, thanks to annotations and some simplifications to the standard, EJBs have turned from the epitome of overengineered bloat into a simple, lean service layer.


Annotations have only ever led to less files for me


Could you elaborate(/give references) about your claim?

(I don't know anything about the GP, but I really haven't looked at Java development in 5++ years. (-: If nothing else, I might need to update my jokes :-) )


XML configuration files have pretty much disappeared/become optional. It's all done via annotations nowadays, which are much less verbose since their context is implicit, and which are actual language constructs known to the compiler.


Thanks!

Annotations have the disadvantage of needing a recompile to reconfigure?


Can I ask why you're rewriting code on your production server on the fly without the aid of the rest of your tool chain?

In any good development shop you make a change, your CI server picks it up, builds it, and creates a release candidate you deploy. Every change should be checked into source control and built by your automated build bot.

At that point the difference between changing an annotation and an XML configuration file should be moot. I'd think the annotation would be easier because you can still mess up the syntax of the XML file pretty easy (e.g. "Can you change the blahblah label to System & such?" That ampersand will hose your system when you get it to production).


Well, there's always some genuine configuration that contains the actual differences between environments, like DB connection and API keys, and which isn't going to be part of the automated build.

But that's a tiny subset of what architecture astronauts try to label "configuration".


So how about using a tool like jslint that will get you 90% of the static checking and will solve the kind of crash you mentioned ? Looks pretty good to me.


Does jslint handle imports? Which would be surprising, given the lack of a standard system in Javascript? If it doesn't, then this leaves you very far from your 90%.

On the other hand, pylint for Python is really good for static checking, even if it won't catch everything.


No, this is what people that have real life experience from large scale applications think.

I have quite some experience with most mainstream dynamic languages, and wouldn't do any large scale application with any of them.

The company I work for, does large scale enterprise consultancy projects.

This means:

- Multiple development sites;

- Some projects have up to 200 developers;

- Usually several megabytes of source code;

- Continuous Integration build systems with automatic unit and integration tests

- Usually distributed architecture

- High performance requirements

No way I would advise anyone to do develop such systems in a dynamic language, let alone in JavaScript.


Maintaining a large PHP project written by idiots, in addition to a much smaller codebase in Javascript has convinced me of the importance of static typing for large-scale projects.


By the way, if all you need is classes, there are many many libraries that give you those in JS (not to talk about CoffeeScript).

What I really miss from a maintainability point of view with javascript, on the other hand, is better development tools (ie IDEs and testing tools). I'm pretty sure there is a big opportunity there.


> everything that does not have classes is unmaintable

Not that javascript doesn't. It doesn't have the sugar around it, and it doesn't statically check them. But javascript's OO is not "prototype-based" (that doesn't even make sense, prototypes are not a unit of reuse in Self) and it's not anything even remotely close to Self's.

Javascript's OO is single-inheritance class-based with no `class` sugar but at the end of the day it behaves pretty much the same way (and offers no more features — less if anything) Python's or Ruby's class-based OO work (sans metaclasses).


Was the argument really about classes? I would have expected this to be about the lack of namespaces. (I can't watch the video, it stops to buffer every second.)


Yet Google agrees with him and pushes Dart


Note that Go has no 'classes', and doesn't follow what many people consider mainstream OO principles (eg., inheritance), and many people would say this is one of the things that make it so great, specially in large projects (working out a good type hierarchy, and evolving it over time is extremely difficult and painful).

The problem with JavaScript is not lack of 'classes', but a not just dynamic but also very weak type system.

Add to that the callback-hell caused by the async model of things like Node.js, and you end up with something very hard to maintain quite fast.


I think they're covered under "think in oop and love java"


I don't think the Go developers "think in oop", and they certainly don't love Java.


You definitely can create classes in JavaScript, its just not especially convenient.

But to me its not really a critical issue, because OOP is very easy in CoffeeScript, which is my favorite language and happens to compile to JavaScript.


If you're going to attack Node.js, do it to its face.


Yes, he's very afraid of Node.js, that's why he said those things. I mean who is this Anders Hejlsberg guy, criticizing the BEST work of language designer giants like Brendan Eich and framework masterminds like Ryan Dahl.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: