Anders Hejlsberg Is Right: You Cannot Maintain Large Programs In JavaScript

There’s a quote over on a Channel 9 video of Anders Hejlsberg:

Erik Meijer: Are you saying you cannot write large programs in JavaScript?

Anders Hejlsberg: No, you can write large programs in JavaScript. You just can’t maintain them.

With a follow-up post on DZone asking if you agree with this quote or not. I haven’t listened to the interview so I honestly don’t know if the quote is taken out of context or not.  But honestly, I don’t think it matters if the quote is taken out of context because …

Anders Is 100% Correct

No ifs, ands or buts about it. Maintaining large JavaScript apps is nearly, if not entirely, impossible.

But Derick, You Write Large JavaScript Apps…

No, actually, I don’t.

I write JavaScript applications that appear to be large. They may be large systems, but in reality they are very small applications (“programs” as Anders says). In spite of 5 to 10 thousand lines of JavaScript code per system, easily, my applications follow the secret to building large applications:

“The secret to building large apps is never build large apps. Break your applications into small pieces. Then, assemble those testable, bite-sized pieces into your big application” - Justin Meyer, author JavaScriptMVC

(Quote taken from http://addyosmani.com/largescalejavascript/ )

And that’s what I do. I write dozens of small “applications” – modules, really – that are then composed in to larger functional systems at runtime.

Improving Ander’s Quote

Like I said, Ander’s quote is 100% correct. I think Ander’s quote quote can be improved, though.

Did you notice that Justin Meyer’s quote didn’t mention JavaScript at all? The truth is, it doesn’t matter what language you’re writing in. This secret to writing large application is applicable to all of them. It’s why we have functions, objects, modules, classes, and other ways of grouping related sets of functionality and/or data together.

So, Ander’s quote should read:

Erik Meijer: Are you saying you cannot write large programs in [any language]?

Anders Hejlsberg: No, you can write large programs in [any language]. You just can’t maintain them.

Maintaining Large Systems

You’ll have to pardon the link-bait title of this post, and really pay attention to the semantics and language for a moment.

Anders is correct, but not because he is talking about JavaScript. He is correct because it is not possible to maintain large applications in any language / platform / runtime. Write small applications as modules, classes, assemblies, libraries, and/or any other type of modularization technique for your language and runtime environment. Then compose those small “applications” (modules, etc) in to large systems which are easier to write and maintain, in JavaScript or any other language.


Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Derick Bailey

Derick Bailey is an entrepreneur, problem solver (and creator? :P ), software developer, screecaster, writer, blogger, speaker and technology leader in central Texas (north of Austin). He runs SignalLeaf.com - the amazingly awesome podcast audio hosting service that everyone should be using, and WatchMeCode.net where he throws down the JavaScript gauntlets to get you up to speed. He has been a professional software developer since the late 90's, and has been writing code since the late 80's. Find me on twitter: @derickbailey, @mutedsolutions, @backbonejsclass Find me on the web: SignalLeaf, WatchMeCode, Kendo UI blog, MarionetteJS, My Github profile, On Google+.
This entry was posted in AntiPatterns, Composite Apps, CQRS, Craftsmanship, Javascript, Philosophy of Software, Pragmatism, Principles and Patterns, Risk Management. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Nolan Egly

    I completely agree with your adjustment of Ander’s
    quote.  However, I would suspect that programming
    language has a huge impact on program size and maintainability.  I don’t have any citations to hard studies,
    but I’ll dangerously speculate anyway.

     

    Some languages have much more limited scoping options than
    others (compare C and JavaScript to C++ and Java/C#).  Being able to localize state is essential to limiting
    unintended side effects.

     

    Some languages also make certain mistakes easier than
    others, such as accidently assigning instead of comparing a value inside an if
    statement in C as opposed to C# which requires an if condition to explicitly be
    a boolean.

     

    This doesn’t even begin to account for the actual complexity
    of the application.  A 10k line chess
    program is going to be a lot more difficult to work with than a 100k line forms
    over data/data driven/CRUD application.

     

    I agree any language at some sufficiently large point will
    suffer a drop in maintainability, but I feel that point will be measurably
    different across languages.  I’d love to
    see a study on this, but think it would be difficult to factor out developer
    skill, which is an entirely different issue.

  • Anonymous

    I don’t think it was taken out of context. If you start watching at about 11:15 in you can hear the whole exchange.

    Regardless, you make a good point.

  • http://twitter.com/justinbmeyer justinbmeyer

    The other secret … http://canjs.us … Shameless plug!

    Having being part of a 100k+ LOC, I can asure everyone that you can maintain a large JS project.  You just have to develop everything as independent as possible. 
    This is why JMVC tries to organize almost every file in it’s own folder, with it’s own test and demo page.  Every component is it’s own mini library.  And we eat our own dog food, JMVC, CanJS, and jQuery++ are all organized this way.  For example:  https://github.com/jupiterjs/canjsAnd IMO the value of tests isn’t in finding bugs, it’s in forcing the developer to isolate their code. If a chunk of code depends to heavily on a large number of other components and a specified state, it’s going to be a pain to test.

    Finally, people matter more than any technology.  A good manager who understands that taking time for quality now means faster development later is a rare person.

    • http://rendion.myopenid.com/ render

      100K LOC is large to you?

      • http://www.selectioneffect.info/ Corrie Engelbrecht

        @openid-26332:disqus So what is large to you? What is the largest JavaScript program you’ve maintained or developed?
        Not another language, but JavaScript, which is what you commented on.

    • http://mutedsolutions.com Derick Bailey

      +1000 to all of that :)

    • Anonymous

      “IMO the value of tests isn’t in finding bugs, it’s in forcing the developer to isolate their code.”

      Yes, and they also allow us to make changes without the fear of breaking things.

  • Daniel Marbach

    That is exactly what SOA has always told us to do. Large applications are a composition of several SOA services (attention: NOT webservices). These services itself are decomposed into business components and business components are divided into autonomous components

    Daniel

  • http://rendion.myopenid.com/ render

    The key to the kind of modularization that might make large systems composable in Javascript is well defined APIs.  I have yet to really see decent Javascript APIs, they are getting better, but given the 99% slop that I have encountered on web projects, I doubt the seriousness of folks who want to bet the farm on this language.

    You cant even get javascript web APIs to work together much less compose a large system out of these things.  Good luck?

  • http://twitter.com/Thoriumi Tuomas Hietanen

    This Javascript in the quote represented a dynamically typed language (vs. statically typed languages like Ander’s C#).

    Small components are must. But with dynamically typed languages you don’t know the interfaces: You are not 100% sure what the component may return. This makes defining of component boundaries much harder.

  • Anders Pearson

    “Ander’s” is not the possessive form of “Anders”. 

    Speaking as another Anders, this drives us nuts.

    • http://chrismissal.lostechies.com Chris Missal

      Anders

    • Neil Haughton

      As does “it’s” meaning “belonging to it” when it should be “its”.

  • Agile Hobo

    If so, why Microsoft doesn’t talk about future of Silverlight? And why they don’t support it in Metro browser in Windows 8?

  • Agile Hobo

    Ah, and why they support to develop Metro apps using HTML and JavaScript?

    • http://www.facebook.com/people/Anton-Martynenko/100001239604684 Anton Martynenko

      Because Microsoft usually invests millions in something and then abandon it (i.e. Silverlight) ;)

  • http://www.selectioneffect.info/ Corrie Engelbrecht

    This is a very insightful article. I’ve programmed large systems in C, Python, Delphi, C++, Java, and C#, and I’m almost at the stage where I can add JavaScript to that list.

    It’s universally true that only programmer disciple, and following proper design principles, help with software construction.

    It doesn’t help to blame a language for unmaintainable programs. You can accomplish that in any language.

    It’s much better to have testable modules, or varying granularity, that can be assembled together and work as a progressively testable system.

    And then the challenge is to stay consistent. And to keep testing. And to never implement short-cuts that undermine the integrity of the modules. And to always stick to well known design principles. And, and…

    Language has probably little to nothing to do with the maintainability of a system.

    • http://twitter.com/herbrandson herbrandson

      “Language has probably little to nothing to do with the maintainability of a system.”

      I have found that to not be true. For example, I worked on a project recently where I had to add some features to an existing codebase that I didn’t write. The features required work on both the server side code (c#) and client side (javascript). Both the existing c# and javascript were written by the same (very talented) developer. I found the c# to be 10x easier to extend than the javascript. I would attribute this to the better tooling available on the c# side due to being a statically typed language. Just a few examples…

      1. being able to quickly see what functions are part of a class
      2. knowing what data type each parameter of a function expected
      3. knowing what data type would be returned by each function
      4. being able to change the api (i.e. adding new parameters to a function) and having the compiler quickly tell me what other parts of the system needed to be updated.

      On the javascript side, most of these things required a lot of manual poking around through hundreds of lines of code and a lot of manual testing.

      I realize I am only one data point here, but I have worked on large scale projects in the last few years using c, c++, c#, objective-c, javascript, java, php, and a few others. Each language has been fun to work with and each has it’s own strengths and weaknesses. But, I have to say that the statically typed languages were significantly easier when it came to extending/maintaining an existing codebase.

      • http://www.selectioneffect.info/ Corrie Engelbrecht

        Well, nothing you’ve said actually supports your conclusion that the language itself is related to maintainability.

        Rather, your points appear to rely on tool availability and capability.

        Here are some JavaScript IDEs that support code completion and refactoring to the same degree or better than Visual Studio does for C#:
        1. Aptana Studio (or Eclipse, which is basically the same thing)
        2. BBEdit
        3. Komodo
        4.  NetBeans
        5. WebStorm
        6. JetBrains

        And with all due respect, coding in JavaScript requires a completely different mindset than coding in C#.

        Dynamic typing and functional programming are FEATURES of JavaScript, and requires the correct “thinking in JavaScript” approach to utilize. If you  (you = general populace) want static typing in JavaScript, then you’ve immediately missed a vital, foundational precept of JavaScript, and you will just not succeed in writing maintainable code in the language. But this is NOT the fault of the language, but rather of the programmer. 

        And I think most of the rest of what you’re saying is just arguing from ignorance.

        BDD in JavaScript: Jasmine (http://pivotal.github.com/jasmine/)
        TDD in JavaScript:  QUnit, JSMock
        Source Documentation: JsDoc
        Runtime loading: RequireJS
        Libraries: JQuery, JQueryUI, etc.

        I could go on.

        Furthermore, I don’t know your very talented developer, just as I don’t know you.

        But if the same developer wrote C# code that is highly maintainable, and JavaScript code that is not maintainable, according to a 2nd developer, namely you, then your conclusions are mere supposition.

        It could be that you yourself cannot “think in JavaScript”, and that is the source of your problems.

        It could be that the original developer was not good at JavaScript.

        I’m sorry, but I’ve had quite enough of all the C# developers who think they can comment on JavaScript just because they think they can program.

        Programming languages are different from each other. JavaScript is a FUNCTIONAL programming language. To try and use it as a structured OO language is like trying to use a rapier to mow the lawn. You might think you’re doing well, but actually you’re completely misunderstanding what a rapier is and is used for, and how to do it.

        • Anonymous

          @CorrieEngelbrecht:disqus You raise some good points…
          1. It is important to make a distinction between the tools used to develop in a language and the language it’s self. Poor tools does not equal a poor language (and vice versa).

          2. Trying to use dynamic languages in the same way you would use a static language is missing the point. Dynamic languages strengths are completely lost if you don’t approach them in a different way.

          3. “Programming languages are different from each other”. Each has its own strengths and weaknesses. There is no ”one language to rule them all”.

          4. I completely agree that my opinion is only one data point and far from scientific. I don’t pretend to speak the authoritative truth on this subject and readily acknowledge that I have much to learn.

          Also, thanks for the list of IDEs and libraries you listed. I’ve used many, but not all of them. I’ll check the rest out. I do love new toys :)

          There are also a few points I’d like to clarify…

          1. I get the impression from your comments that you believe me to be a c# only developer (forgive me if I’m mistaken). On the contrary, I pointed out in my original comment that I consistently work in multiple languages. I therefor don’t believe that I am unable to “think in JavaScript”.

          2. If c# developers were unable to think in JavaScript, it would seem to follow that JavaScript developers would also not be able to think in c#. If that were true then we’d be wasting our time with this discussion. Neither of us would be capable of understanding the others side. I don’t believe that to be the case at all.

          3. I enjoy developing in JavaScript. There’s much about it that’s fantastic. JQuery is one of the best libraries I have used in any language. However, my personal experience has been that JavaScript is less maintainable then other languages. Again, just one data point. But not an uninformed or unqualified opinion.

          4. Not all languages are equally maintainable. To take an extreme case, try modifying (or even reading) someone else’s assembly code. Pearl is also commonly referred to as a “write only” language.

          5. Maintainability is not the only reason to select a language. I find c# to be more maintainable then JavaScript, but c# is a very poor choice if you want to write code that will run in the browser. JavaScript is fun and lends itself to rapid development, but it’s not really an option if you want to write a native iPhone app (yes, i know you code use an embedded browser, but that’s really not a native app IMHO). C++ is fast and pretty portable, but  in general it’s too slow to develop with for your typical web app.

          6. Good tools go a long way toward making a project maintainable. They are not the only factor by a long shot, but they can make a significant impact. I have personally found static code analysis tools to make a significant impact on my ability to modify code without introducing bugs. 

          7. Many good tools are the result of good metadata about the code, and a good Type system is the best source of code metadata I’ve seen. Most of the points I listed in my original comment are only possible with good metadata.

          8. It’s very possible that I’m ignorant on this point, but I have not yet seen a tool that does a great job with the points I listed in my original comment (especially points 2 and 3). In fact, it’s the very strengths of JavaScript (it’s dynamic nature) that would seem to make these impossible.

          Once again, I’m not saying that JavaScript is a bad language. But, I do believe there is a case to be made that it is less maintainable over the long run then other languages. Especially as the scale of an application grows (even with best practices such as modular design, unit tests, etc.).

          Thoughts?

          • http://www.selectioneffect.info/ Corrie Engelbrecht

            Hi @twitter-14289895:disqus 

            To clarify:
            1. I explicitely wrote “ (you = general populace) ” so that you would understand that I mean you in the general sense, and not you specifically, unless stated otherwise.

            2. No, this does not follow at all. Any developer can think in one or more languages. Just because a developer cannot “think in JavaScript” says nothing at all about a completely different developer, and what languages that developer might be able to think in.

            4. A Perl (which is what you probably meant) programmer that applies loose coupling and high cohesion principles will produce a maintainable system.

            A Perl programmer that does not, will produce an unmaintainable system.

            It’s as simple as that. And this applies to any language you care to insert there.

            5. Maintainability is a completely nonsensical differentiator among languages. You cannot judge a future, not yet written, system’s maintainability based on some sort of predictive crystal ball that extrapolates maintainability given the name of a programming language as input.

            6. Why do you mention this? I have listed the tools for JavaScript that make the JavaScript ecosystem exactly on par with the C# ecosystem. JavaScript has JSLint for static analysts, and testing frameworks, and refactoring IDEs and mocking suites, and testing suites (non-TDD type testing and TDD type testing), and code completion.

            There’s no tool you can mention that exists in Visual Studio or for C# that does not also exist for JavaScript.

            7. I don’t think you understand dynamic typing. JavaScript does not have classes. It only has functions. Any OO concept is done on object prototyping. But this does not prevent any static analysis, or any documentation generation, or any refactoring, or any code completion from being performed on JavaScript source code.

            8. So this is where I’m starting to think that the “you = general populace” that can’t think in JavaScript should become “you = herbrandson” cannot think in JavaScript.

            And I say this without trying to be insulting, even though I’m probably failing at that:)

            You do not need to know what data type is expected by a function in its parameters, nor do you need to know what data type will be returned by a function. JavaScript does not work that way.

            I want to mention two good sources of information, with the idea that future visitors might be able to use this information as well, so don’t take this personally:

            a). The book Object-Oriented JavaScript is one of the best sources of good JavaScript practices, with specific sections on writing maintainable code: http://www.packtpub.com/object-oriented-javascript-applications-libraries/book

            b) The book “JavaScript: The GoodParts” is another standard source of excellent information: http://shop.oreilly.com/product/9780596517748.do

            I could go into this, but basically it comes down to this: if you find yourself wanting a type system in JavaScript, then you’re not writing JavaScript.

            JavaScript is a functional programming language, with objects prototypes as an added structural bonus.

            But of course, developers depend heavily on object prototyping because we want to use OOP.

            However, this requires the JavaScript developer to understand something fundamental about JavaScript: object prototyping IS NOT the same as a class system.

            Object prototyping is a paradigm all on its own, and it results in a polymorphic typing system, which is immensely powerful.

            However, if you want to misuse this object prototyping mechanism and pretend it’s a class modelling system like in C#/Java/C++, then you’re not only missing the point, but it’s like you’re trying to use gasoline in a diesel engine. The two things are superficially equivalent, but they require completely different approaches.

            Once again, when you mention tools that can make use of parameter types or function return types, then you’re actually mentioning … tools.

            Not the language.

            It is completely feasible to write large, maintainable JavaScript systems.

            The key is just modularisation.

          • Anonymous

            @derickbailey:disqus Sorry we’ve sorta hijacked your blog post at this point :(. If it goes on much longer maybe we can take it off line.

            @CorrieEngelbrecht:disqus First let me say how much I am enjoying this discussion. I’ve learned some new things and have also been able to better think through and clarify some of my opinions. So, thanks!

            I’d like to respond to a few of your points, but in re-reading my responses I think I’m trying to make too many points in too small of a format, so I’m going to try to reign it in a bit here :)

            I think it’s important to make the distinction that I am not saying that ANY language is NOT maintainable. It’s not a boolean thing. Of course you can maintain anything given enough time and patience. Rather, I’m trying to make the argument that some languages, and by extension the tools that those languages support, lend themselves in varying degrees to application maintainability (same thing goes for tools. JSLint and gcc both do static analysis, but in different ways and to different degrees). 

            Take the following example. I admit it’s a bit contrived but I think it still works to illustrates my point. Both sets of code do the exact same thing. Would you agree that the second one will be easier to maintain?

            ASSEMBLY:

            push        ebp 
            mov         ebp,esp 
            push        edi 
            push        esi 
            push        ebx 
            sub         esp,38h 
            mov         esi,ecx 
            lea         edi,[ebp-38h] 
            mov         ecx,0Bh 
            xor         eax,eax 
            rep stos    dword ptr es:[edi] 
            mov         ecx,esi 
            mov         dword ptr [ebp-3Ch],ecx 
            mov         dword ptr [ebp-40h],edx 
            cmp         dword ptr ds:[04AE0AF4h],0 
            je          0000002D 
            call        73114587 
            xor         edx,edx 
            mov         dword ptr [ebp-44h],edx 
            nop 
            mov         eax,dword ptr [ebp-3Ch] 
            add         eax,dword ptr [ebp-40h] 
            mov         dword ptr [ebp-44h],eax 
            nop 
            jmp         0000003F 
            mov         eax,dword ptr [ebp-44h] 
            lea         esp,[ebp-0Ch] 
            pop         ebx 
            pop         esi 
            pop         edi 
            pop         ebp 
            retC#:

            public static int Add(int value1, int value2)
            {     return value1 + value2;}

          • http://www.selectioneffect.info/ Corrie Engelbrecht

            @herbrandson:disqus This is a straw man argument, my friend.

            You’ve copied the CPU view code from a debug view or something from a function you wrote.

            This does not correspond at all to maintaining a system written in Assembler.

            I actually have programmed large systems in Assembler, namely device drivers for network cards way back then.

            When programming in assembler, you can do the following:

            1. Modularize functionality into separate files
            2. Organize files into a directory structure, which is a form of namespacing
            3. Label your routines and call them or jump to them as the occasion demands

            If you were to take just those facts, it’s obvious that you can write tools and an IDE that are 100% equivalent to what is available to C# developers today.

            It is definitely a lot more work to program in Assembler, because you have to basically write everything you want to use from scratch.

            But coding in Assembler is not very hard. All you have to do is to program only in Assembler for about a year, and then you’ve done the learning curve. From then on, coding in assembler is like coding in any other language that you know intimately: easy.

            I will grant you that the type of projects where you actually code in Assembler are complicated, low-level stuff, where you have to be extremely detail oriented and fastidious, but that has nothing to do with Assembler. Because those same projects can be, and often are, written in C instead. And C is very definitely maintainable.

            Coding in assembler also requires you to write programs in layers:

            a) First write the very basic routines, like reading a hardware port, or something like that
            b) Write layer on top of that, which makes use of the lower level layer
            b) Repeat as necessary

            Just coding in layers like that actually has the beneficial side-effect of enforcing a layered architecture (logically level), which is a fundamental property of any well-designed system.

            Now, if you were to listen to Assembler programmers who do not structure their code like this, and who do not modularize as in a)-c), then you have discovered an incompetent programmer. You have NOT discovered anything about the maintainability of programs written in Assembler. But you might have discovered something about the maintainability of programs written by the aforementioned programmer:)

            Also, if you were to just stare at a block of assembler code, it would look like gibberish, I suppose.

            But I promise you that there are large systems written in Assembler, and they’re shining examples of how to code a highly maintainable system in any language.

            It’s all about applying basic design principles.

            It’s NOT about what language you choose to do the final “typing in” of the previously designed system.

            Here’s an OS written in Assembler. I’ve looked at the source code, and it’s extremely good, and I would find it easy to maintain that system, if I had to:
            http://www.menuetos.net/64bit.htm 

          • Eric Herbrandson

            @CorrieEngelbrecht:disqus Are you saying Assembly is every bit as easy to maintain as C? Every bit as easy to maintain as JavaScript (all else being equal)?

  • Anonymous

    Agreed, but there is another problem in deviding application to small modules: the huge amount of this modules and their interoperation.

  • Frank

    ‘The secret to building large apps is never build large apps.’,I can not agree more.
    But I want to ask a question, how do you handle the error(ajax,incorrect param) interaction?
    first,where to (parse() or validate() ) and how to(globally,or in  the model view,or in a specify view );

  • Donzo

    Your opinion should be backed up by some facts or examples to use this “teachable moment”. Also, warn at the other end of the scale, about chunks of code that are so tiny,
    no one can follow the overall program flow. best, donzo

  • martin

    Well sure, if you want to write a large system you need to break it up into smaller pieces. That’s standard software development practice, so what’s new here?

  • jmh

    “So, Ander’s quote should read…”Really?  You can just edit someone’s quote?
    Cool!
    So,  Derick’s blog entry should read: …