Skip to main content

What’s your favorite Dart feature?

Earlier this year we had an ongoing thread where Googlers shared their favorite Dart feature—perhaps a less known one. We wanted to share these insights from some of our most engaged internal users more broadly. Hence this post.

The names have been changed to protect the innocent, but the contents should constitute some fine reading.

Here we go:



What's your favorite "less known" (or undocumented) feature of Dart?
Any particular syntax trick or library function?

Java has loads of these, tricks ranging from the double-paren. init (Map<String,String> {{ put("a", "1"); }};) to "sneaky throwing" ANY exception.
Anything similar in Dart?

Cheers,
Agile Analyzer



As a Java developer, my opinion of both of those is: this is clever, but don't do it in real code under any circumstances.

-Bug Basher



I'm not a fan of tricks, and from what I've seen so far Dart needs very few. There are some features of the language that I feel are underutilized or are very new. Here are a few:

- Null is a type, so if you have a Future and you want to document that it doesn't return anything useful, make it a Future<Null>
- You can throw arbitrary objects in Dart without losing stack traces: throw "This is an error"
- const can be a local variable and it will still be allocated only once (no need to hoist it into a static field or top-level constant)
- You can create custom matchers and use them in your tests (example)
- There exists package:meta that the analyzer understands, and which has @protected, @required (for required named parameters), and others
- You can implement classes as every class also exports its interface.

-Clever Compiler



My favorite lesser-known feature is pretty simple: you can define stuff outside of classes.

I see a lot of users coming to Dart from Java or C# and they are in the habit of stuffing every variable or function inside a class either because they think you have to—which you do in those languages—or out of a belief that it makes their code better in some vague "OOP paradigm is best paradigm" sort of way.

Object-orientation is a fantastic paradigm for expressing some kinds of code. It works really well when you have interesting state and interesting operations that are deeply tied to that state. It's also great when you want polymorphism based on kinds of objects.

But a lot of times, you're just trying to express some vanilla data or some imperative behavior. For those, classes don't provide any value. If you just want to define the value of π somewhere, you don't need a class named, like, I dunno "MathematicalConstants" to put it in. You can just do:

const pi = 3.1; // Eh, close enough.

Likewise, sometimes all you need is a procedure, not a method. Say you create and file and write some string to it. You could make a "FileWriter" class or something, but why bother? You can just do:

void writeFile(String path, String contents) { ... }

You might be thinking that you need to put definitions inside classes to avoid name collisions and to "namespace" things, but you don't need to do that in Dart. Libraries in Dart are the unit of namespacing and modularity. With show, hide, and import prefixes, libraries are much better at expressing namespaces and dealing with name collisions.

If you made it this far, I will note one feature that really is rarely used. Did you know that you can define getters and setters at the top level too? You can define something that looks like a top-level variable but is actually doing computation.

Cheers!
--Dart Dogfood



+1 for simple short-hands.  When a language is young, there's a tendency to use it like that-other-thing-you-know.  These conversations are a really good thing.

Instead of writing:

if (foo == null) {
  foo = 'bar';
}

Just do:  foo ??= 'bar';

The "cognitive load" (ahem!) is much lower.  It's similar to Ruby's foo ||= 'bar' but better, because it strictly applies to nulls (vs. nil & false).

-Eager Execution



I like ??= for lazy-initialized fields

   T _foo;
   T get foo => _foo ??= _computeValue();

--Failed Function



I wouldn't describe these as "favorite" features, but they do seem to be lesser known:


+1 to avoiding things that are "clever" but hard to read.

--Great Googler



I don't see generators used all that much and there are some places where they really help.
https://www.dartlang.org/articles/language/beyond-async#generators

For some use cases a generator is going to be more readable than the alternatives, in others it's very tempting to write a 'clever' generator.

--Heated Hotspot



One of my favourite features is that the analyzer will tell you if you use a switch statement with an enum and don't list all the enum values.

This means that if you've been careful always to use switches when using enums (rather than if/else chains), you can just add the new value to the switch, run the analyzer, and it'll tell you all the places you need to update.

--Injected Iterator



Thanks everybody!!!

Lots of stuff to try out and/or read about! I've been actually thinking that something like the meta library would be nice (and hey, it's already live!)

Awesome thread :)

--Agile Analyzer



My favourite Dart things are foremost the ones I created ;) ... immutable collections, immutable value types, proper enums, and object oriented serialization:

- https://github.com/google/built_value.dart/blob/master/libraries_for_object_oriented_dart.md

And a few I didn't:

 - The ".." operator is a gift for anyone who likes fluent APIs.
 - source_gen (and now the "build" package) really hits the sweet spot for code generation.

