Dartlang for JavaScript developers

This is my first blog and I’ll start with a new language: DART.

Dart has been open for public for some time now, but the official 1.0 version is still not out there. Since it targets JavaScript developers, I decided that my first post should address the differences.

dart-logo

On the official dartlang page there is a single sentence description of dart:

A new language, with tools and libraries, for structured web app engineering

Well it’s new, at the time of writing it has not yet been released. It’s for web which means it has to deal with javascript. It has, or at least supports tools and is structured.

It is obvious that Dart is supposed to replace JavaScript. Of course that is impossible. Browser makers can’t even agree on existing standards and Dart is a Google project, so no way.

To overcome this problem one of the main goals is efficient dart2js translator. The overall philosophy is: if your browser supports dart VM we’ll use it. If not, we’ll fall back to JS. This way JS becomes assembly language of the web.

So what is the Dart team up to?

As Google is developing a lot of web apps (which means a lot of JS), they obviously decided to increase productivity in that area. Therefore they decided to fix javascript flaws and created Dartlang.

I have extracted some areas in which JavaScript is not perfect and described how Dart improves them:

Javascript uses prototype structure that confuses class oriented developers

As I have read in a certain book, most developers prefer object oriented programming based on classes and interfaces and when they use JS they usually don’t realize that JS is prototype oriented. So there are tons of Class implementations in JS, but the “this” problem was still there. Then we decided to reorganize out code to avoid “this” and also to make some kind of private and public methods. So we get this structure:

function GameScore(playerNick) {
  // private members
  var currentPoints,
      currentLevel,
      pointsPerLevel = 1000;
  // private function
  function increaseScore(points) {
    currentPoints += points;
    if (currentPoints > pointsPerLevel) {
      currentLevel += 1;
      currentPoints = currentPoints - pointsPerLevel;
    }
  }
  function reset() {
    currentPoints = 0;
    currentLevel = 1;
  }
  // construction
  reset();

  // public methods
  return {
    addPoints: function(points) {
      increaseScore(points);
    },
    getScoreText: function() {
      return "Player " + playerNick + " is at level " + currentLevel + " and has " + currentPoints + " points.";
    },
    resetScore: function() {
      reset();
    }
  }
}
var score = new GameScore("Me");
console.log(score.getScoreText()); // Player Me is at level 1 and has 0 points. 
score.addPoints(1200);
console.log(score.getScoreText());// Player Me is at level 2 and has 200 points. 

The Dart does it the “old”, familiar way:

class GameScore {
  String _playerNick;
  int _currentPoints = 0;
  int _currentLevel = 0;
  static const _pointsPerLevel = 1000;

  GameScore(this._playerNick) {
    resetScore();
  }

  void resetScore() {
    _currentPoints = 0;
    _currentLevel = 1;
  }

  void addPoints(int points) {
    _currentPoints += points;
    if (_currentPoints > _pointsPerLevel) {
      _currentLevel += 1;
      _currentPoints = _currentPoints - _pointsPerLevel;
    }
  }

  String getScoreText() {
    return "Player ${_playerNick} is at level ${_currentLevel} and has ${_currentPoints} points.";
  }
}

main() {
  var score = new GameScore("Me dart");
  print(score.getScoreText()); // Player Me dart is at level 1 and has 0 points.
  score.addPoints(1200);
  print(score.getScoreText()); // Player Me dart is at level 2 and has 200 points.
}

This way most developers will find it understandable and familiar from the first look! Note that members starting with “_” are library private (not class private).

Dart team is balancing between dynamic and static type of language. So not everything is public, but private is not fully private. And there are no protected members so writing a framework that is supposed to be extended by other people will require programmers to use public members in places they would usualy use protected. The workaround that I plan to use here is to name those members with something notable that would make it clear that this member is not public and should not be used, like: void protectedInitializeSelf(params);
There is a discussion about protected and private in dart: https://groups.google.com/a/dartlang.org/forum/#!topic/misc/MgQY-Cnimbw

 

And there is also inheritance and abstraction for which in JS there are only workarounds:

abstract class SomeOtherFeature {
  String doTheOtherFeature();
}
class MyExtendedClass extends MyClass implements SomeOtherFeature {
  String doTheOtherFeature() {
    return "I did it!";
  }
}

