2015-04-21

Dart Dev: do you have unittest:any in your pubspec?


tl;dr If you're using unittest, make sure you have an upper-bound on the package version in your pubspec.yaml.


The new (unit)test package is almost ready and it's awesome.

The 0.12.0 release will be the migration point from unittest to test.

Folks who use unittest will be able to upgrade to 0.12.0 and will get an exported version of test. You'll notice some breaking changes and a lot of deprecations. All future work will happen in the test package, so you'll want to migrate eventually.

In the mean time, if you're not ready to migrate, make sure you don't end up with 0.12.0 accidentally.
You might wonder why your tests start acting weird.

2015-04-08

Enforce formatting for your Dart projects

A while ago, I wrote about using Travis to add continuous integration to your Dart projects.

I've started adding a new trick to tool/travis.sh: format verification.

I add a script to my tool directory:

#!/bin/sh
dart_files=$(git ls-tree --name-only --full-tree -r HEAD | grep '.dart$')
[ -z "$dart_files" ] && exit 0

unformatted=$(dartfmt -n $dart_files)
[ -z "$unformatted" ] && exit 0

# Some files are not dartfmt'd. Print message and fail.
echo >&2 "dart files must be formatted with dartfmt. Please run:"
for fn in $unformatted; do
  echo >&2 "  dartfmt -w $PWD/$fn"
done

exit 1

Then I add a line to the top of travis.sh:

# Ensure the source is formatted
$(dirname -- "$0")/ensure_dartfmt.sh

Here's a commit that adds this support to the dartdoc project.

I find it's much easier to collaborate on a code base when a whole pile of formatting arguments are settled upfront.

Cool? Let me know if you try this on your project.

2015-03-07

Angular.ts.js.at.dart.wtf

You might have heard that Angular is going to be using TypeScript.

This has lead to questions about the relationship between Angular and Dart.

Let me see if I can help.

First, Angular 1.

Angular 1 JS is crazy popular. Mountains of folks use it. It’s awesome.

Angular 1 Dart was a hand-rolled port of Angular 1 JS. It tried to follow the JS flavor of the framework, while being a true Dart framework. While a lot of folks have used Angular 1 Dart, especially within Google, it turned out to be tough to maintain two separate versions of the same framework for two languages.

Enter Angular 2.

Angular 2 was pitched in October as a better/faster framework built on AtScript – AtScript was an extension of TypeScript from the beginning.

Important point: Angular 2 has always been built on TypeScript.

The Angular/TypeScript announcement is amazing news. The features that were added to AtScript are being pulled into TypeScript.

Important point: AtScript has been merged into TypeScript – one less language to worry about.

TypeScript lets the Angular folks build a framework that targets both Javascript and Dart simultaneously. Check out the Angular Travis page to see build output for both languages.

Important point: Angular 2 has first class support for Javascript AND Dart out of the box.

This leaves us with THE BIG QUESTION:

Why isn’t Angualr 2 just built in Dart?

Answer: the Angular folks want to deliver a great framework for BOTH Javascript and Dart.

Dart generates great Javascript for browsers, but we have work to do to generate reusable Javascript libraries.

The Angular team needs to generate reusable Javascript libraries.

That’s it.

One of my personal goals is to make Dart great for generating JS libraries. We’ll have more to discuss at the Dart summit in April – psst – you should register.

In the mean time, check out the alpha of Angular2 Dart package.

Check out the Angular GitHub project if you want to play with Angular for Dart or Javascript – OR BOTH.

File bugs. File feature requests. Send pull requests.

I’ve had fun using the Dart analyzer to do a bunch of cleanup in the Angular source – it’s nice.

Happy hacking – now with 20% less FUD.

2015-02-17

Testing Dart projects with latest release and code coverage

Test your package stable and dev

If you’re using Travis CI, it’s as easy as adding a dart: entry to your .travis.yml file. You can specify dev, stable or both to make sure your code works great on current and future build of the Dart SDK.

language: dart
dart: 
  - dev
  - stable

See the dartdoc project for an example.

Here’s a build report for dartdoc on Travis CI.

Getting code coverage with coveralls.io

  1. Setup an account on coveralls.io using your GitHub account.
  2. Pick the GitHub repo for your project
  3. Get the Coveralls “repo token” for the project.
  4. Populate it in Travis CI Settings as COVERALLS_TOKEN – or whatever you like.
  5. Add Coveralls to your travis.sh script.
#!/bin/bash

# Fast fail the script on failures.   
set -e

# Run the tests.
dart --checked test/test_all.dart

# If the COVERALLS_TOKEN token is set on travis
# Install dart_coveralls
# Rerun tests with coverage and send to coveralls
if [ "$COVERALLS_TOKEN" ]; then
  pub global activate dart_coveralls
  pub global run dart_coveralls report \
    --token $COVERALLS_TOKEN \
    --retry 2 \
    --exclude-test-files \
    test/test_all.dart
