The Pew Pew Manifesto

This is the last post of the Pew Pew Chronicles – a series of blog posts about a crazy journey that eventually led to Pew Pew becoming one of the first apps in Microsoft’s App Store.

I would like to end this series with summarizing the underlying ideas of my work on Pew Pew.

 

Please wake up now

Last month I gave a talk about creating Metro applications using ActionScript. In order to spice up the Q&A segment at the end of my talk I thought it would be fun to add a final slide with some provocative statements. I called that slide The Pew Pew Manifesto, which I am going to share with you in a minute.

I suspect that not everybody will agree with what I put into the Pew Pew Manifesto. But before we enter a religious war about dynamically versus statically typed languages, or whether JavaScript can be used for large projects, let me stress that I didn’t write the Pew Pew Manifesto in order to pick up a bar fight. I wrote it in order to wake up my colleagues that fell asleep during my talk! (Just kidding, nobody fell asleep.)

That said, let me present the Pew Pew Manifest:

  1. JavaScript is not suitable for large web apps.
  2. JavaScript is the browser’s assembly language.
  3. Choose a high-level language for developing web apps.
  4. Cross-compile from a high-level language to JavaScript.
  5. Use Google’s Closure Compiler for optimizing JavaScript.
  6. Optimized JavaScript is obfuscated and protects your intellectual property.
  7. Let your app degrade gracefully when OS features are missing.
  8. Invade every Web Platform!

I’ll walk you through the list…

 

JavaScript is not suitable for large web apps.

I am serious: Don’t write large web apps in JavaScript. As mentioned in Planning A Death March I don’t think JavaScript is suitable for implementing large projects. Last year I was asked to help out with an internal project that used JavaScript. Over time the code had grown out of control and there was only one person left, who really understood how it worked. The project had also become unscalable, because adding more developers would not have increased the overall productivity. It would have taken those developers too much time to come up to speed and work on this particular code base written in JavaScript. I looked at the code and suggested this crazy idea: Why not porting the existing JavaScript code to ActionScript and then continuing development in ActionScript while cross-compiling to JavaScript?

Porting JavaScript to ActionScript in order to cross-compile back to JavaScript? Was that crazy-talk? Perhaps, but it surprisingly worked and probably saved that project. Here is what happened when I ported the JavaScript code to ActionScript:

  • The code naturally distributed itself from about 10 files to over 100 files when creating ActionScript classes.
  • Porting JavaScript to ActionScript revealed inconsistencies and at times incoherent uses of types.
  • My cross-compiler automatically added type annotations necessary for compiling with Closure’s Advanced Mode.

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.

You wouldn’t believe how many inconsistencies I found when porting JavaScript to ActionScript. Often JavaScript code, which looked perfectly fine at the first glance, revealed itself as incoherent the moment I tried to compile it with an ActionScript compiler. Sloppy usage of types were to blame for most of the inconsistencies. A very popular anti-pattern seemed to emerge: functions, which return incompatible types:

// (bad) JavaScript
function createBunnyOrToaster(createBunny)
{
  if( createBunny )
    return new Bunny();
  return new Toaster();
}

 

Of course if you start writing this kind of code your receiving end gets quickly contaminated with inconsistencies:

// (bad) JavaScript
function feedBunnyOrToaster(bunnyOrToaster)
{
  if( bunnyOrToaster instanceof Toaster )
    bunnyOrToaster.insert(new Toast());
  else
    bunnyOrToaster.feed(new Carrot());
}

 

Nobody in his right mind would write this kind of code. But I have seen it more than once. In fact I have written that kind of code myself. My point is that it’s not necessarily the developer’s fault that we end up with bad code like the examples above. I would argue that dynamically typed languages like JavaScript are too tolerant and don’t slap developers on the fingers when they start mixing up bunnies with toasters. It might cramp your artistic programming style if you cannot mix up bunnies with toasters but where I come from doing so results in bad projects.

Just to be clear: You can write bunny-and-toaster code in ActionScript, too. But I would argue that you get immediate feedback of something being fundamentally wrong as you are typing that code, just by being confronted with questions like “what should be the return type?”. Of course you can choose to use “*” or “Object”. But most people pause and rethink their design at that point.

Not everybody is as smart as Gilad Bracha or John Resig and those that aren’t – like this author – are probably better off with writing their code in a statically typed language. Many will probably disagree with this statement. It might make more sense after reading the next Manifesto statement.

 

JavaScript is the browser’s assembly language.

In the following week after I gave my talk about creating Metro apps using ActionScript I ran into a few colleagues and I was surprised that it was this statement that they found most intriguing.  One colleague argued that the definition of assembly language implies a one to one correspondence with the underlying machine code. Another characteristic element of assembly languages are that they are also generally understood to be non-portable. Since JavaScript is neither, where does this idea of JavaScript being an assembly language come from and what is this about?