var a = new MyExtendedClass();
print("${a is SomeOtherFeature}"); // true
print("${a is MyClass}"); // true
print("${a is String}"); // false

Optional types in Dart

In Java variables have to declare type. In JS there is no way to do that. In Dart you can do both:

String myString = "Something";
var myString = "Something";

Now this is something I really like. Sometimes variables are self explanatory and there is no need to declare type, but many times declaring a type will make code more descriptive. Not to mention a great help it gives to the editor and code validation.

Also function parameters in JS can cause headaches. Parameters have no type, and when many optional parameters are available, people often put a single options parameter for which you have to look into source code or documentation.

Dart has excellent solution for optional parameters:

void manyParams(String name, {String title: null, int age: null}) {
  ...
}
manyParams("myName");
manyParams("myDoctor", title: "dr");
manyParams("mySon", age: 3);
manyParams("myCar", title: "gas consumer", age: 12);

The great thing is that editor is able to help you with possible parameters, and if you make a mistake, editor can detect it!

Multiple files organization

JS was created as a helper language to make html a little dynamic. It was not meant to be split in multiple files. Over the time it has grown, and most of html-s today include many JS files. This causes many issues:

  1. JS files must be included in the right order
  2. dependencies are resolved manually in HTML
  3. problem of global objects which names can conflict (using prototpe and jQuery at the same time)
  4. starting a new project requires manually downloading and including all libraries used
  5. library upgrading and dependencies might be a problem

Today there are many frameworks that resolve this issue. My favorites are RequireJS with AMD modules and all those NodeJS tools for building a single assembled JS file (Grunt, Almond, JSLint…). In Dart all is included in the core language, including the pub tool to organize libraries and dependencies.

Every dart project has pubspec.yaml configuration file that explains dependent libraries and to install them you can simply use pub install command. It is inspired by ruby bundler and similar tools.

pubspec.yaml

name: test_polydart
description: A sample web application
dependencies:
  browser: any
  polymer: any

When pub install is run, it creates pubspec.lock file which describes all dependencies and versions.

Other files in a project are included with include keyword at the top of the file. The libraries are organized using library and part of keywords:

main.dart

import 'dart:html'; // dart built in library
import 'red_box.dart'; // library in my project
import 'package:polymer/polymer.dart'; // polymer package fetched via pub tool

void main() {
  ...
} 

red_box.dart

library RedBox; // this is RedBox library

import 'package:polymer/polymer.dart';
import 'dart:html';

part "red_box_component.dart"; // this file is part of RedBox library

red_box_component.dart

part of RedBox; // this file is part of RedBox library

@CustomTag('red-box')
class RedBox extends PolymerElement with ObservableMixin {
}

Chaining vs nesting asynchronious function calls

Dart is single threaded language, just like JS. Handling asynchronius results can be donne with anonymous function that have to be nested within the caller function. Now at some point we get function within function within function…

Dart in this matter is just like JS, but at some points the Future class was introduced.

Future httpRequest = HttpRequest.getString("http://someurl");
httpRequest.then((response) => print("Got ${response}"), onError: (_){print("Got error");});

Chaining operations:

expensiveA().then((aValue) => expensiveB()) 
            .then((bValue) => expensiveC()) 
            .then((cValue) => doSomethingWith(cValue));

Waiting for multiple operations:

Future.wait([expensiveA(), expensiveB(), expensiveC()])
      .then((List responses) => chooseBestResponse(responses))
      .catchError((e) => handleError(e));

Now that might look like nothing special, but eventually your code will be slightly different. Every async function will not return value, but the future generic of the resulting type:

Future getUserPreferences(String userId) {
  Completer completer = new Completer();
  HttpRequest.getString("some url").then((response) {
    completer.complete(new Preferences.fromJson(response));
  });
  return completer.future;
}

Future showLogin({message: null}) {...}

void renderMainScreen(Preferences prefs) {...}
main() {
  showLogin().then((String loggedUserId) => getUserPreferences(loggedUserId))
             .then((Preferences prefs) => renderMainScreen(prefs))
             .catchError((Error e) => showLogin(message: "Login failed"));
}

