Why I moved from Java to Dart

27,236 reads

I heard some are moving from JavaScript to Dart. Well, my journey was a bit different: I moved from Java to Dart. And, part of adwords.google.com came with me.

AdWords is at the heart of Google’s revenue stream and is currently being rewritten in Dart. But the corner of AdWords I worked on — the part that sells skippable ads on YouTube — has been running Dart since 2014.

The interesting part of the story is that we weren’t told to use Dart, or even asked to use it; we saw what Dart had to offer and decided it was worth a try.

Crucially, we didn’t do a big-bang rewrite. We were using Java/GWT, and were able to integrate it with Dart in the browser in order to move to Dart incrementally. As our familiarity with Dart grew, so did our enthusiasm for it; and in the end we rewrote nearly all our browser code from Java/GWT to Dart.

Here are the major reasons I found to prefer Dart over Java.

1. The Dart SDK

If you’ve written much Java, one of your biggest complaints is probably the SDK libraries. Key decisions were made a long time ago, and can’t be changed. You only have to compare Java’s Iterable to Dart’s Iterable to see how far things have come.

So the best way to write Java is to bring in a third party library. At Google we use Guava, and it’s quite wonderful. For example, it offers FluentIterable. But without being part of the SDK it’s still a second class citizen.

Dart had the chance to do everything from scratch, and it shows. Here’s an example that you might use FluentIterable for in Java:

print(

[1, 2, 3].where((x) => x.isOdd).map((x) => x + 10));

-->

(11, 13)

2. Callbacks, Futures and async/await

If you’ve written much Java/GWT, you’ve probably developed an autonomic response to the word “callback”. The merest mention brings you out in a cold sweat.

I’ve personally written and maintained terrible, horrible code that threaded callbacks through callbacks through callbacks to deal with different eventualities in chains of RPCs.

Here’s a relatively tame example:

public void getFoo(AsyncCallback<List<String>> callback) {

getThenFilter("foo", callback);

}

private void getThenFilter(

final String parameter,

final AsyncCallback<String> callback) {

makeRequest(new AsyncCallback<List<String>>() {

void handle(List<String> values) {

List<String> filtered = new ArrayList<>();

for (String value : values) {

if (value.startsWith(parameter)) {

filtered.add(value);

}

}

callback.handle(filtered);

}

}

And then Dart came along with the Future class, and an SDK designed around it, and made all that go away. This is when it immediately became clear Dart was talking to me, personally. It was providing exactly what I needed to make my day better:

Future<List<String>> getFoo() {

return _getThenFilter('foo');

}

Future<List<String>> _getThenFilter(String parameter) {

return makeRequest().then((result) =>

result.where((string) => string.startsWith(parameter))

.toList());

}

And it didn’t stop there. They talked about adding async/await keywords to Dart as a nicer way to use futures. You could just write “await” and then continue coding as if the asynchronous code blocked, and everything would be handled for you behind the scenes.

And then they actually did it. As a long-time Java developer I had learned to think of discussions about language changes as purely hypothetical, never to impact my work day. I was overjoyed:

Future<List<String>> getFoo() {

return _getThenFilter('foo');

}

Future<List<String>> _getThenFilter(String parameter) async {

var unfiltered = await makeRequest();

return unfiltered.where(

(string) => string.startsWith(parameter)).toList();

}

3. No Nonsense, No Boilerplate

Moving from Java to Dart you encounter so many features that just make life easier:

Gaining just one of these would raise a smile from any Java programmer. The whole lot at once is overwhelming — in a good way.

4. Moving Forward

The language improvements didn’t stop with the addition of async/await. We recently got a new generic method syntax. Work is in progress on a non-nullable types experiment. The type system is being revamped with strong mode.

Dart is moving forward in a thoroughly pragmatic way: any new feature has to pull its weight in real code. So there will be new stuff — but only good new stuff.

5. Webby

Finally, Dart came with UI frameworks that were “webby”. We actually started before AngularDart existed in any form, with Web UI. Then we used AngularDart, and now AngularDart 2. All of these had something in common: lightweight, HTML-like templates. And it turned out this was a wonderful way to build UI code.

The Search for Immutability

The only big thing missing from Dart from my point of view was good support for immutable collections and values. So I quickly hacked together something workable for my team to use, in the hope that someone else would write packages I could use.

In the end, though, I put in the time to make something worth open sourcing. The built_collection and built_value packages were born.

And that’s it. Dart is ready for prime time. You can build huge, mission critical web applications in it, as we did with AdWords for video; or you can take flutter and start building mobile apps for Android and iOS. And as my recent articles have shown, Dart on the server goes really well with Dart on the client.

As to my own personal story; shortly after giving a talk at the Dart Developer Summit I joined the Dart team. So in the end I really did “move to Dart”.

Update

A couple of extra notes following feedback to this article on Reddit.

FluentIterable wasn’t a great example of needing third party libraries to complement the SDK, as Java 8 adds streams which offer significantly similar functionality.

The next SDK comparison that comes to mind is reading a file. In Dart you can just do “new File(‘foo.txt’).readAsStringSync()”, or “await new File(‘foo.txt’).readAsString()” if you don’t want to block. I always had to look up the current correct way to do this in Java.

It’s easy to find more examples, and this shouldn’t come as a surprise: Dart’s SDK was built a long time after Java’s. API design in OO languages has come on long way.

I’d like to emphasize that this article is about Dart as compiled to js, for use in the browser. The transition we made was from Java/GWT to Dart.

And, finally, I think it’s worth saying that Java is still my second favourite of the many languages I’ve worked in.

Tags