Programming Snake using Dart

August 2, 2013

Dart is a new web programming language designed with the purpose of helping developers building high-performance apps for the (modern) web. When it was announced by Google last year, it took my attention because of its premise to replace Javascript. As Dart recently entered beta, I decided to explore the language and implement my own little Snake game. This post gives a brief introduction of the language and describes my experiences on programming Snake using Dart.
  • Dart is a well-designed, object-oriented programming language designed for building rich web applications. Its syntax feels really familiar and especially if you already know some Java or JavaScript, you’ll probably be productive in less than an hour.

    The core Dart language is pretty straightforward. It is a class-based, object-oriented language wherein everything is an object (including primitives and nulls). Dart is optionally typed, which means that you have the choice to add type annotations or not. The semantics of your code will eventually be the same, but the advantage of adding them is that errors can be detected early by the static checker. Although Dart is a ground-up re-imagining of what JavaScript should be, it undeniably maintains many of Javascript's paradigms like, for instance, first-class functions.

    Unlike Javascript, Dart not only has an optional typing system, but it also lets you programmatically update the DOM (Document Object Model) of a HTML page in a very natural and intuitive way. Other differences are: Isolates to take advantage of multi-core machines, interfaces and generics.

    Dart code can run in its own virtual machine or can be compiled to Javascript (via the Dart2js compiler). Benchmarks show that the performance of Dart code running in its virtual machine is significantly better than its Javascript equivalent (whether or not compiled from Dart code). The problem, however, is that no major browser currently supports the Dart virtual machine, meaning that the only way to make Dart applications accessible on the web is to compile them to Javascript first.

    Compiling Dart code to Javascript results in a massive amount of (ugly) code. It should be noted though that the performance of this code is slightly better than its hand-written Javascript equivalent because Dart2js applies several optimizations such as method inlining and pre-computation.

    Dart's ultimate goal is to replace JavaScript. Although this is very ambitious and not something that can happen overnight, the motivation behind this is that Javascript is not suited for heavy, large-scale web applications. Therefore, Dart offers a better performance, scales better for large projects, and provides more security features than Javascript does.

    As I was eager to explore the Dart language, I decided to program a game of Snake. The reason why I thought of Snake is because I believe it's a great application to implement when exploring a new language. The application logic is relatively simple, yet it requires to touch several facets of the language such as dealing with keyboard input, storing data, maintaining a user-interface and basic arithmetic operations.

    Implementing Snake in Dart was fun. One of the reasons for this is that I found it really great to have this Java-like syntax for web programming while still being able to use many of the Javascript programming features. Dart also comes with its own IDE and browser (supporting the Dart virtual machine), which makes writing Dart code an elegant and seamless experience.

    I do have two points of criticism though. First of all, Dart currently lacks support for enumerations. By itself this is not a major issue, but especially in large projects, enums are often inevitable for writing clean interfaces. Luckily, the problem has been recognized by the community and support is on its way. As I wanted to use a Direction enumeration in my Snake implementation, I explicitly implemented the directions as static constant variables inside a regular Direction class. Here is the code:

  • class Direction {
      static const LEFT = const Direction._(0);
      static const RIGHT = const Direction._(1);
      static const UP = const Direction._(2);
      static const DOWN = const Direction._(3);
      static get values => [LEFT, RIGHT, UP, DOWN];
      final int value;
      const Direction._(this.value);
  • Another issue I experienced is related to Dart's optional typing. Although types are optional and only relevant in development modus, I decided to consistently use them in order to detect type errors early. However, the problem I had is that it's sometimes difficult to know the exact type of a return value. Especially in the case that you dynamically query an element from the DOM, it sometimes takes quite some time to find out what the type of this element will be. This information is obviously (somewhere) available in the API documentation, but it's not automatically inferred by the type checker. To proof my point, consider the following code snippet from my Snake implementation where I query the HTML5 canvas object.

  • CanvasElement canvas = query('#canvas');
    CanvasRenderingContext2D ctx = canvas.getContext('2d');
  • The documentation specifies that the query method returns something of the type Element. This is, however, just a general interface, so if you want to invoke specific canvas operations (like here getContext), you need to know that the canvas is actually of type CanvasElement in order for the program to type check properly. Of course, this is what programming is, but my point here is that sometimes it's just very clunky to find out the actual return type of an expression.

    Apart from these two minor things, it was a lot of fun to program in Dart. The clean syntax together with a great set of language features -optimized for the web- makes writing web applications in Dart faster and more elegant than in Javascript. However, as long as major browsers don't support the Dart virtual machine, Dart will just remain a niche language with barely no impact. Compiling your code to Javascript is, at least for now, the only way to get your Dart projects out to the world.

    A demo of my Snake implementation can be found here. The actual code is available on Github.