updated from Florian’s comment:

Note that there is no reason to use Completer if you already got Futurebut I wanted to present the existence of Completer and the Future. Function getUserPreferences would be better written as:

Future getUserPreferences(String userId) {
  return HttpRequest.getString("some url").then((response) {
    return new Preferences.fromJson(response);
  }
});

 

JavaScript design flaws

JS has many annoying issues. This page has a nice list: http://www.pixelstech.net/article/index.php?id=1354210754

null and undefined

Dart has no undefined. If you use variable that has not been declared it will throw exception. Also editor will inform you of this error in advance:

void main() {
  print("${myVar}");
}
Unhandled exception:
No top-level getter or setter 'myVar' declared.

In Dart null is an object:

void main() {
  var myVar;
  print("${myVar}"); // null
  print("${myVar.toString()}"); // null
  print("${myVar == null}"); // true
  print("${myVar is Object}"); // true

  int myInt;
  print("${myInt}"); // null
  print("${myInt == null}"); // true
  print("${myInt is Object}"); // true
  print("${myInt.toString()}"); // null
}

Also all declared variables without value are null.

variable scope

Scope of variables in Dart is clear. If it is declared inside function it’s localized to that function. If declared in a class – it’s localized to that class. If it’s declared outside of everything – it is global.
Now global objects in libraries can have the same name. Therefore when importing library it can be given a prefix:

import "dart:math" as m;
void main() {
  print("${m.sin(m.PI / 2)}"); // 1.0
}
+ operator is predictable
void main() {
  print("${1 + 10}"); // 11
  print("${"1" + "10"}"); // 110
 print("${1 + "10"}"); // The argument type 'String' cannot be assigned to the parameter type 'num'
  print("${"10" + 1}"); // The argument type 'int' cannot be assigned to the parameter type 'String'
}

There is NaN in Dart, but it’s not like NaN in JavaScript:

a = "String" / 2; // makes a NaN

In Dart NaN is a part of double precision, thanks Florian :)

double b = double.INFINITY / double.INFINITY; 
print("${b}");// NaN which is declared as double.NaN

So there is no Batman JavaScript error in Dart :)

Knowing if something is an array or not

In Dart array is called a List (class List). It is easy to know if an object is an array or not. It is also well implemented so there are not “tricks” using it.

void main() {
  var a = [1, 2, 3];
  print("${a is Object}"); // true
  print("${a is List}"); // true
}

There are also other collections like Set and Map and like List, they all implement Iterable interface which declares all those nice functions we need – forEach, where, reduce, …

“this” is always “this”

In JS there is a rule. If a function is part of an object then this points to that object. If not it points to the “owner” of that function. That creates a lot of problems when using anonymous functions:

var object = {
    window: "window from object instance",
    showWindow: function() {
      console.log(this.window); // window from object instance
      var inner = function() {
        console.log(this.window); // global window object
      }
      inner();
    }
  }
  object.showWindow();

Dart has this fixed:

class MyClass {
  String toString() => "instance of MyClass";

  void checkAnonymous() {
    print(this.toString()); // instance of MyClass
    var inner = () {
      print(this.toString()); // instance of MyClass
    };
    inner();
  }
}
void main() {
  new MyClass().checkAnonymous();
}

jQuery inclusion

jQuery has become something like a standard for using JS on the client side. Most projects I start, start with jQuery. Rails also include it by default in a new project.

Dart comes with dart:html package that has query and some other methods which implement all that we need from jQuery. It was made as jQuery for Dart with the same syntax of querying elements. But nevertheless a jQuery port to Dart was created as a package: http://pub.dartlang.org/packages/dquery. I guess that it is used as a helper for porting existing jQuery dependent libraries to Dart.

Conclusion

I’m very excited about Dart, but there will be some time before I get to use it in production. JavaScript has a huge community and there will be some time before Dart comes close to it.

For my next post I’m preparing the following topics:

  • working with JSON objects in Dart and some helpfull libraries
  • interoperability between JavaScript and Dart
  • testing in Dart
  • debugging in Dart
  • polymer UI framework
  • porting frameworks to Dart
  • Dart command line and server side

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>