Effective Dart
- Be consistent. When it comes to things like formatting, and casing,arguments about which is better are subjective and impossible to resolve.What we do know is that being consistent is objectively helpful.
If two pieces of code look different it should be because they _are_different in some meaningful way. When a bit of code stands out and catchesyour eye, it should do so for a useful reason.
- Be brief. Dart was designed to be familiar, so it inherits many of thesame statements and expressions as C, Java, JavaScript and other languages.But we created Dart because there is a lot of room to improve on what thoselanguages offer. We added a bunch of features, from string interpolation toinitializing formals, to help you express your intent more simply andeasily.
If there are multiple ways to say something, you should generally pick themost concise one. This is not to say you should code golf yourself intocramming a whole program into a single line. The goal is code that iseconomical, not dense.
The Dart analyzer has a linter to help you write good, consistent code.If a linter rule exists that can help you follow a guideline,then the guideline links to that rule. Here’s an example:
Linter rule:
For help onenabling linter rules,see the documentation for.
We split the guidelines into a few separate pages for easy digestion:
Style Guide – This defines the rules for laying out andorganizing code, or at least the parts that doesn’t handle foryou. The style guide also specifies how identifiers are formatted:,
using_underscores
, etc.Documentation Guide – This tells you everything you need toknow about what goes inside comments. Both doc comments and regular,run-of-the-mill code comments.
– This teaches you how to make the best use oflanguage features to implement behavior. If it’s in a statement orexpression, it’s covered here.
Design Guide – This is the softest guide, but the onewith the widest scope. It covers what we’ve learned about designingconsistent, usable APIs for libraries. If it’s in a type signature ordeclaration, this goes over it.
For links to all the guidelines, see the.
Each guide is broken into a few sections. Sections contain a list of guidelines.Each guideline starts with one of these words:
DO guidelines describe practices that should always be followed. Therewill almost never be a valid reason to stray from them.
DON’T guidelines are the converse: things that are almost never a goodidea. Hopefully, we don’t have as many of these as other languages do becausewe have less historical baggage.
PREFER guidelines are practices that you should follow. However, theremay be circumstances where it makes sense to do otherwise. Just make sure youunderstand the full implications of ignoring the guideline when you do.
AVOID guidelines are the dual to “prefer”: stuff you shouldn’t do butwhere there may be good reasons to on rare occasions.
Some guidelines describe an exception where the rule does not apply. Whenlisted, the exceptions may not be exhaustive—you might still need to useyour judgement on other cases.
This sounds like the police are going to beat down your door if you don’t haveyour laces tied correctly. Things aren’t that bad. Most of the guidelines hereare common sense and we’re all reasonable people. The goal, as always, is nice,readable and maintainable code.
To keep the guidelines brief, we use a few shorthand terms to refer to differentDart constructs.
A library member is a top-level field, getter, setter, or function.Basically, anything at the top level that isn’t a type.
A class member is a constructor, field, getter, setter, function, oroperator declared inside a class. Class members can be instance or static,abstract or concrete.
A member is either a library member or a class member.
A variable, when used generally, refers to top-level variables,parameters, and local variables. It doesn’t include static or instance fields.
A type is any named type declaration: a class, typedef, or enum.
A property is a top-level variable, getter (inside a class or at the toplevel, instance or static), setter (same), or field (instance or static).Roughly any “field-like” named construct.
Identifiers
- DO name types using
UpperCamelCase
. - DO name libraries, packages, directories, and source files using
lowercase_with_underscores
. - DO name other identifiers using
lowerCamelCase
. - DO capitalize acronyms and abbreviations longer than two letters like words.
- DON’T use prefix letters.
Ordering
- DO place “package:” imports before relative imports.
- DO specify exports in a separate section after all imports.
Formatting
Comments
Doc comments
- DO use
///
doc comments to document members and types. - CONSIDER writing a library-level doc comment.
- DO start doc comments with a single-sentence summary.
- AVOID redundancy with the surrounding context.
- PREFER starting library or type comments with noun phrases.
- DO use square brackets in doc comments to refer to in-scope identifiers.
- DO put doc comments before metadata annotations.
Markdown
Writing
Booleans
Strings
Collections
- DO use collection literals when possible.
- CONSIDER using higher-order methods to transform a sequence.
- DON’T use
List.from()
unless you intend to change the type of the result. - DON’T use
cast()
when a nearby operation will do.
Functions
Parameters
Variables
Members
- DON’T wrap a field in a getter and setter unnecessarily.
- CONSIDER using
=>
for simple members. - DO initialize fields at their declaration when possible.
Constructors
Error handling
- AVOID catches without
on
clauses. - DO throw objects that implement
Error
only for programmatic errors. - DO use
rethrow
to rethrow a caught exception.
Asynchrony
Names
- DO use terms consistently.
- CONSIDER making the code read like a sentence.
- PREFER a non-imperative verb phrase for a boolean property or variable.
- PREFER the “positive” name for a boolean property or variable.
- PREFER a noun phrase or non-imperative verb phrase for a function or method if returning a value is its primary purpose.
- AVOID starting a method name with .
- PREFER naming a method
as_()
if it returns a different representation backed by the original object. - DO follow existing mnemonic conventions when naming type parameters.
Libraries
Classes and mixins
- AVOID defining a class that contains only static members.
- DO document if your class supports being extended.
- DO document if your class supports being used as an interface.
- AVOID mixing in a type that isn’t intended to be a mixin.
Constructors
Members
- PREFER making fields and top-level variables
final
. - DO use setters for operations that conceptually change properties.
- AVOID returning
null
from members whose return type isbool
,double
,int
, ornum
.
Types
- PREFER type annotating public fields and top-level variables if the type isn’t obvious.
- AVOID type annotating initialized local variables.
- AVOID redundant type arguments on generic invocations.
- PREFER annotating with
dynamic
instead of letting inference fail. - DON’T specify a return type for a setter.
- PREFER inline function types over typedefs.
- DO annotate with
Object
instead ofdynamic
to indicate any object is allowed. - AVOID using
FutureOr<T>
as a return type.
- AVOID optional positional parameters if the user may want to omit earlier parameters.
- DO use inclusive start and exclusive end parameters to accept a range.
Equality
- DO make your
==
operator obey the mathematical rules of equality. - DON’T check for in custom
==
operators.