-
Notifications
You must be signed in to change notification settings - Fork 1
Coding Standard
A surprisingly important part of good code is good style. Consistent naming, ordering, and formatting helps code that is the same look the same. It takes advantage of the powerful pattern-matching hardware most of us have in our ocular systems. If we use a consistent style across the entire Dart ecosystem, it makes it easier for all of us to learn from and contribute to each others' code.
Identifiers come in three flavors in Dart:
- UpperCamelCase names capitalize the first letter of each word, including the first
- lowerCamelCase names capitalize the first letter of each word, except the first which is always lowercase, even if it's an acronym
-
lowercase_with_underscores names use only lowercase letters, even for acronyms, and separate words with
_
Linter rule: camel_case_types
Classes, enum types, typedefs, and type parameters should capitalize the first letter of each word (including the first word), and use no separators.
Good:
class SliderMenu {
// ...
}
class HttpRequest {
// ...
}
typedef Predicate<T> = bool Function(T value);This even includes classes intended to be used in metadata annotations:
Good:
class Foo {
const Foo([Object? arg]);
}
@Foo(anArg)
class A {
// ...
}
@Foo()
class B {
// ...
}For annotation classes with no parameters, create a separate lowerCamelCase constant:
Good:
const foo = Foo();
@foo
class C {
// ...
}Linter rule: camel_case_extensions
Good:
extension MyFancyList<T> on List<T> {
// ...
}
extension SmartIterable<T> on Iterable<T> {
// ...
}Linter rules: file_names, package_names
Good:
my_package
└─ lib
└─ file_system.dart
└─ slider_menu.dart
Bad:
mypackage
└─ lib
└─ file-system.dart
└─ SliderMenu.dart
Linter rule: library_prefixes
Good:
import 'dart:math' as math;
import 'package:angular_components/angular_components.dart' as angular_components;
import 'package:js/js.dart' as js;Bad:
import 'dart:math' as Math;
import 'package:angular_components/angular_components.dart' as angularComponents;
import 'package:js/js.dart' as JS;Linter rule: non_constant_identifier_names
Class members, top-level definitions, variables, parameters, and named parameters should capitalize the first letter of each word except the first word.
Good:
var count = 3;
HttpRequest httpRequest;
void align(bool clearItems) {
// ...
}Linter rule: constant_identifier_names
Good:
const pi = 3.14;
const defaultTimeout = 1000;
final urlScheme = RegExp('^([a-z]+):');
class Dice {
static final numberGenerator = Random();
}Bad:
const PI = 3.14;
const DefaultTimeout = 1000;
final URL_SCHEME = RegExp('^([a-z]+):');
class Dice {
static final NUMBER_GENERATOR = Random();
}Good:
// Longer than two letters, so always like a word:
Http // "hypertext transfer protocol"
Nasa // "national aeronautics and space administration"
Uri // "uniform resource identifier"
// Two letters, capitalized in English, so capitalized in an identifier:
ID // "identifier"
TV // "television"
UI // "user interface"
// Two letters, not capitalized in English, so like a word in an identifier:
Mr // "mister"
St // "street"
Rd // "road"When abbreviations come at the beginning of lowerCamelCase identifiers:
var httpConnection = connect();
var tvSet = Television();
var mrRogers = 'hello, neighbor';Good:
futureOfVoid.then((_) {
print('Operation complete.');
});
// Multiple unused parameters
.onError((_, _) {
print('Operation failed.');
});Dart uses leading underscores to mark private members. Don't use them for local variables, parameters, or library prefixes.
Good:
defaultTimeoutBad:
kDefaultTimeoutBad:
library my_library;Good:
/// A really great test library.
@TestOn('browser')
library;Linter rule: directives_ordering
To keep the preamble of your file tidy, follow this prescribed order with blank lines between sections:
Good:
import 'dart:async';
import 'dart:collection';
import 'package:bar/bar.dart';
import 'package:foo/foo.dart';Good:
import 'package:bar/bar.dart';
import 'package:foo/foo.dart';
import 'util.dart';Good:
import 'src/error.dart';
import 'src/foo_bar.dart';
export 'src/error.dart';Bad:
import 'src/error.dart';
export 'src/error.dart';
import 'src/foo_bar.dart';Good:
import 'package:bar/bar.dart';
import 'package:foo/foo.dart';
import 'foo.dart';
import 'foo/foo.dart';Use the official dart format tool for consistent whitespace handling. The remaining guidelines are for things the formatter cannot fix automatically.
When formatted output is hard to read:
- Shorten local variable names
- Hoist expressions into new local variables
- Simplify deeply nested expressions
- Consider shorter class names
Linter rule: lines_longer_than_80_chars
Long lines are harder to read. The main offender is usually very long class names.
Exceptions:
- URIs or file paths in comments or strings
- Multi-line strings where newlines are significant
Linter rule: curly_braces_in_flow_control_structures
Good:
if (isWeekDay) {
print('Bike to work!');
} else {
print('Go dancing or read a book!');
}Exception: Single-line if statements without else can omit braces:
Good:
if (arg == null) return defaultValue;If the body wraps to the next line, use braces:
Good:
if (overflowChars != other.overflowChars) {
return overflowChars < other.overflowChars;
}Bad:
if (overflowChars != other.overflowChars)
return overflowChars < other.overflowChars;Following these coding standards ensures:
- Consistency across the codebase
- Readability for all team members
- Maintainability over time
- Tool compatibility with Dart analyzers and formatters
Remember to use dart format and enable the relevant linter rules in your analysis_options.yaml file to automatically enforce these standards.