The first time I heard about JavaScript described as an assembly language was through Gilad Bracha’s blog. In 2008 he wrote in java’scrypt:

I’m not advocating writing clients in Javascript directly. Javascript is the assembly language of the internet platform (and the browser is the OS). It’s flexible enough to support almost anything on top of it, and poorly structured enough that humans shouldn’t be writing sizable applications in it.

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. In that sense the code looks more like binary code to me. It turns out that this kind of “binary looking” JavaScript is the most efficient version in terms of size and performance.

If you are interested in the discussion about JavaScript as an assembly language I recommend listening to JavaScript is Assembly Language for the Web: Semantic Markup is Dead!

 

Choose a high-level language for developing web apps.

Implementing your project in JavaScript  leaves you with some tough choices: If you ship the development version of your JavaScript code with your product, it is not obfuscated, and also bigger, and slower. If you want a faster, smaller app that also protects your intellectual property you have to optimize your JavaScript. But then you also have to annotate your code with type hints. If you don’t annotate your code with type hints the Closure compiler won’t be able to optimize as much and your code is less obfuscated, bigger, and slower. If you do find yourself writing JavaScript with type type annotations then why not using a high-level language instead and use a cross-compiler that automatically generates the type hints for you?

That’s really the point of this Manifesto statement.

 

Cross-compile from a high-level language to JavaScript.

You have several choices:

Some folks are even experimenting with cross-compiling Scala to JavaScript.

In the case of Pew Pew I used my own ActionScript to JavaScript cross-compiler. In Planning A Death March I made the argument that if you had to implement Photoshop in six weeks you wouldn’t pick an assembly language. Being able to cross-compile from a high-level language to JavaScript was a crucial element of my plan.

 

Use Google’s Closure Compiler for optimizing JavaScript.

In Optimizing cross-compiled JavaScript I wrote a whole article about the importance of optimizing your JavaScript code. As far as I know Google’s Closure Compiler is still the best JavaScript optimizer out there.

 

Optimized JavaScript is obfuscated and protects your intellectual property.

A nice side effect of optimizing your JavaScript is that it becomes unreadable as I illustrated with my SpriteExample snippet. You would never write “binary JavaScript” code like that manually. But for professional software production it is important to be able to write code in a maintainable high-level language while deploying a product that does not reveal the ideas of your source code.

In my opinion the current version of Visual Studio 11 for Metro is missing this important point. There is no built-in JavaScript optimizer and no support to hook one in. Microsoft seems to assume that nobody wants to optimize JavaScript code. Their current IDE only outputs Debug JavaScript code. There is in my opinion essentially no Release option for JavaScript apps in Visual Studio 11 for Metro. I really hope Microsoft will change that.

 

Let your app degrade gracefully when OS features are missing.

This might be an obvious statement. But what I am saying is, if you write a Metro app in a high-level language like ActionScript make sure that your code “degrades gracefully” so your app would also run in most modern browsers on other platforms.

I’ll give you an example from my Pew Pew code:

const domWindow : DOMWindow = adobe.globals;
if( domWindow.hasOwnProperty("Windows") )
{
  var appLayout : ApplicationView = Windows.UI.ViewManagement.ApplicationView;
  appLayout = appLayout.getForCurrentView();
  appLayout.addEventListener("viewstatechanged", onViewStateChanged, false);
}

 

The code above only registers onViewStateChanged if the environment is known to support the Windows namespace. In other words, if this code runs in a browser without Metro support, it won’t register for view state changes.

Why going through the trouble? The last statement of the Pew Pew Manifesto will answer that question.

 

Invade every Web Platform!

I think, being able to write code once and reuse the same code on different platforms without  compromising neither functionality nor aesthetics of your app’s user interface is a very desirable goal.

This might sound like science fiction, but what if all of your apps in the near future were just custom browsers? Like Flash Player playing SWFs your custom browser would run your JavaScript, that is, code written in a high-level language and then cross-compiled to JavaScript. There are many cases where your JavaScript code could run in the browser as is. But how would you get your app into the Apple App Store, or the Android Marketplace? How would you make money?

This is why I find PhoneGap (now an Apache incubator project called Apache Cordova) very intriguing. In many ways PhoneGap’s architecture might lead to a new type of apps that you could call “custom web browser apps”. You can look at the PhoneGap architecture as a framework that provides custom browsers for multiple platforms (iOS, OSX, Android, Blackberry, Windows Phone). All you have to care about are the HTML, CSS and JavaScript parts you have to provide. PhoneGap even supports special JavaScript APIs for features like Camera, Location, or Accelerator, that are not accessible via standard DOM APIs.

For example, if I wanted to get Pew Pew into the Apple AppStore and Android Marketplace I would simply cross-compile my ActionScript project to JavaScript and plug it into the PhoneGap architecture. As far as I know I can even write my own native plug-ins for PhoneGap. If that’s really the case I can pretty much invade every web platform that PhoneGap supports.

Maybe that’s what I should be working on next…