Cheers
--JIT Juggler



Someone I was talking to mentioned another of my favourites - using interpolation instead of toString.

    x.toString()

can usually be replaced by

    '$x'  or  '${x}'

It is shorter, looks like it should be a string, and guarantees the result is a String (toString() may perversely return null, even in checked or strong mode).

--Failed Function



Kinda late for the party ;)

I just started to use Dart for two months, still so much to learn. Other than null-aware operators that is already mentioned, I also find double-dot operator very handy for method cascade.

Instead of doing:
o = new MyObject();
o.set(x);
o.set(y);

Now we can:

o = new MyObject()
   ..set(x)
   ..set(y);

--Klever Kompiler



Here's some I like:

You can use 'expand' to concat lists:
[[1,2,3], [4,5,6], [], [7,8,9]].expand((x) => x) // returns [1,2,3,4,5,6,7,8,9]

I don't think this pattern is used often enough, abstract classes which have a forwarding factory constructor to the real implementation:

abstract class Foo {
  factory Foo() = _Foo;
  // ... Foo methods ...
}

class _Foo implements Foo {
  // ... implementation  ...
}

This lets you put all your documentation on 'Foo' and let people call 'new Foo()' while the private class '_Foo' actually has all the implementation details that nobody cares about.

--Linked List



This may not come up that often, but I love the * operator on Strings (thanks Failed Function!):

_padRight(String message, int columns) {
   var padding  = " " * (columns - message.length);
   return '$padding$message';
}

--Main Method



I wouldn't call it a feature, but lot of people don't seem to realize (is it something originating from Java?) you can pass any function/method tearoff as an argument, not necessarily an anonymous literal, ie:

Instead of xs.map((x) => foo(x)) do xs.map(foo).

--Non Nullable



I really like functional methods in combination with tear-offs:

int bestScore = [1, 2, 5, 1].reduce(max);

And generators.

/// Merge [a] and [b] until [a] is fully consumed. Then add 42.
Iterable<int> combine(Iterable<int> a, Iterable<int> b) sync* {
  var aIterator = a.iterator;
  var bIterator = b.iterator;
  while (aIterator.moveNext()) {
    yield aIterator.current;
    if (bIterator.moveNext()) {
      yield bIterator.current;
    }
  }
  yield 42;
}


Seriously, though, this whole thread should be a blogpost on news.dartlang.org.

--Optimized Object



The only question remaining now is:

What is your favorite Dart feature?




Popular posts from this blog

Dart in 2016: The fastest growing programming language at Google, 2nd fastest growing in TIOBE Index

Dart was the fastest growing programming language at Google in 2016 with millions of lines of code written. It also made it to TIOBE Index Top 20 this month (see TIOBE's methodology).

It takes time to build something as ambitious as Dart and, in some ways, Dart is still in its infancy. But we're glad the hard work is starting to pay off.

Many thanks to our amazing community!

We're going to celebrate by ... releasing 1.22 next week (as per our usual 6 week release schedule).

The new Google AdSense user interface: built with AngularDart

AdSense is a free, simple way to earn money by placing ads on your website. The team just launched a completely new version of their app for publishers. Read all about it here. We asked Daniel White, the tech lead for the project, some questions because the new UI happens to be built with Dart and Angular2.


AdSense launched way back in 2003. How long is it since the last big redesign?
Last big redesign was called ‘AdSense 3’ and launched about 6 years ago. It was written in Google Web Toolkit (GWT) and the UI has evolved through several iterations - but this is the first ground-up redesign in 6 years. There are a number of long-standing UX issues that we’ve taken the opportunity to solve. A big shout-out to our UX team who’ve been 100% behind this project. We couldn’t have done it without them!

How many software engineers worked on the project?
Purely on the AdSense applications, we have a team of close to 100. Around 25% of them write Dart.

How many lines of code?
We have around 160K LO…

A stronger Dart for everyone

We are constantly asking ourselves:
How do we make developers even more productive when writing Dart apps? We believe that a critical part of the answer to this question is to make strongmode – a sound static type system for Dart – the standard for all Dart developers.

Teams that use Dart to build apps like Soundtrap, AdWords, AdSense, and Greentea say they really enjoy using strong mode features, such as early error detection. In fact, teams that have switched completely to strong mode cite not only early error detection but also better code readability and maintainability as major benefits. We hear this both from small teams and – even more so – from large teams with hundreds of developers writing and maintaining millions of lines of Dart code. As Björn Sperber from Soundtrap says,
Strong mode and the smooth integration with IntelliJ is a joy to use and a huge improvement. If you’ve tried out Flutter, you’ve already used strong mode checks from the Dart analyzer.

Given the benefits …