fi

See the source_gen project for an example.

Here’s the coverage report for source_gen on Coveralls.

Happy hacking!

2014-05-26

Equality and Dart

A month ago I asked a question on my blog about a piece of Dart code.

For the below class, what are at least two things wrong with the implementation of operator ==.

class Foo {
  int _a;
  int _b;

  int get a => _a;
  int get b => _b;

  ...

  bool operator ==(Foo other) {
    return other._a == this._a && other._b == this._b;
  }
}

A number of guesses were posted to the G+ discussion.

Context: designing types for reuse is tough

If Foo is only used within one library – so it should be named _Foo – the existing implementation might be totally fine.

But if Foo is…

  • Used a lot within a single library or package
  • Part of a code base with a lot of developers
  • Part of a public package
  • Serves as a base class

…then you have to think a lot harder about its implementation.

Special Equality

The parameter to operator == should always be Object.

Don’t believe me? Paste the code below into try.dartlang.org. I’ll wait.

void main() {
  var items = [0, 1, new Bar(5), 6, 7];
  print(items.contains(6));
}

class Bar {
  final int value;
  Bar(this.value);
  bool operator ==(Bar other) => value == other.value;
}

operator == is used in Iterable for contains, where, and many other methods. Map also uses == for its final check after finding matching hash codes. If there is any chance that an instance of your class will have equality checked with any other type – either directly or via very common Dart classes – you should not make assumptions about the argument to == except that it’s not null. Dart takes care of the null check for you.

This is easy to fix:

class Bar {
  final int value;
  Bar(this.value);
  bool operator ==(Object other) => 
    other is Bar && value == other.value;
}

General Equality

Just like relativistic physics, the special case is pretty straight forward. The general case is a bear.

I read that Special Relativity took Einstein 8 weeks where General Relativity took him 8 years, but I digress.

The special case is a black-and-white comparison: is the operand the same type as this or not. The general case introduces a pile of gray.

Dart has implicit interfaces. This means anyone can implement your Foo or Bar class.

Let’s say we fixed our original example for the special case:

class Foo {
  int _a;
  int _b;

  int get a => _a;
  int get b => _b;

  bool operator ==(Object other) {
    return other is Foo && other._a == this._a && other._b == this._b;
  }
}

What if someone implements Foo in another library.

import 'package:foolib/foolib.dart';

class MyFoo implements Foo {
  int get a => 41;
  int get b => 42;
}

Try doing if (foo == myFoo).

You’ll get a runtime error along the lines of MyFoo does not have instance property _a.

General Equality: simple fix

The simple fix is, well, simple. Avoid using private members of objects you don’t completely control. In the case of == that means any private members on other.

This problem goes beyond operator == and extends to any method anywhere in your library.

Consider the static distance method below.

class MyPoint {
  num _x, num _y;
  num get x => _x;
  num get y => _y;
  static double distance(MyPoint a, MyPoint b) {
    // should you access _x or _y here?
  }
}

See what I mean?

General Equality: simple mistakes

Avoiding private members is only part of the problem. Let’s look at MyPoint again.

class MyPoint {
  final num x, y;
  MyPoint(this.x, this.y);
  bool operator ==(Object other) =>
    other is MyPoint && other.x == x && other.y == y;
}

No private members. No type assumptions. We’re home free! Right?

Try this in try.dartlang.org:

class MyPoint {
  final num x, y;
  MyPoint(this.x, this.y);
  bool operator ==(Object other) =>
    other is MyPoint && other.x == x && other.y == y;
}

class MyPoint3 extends MyPoint {
  final num z;
  MyPoint3(num x, num y, this.z) : super(x, y);
  bool operator ==(Object other) =>
    other is MyPoint3 && other.x == x && other.y == y && other.z == z;
}

void main() {
  var mp = new MyPoint(1,2);
  var mp3 = new MyPoint3(1,2,3);

  print(mp == mp3); // true
  print(mp3 == mp); // false
}

You’ve just broken one of the three laws of equality.

Cue mass hysteria.

There are solutions to this problem, but they are not simple. We’ll have to bother Florian Loitsch for details.

…and I haven’t even gotten into implementing hashCode and handling mutable fields – here’s a taste.

Now what?

Keep calm, but be paranoid.

  • Be careful when implementing ==.
    • Make sure it’s something you want to sign up for.
    • Read up on implementing hashCode correctly.
    • If you’re class has mutable state, be afraid!
  • Always type the argument to operator == as Object and do a type check.
  • If your class is public, remember: any instance of Foo may not be my implementation of Foo.
    • Stick to the public interface.
    • Document what you consider equality.

An alternative: public class, private implementation

If you’ve dug around the Dart source code, you’ve likely seen this pattern:

abstract class SomeClass {
  int get a;
  String get b;
  bool someMethod();

  factory SomeClass(int a, String b) => new _SomeClassImpl(a, b);
}

Besides allowing us to efficiently support both the Dart virtual machine and compiling to Javascript, this pattern also allows one to detect random implementations of a type.

class _SomeClassImpl implements SomeClass {
  final int a;
  final String b;
  bool someMethod() ...

  _SomeClassImpl(this.a, this.b);

  // No impersonators allowed
  bool operator ==(Object other) =>
    other is _SomeClassImpl && other.a == a && other.b == b;
}

This pattern also allows you to lock down an object system where an arbitrary instance won’t fly.

Future and Zone are examples from the Dart SDK. You won’t get very far trying to implement or extend either of them – at least if you try to use them in place of their native implementations.

This post was edited and published using StackEdit. Freakin’ awesome. I may not ditch blogger after all.

2014-05-02

Delivered: Pop, Pop, Win! ported to StageXL


The Dart Editor ships with a Minesweeper-inspired game – Pop, Pop, Win! – that I originally hacked together in late 2012.
About a month ago, I made an open request for a Dart community member to port the Pop, Pop, Win! demo to StageXL – a powerful and flexible 2D graphics library for Dart written by Bernhard Pichler.

Alex Gann stepped up and delivered.
Once Dart v1.4 is released, you'll be able to explorer the source code and run the game from the welcome page of the Dart Editor.

In the mean time, you can browse the source on the GitHub source mirror.

I'm also keeping a running copy of the latest code on this GitHub page.

Alex did a bunch of work to optimize image and audio formats, including turning the audio files into a sprite. The download size of the entire game dropped by over a third: from 1.8MB to 1.1MB.

You'll also notice you can play games of arbitrary complexity – click on the logo for help and to switch difficulty.

Huge thanks to Alex for his hard work.

Huge thanks to Bernhard for the great StageXL package and for helping out Alex with a few feature requests during development.

2014-04-28

Method Piping - Dart Syntax Proposal


Update 1: I was delighted, but not totally surprised that someone else thought this was a good idea – 2 months ago. Patrice Chalin wrote up the proposal on his blog in February and filed a feature request. I've closed my request as a duplicate of his.

Disclaimer: This is not in anyway official. It's an idea. If you're excited about it, great. Please star the associated issue. I'm trying to judge interest in the Dart community.

One of the first Dart issues – the 13th, to be precise – was for C#-style extension methods.

This is not possible in a consistent and performant way due to Dart's type system.

But I'm pretty sure that most Dart developers that want C#-style extension methods would be happy with something much more simple.

Imagine the following code
...
class Foo {
  ...
  void fooMethod() {
    ...
    var items = [true, null, "Test", 42];
    var isEven = _isEven(countWhere(items, (e) => e is bool)); 
  }
}

_isEven could be an instance method on Foo, or a static method on Foo, or a top-level method in the current library.

countWhere could also be a instance or static method on Foo, or a top-level method on the current library or an imported library. It could also be a function defined in-line in fooMethod.

Now imagine an alternative syntax for the same behavior, with a new sugar in the form of |> – the method pipe.

...
class Foo {
  ...
  void fooMethod() {
    ...
    var items = [true, null, "Test", 42];
    var isEven = items |> countWhere((e) => e is bool) |> _isEven(); 
  }
}

Method pipe is simple. Anything of the form

g(f(expression))

Can be written as

expression |> f() |> g()

Basically, the expression on the left side of |> is passed as the first parameter of the function on the right of |>.

What about multiple arguments? Named arguments?

If you had function

int count(int a, int b, int c, {int d}) { ... }

You can call it as

count(1, 2, 3, d: 4);

or

1 |> count(2, 3, d: 4);

What if you try to call a method that has no default parameters? Or you try to call a field like a method?

The same thing that happens now.
int value = 5;
void run({String arg}) { ... }

// Today: Warning in the analyzer and errors at runtime
value(10);
run("test");

// Tomorrow: Warnings in the analyzer and errors at runtime;
10 |> value();
"test" |> run();

See where I'm going?

The method pipe syntax – |> – is completely up for debate. But I like the model. One could create and import a library full of top-level methods that consume IterablegroupBy, countWhere, wrapWithUnmodifiableList, etc and write.

var items = [1, 2, 3, 4, 5];

var groups = items |> groupBy((e) => ...);
var evenCount = items |> countWhere((e) => ...);
var readOnly = items |> wrapWithUnmodifiableList();

Thoughts?

Here's the feature request.