This skill defines how to write idiomatic, high-quality Dart and Flutter code following Effective Dart guidelines.
| Kind | Convention | Example |
|---|---|---|
| Classes, enums, typedefs, type parameters, extensions | UpperCamelCase |
MyWidget, UserState |
| Packages, directories, source files | lowercase_with_underscores |
user_profile.dart |
| Import prefixes | lowercase_with_underscores |
import '...' as my_prefix; |
| Variables, parameters, named parameters, functions | lowerCamelCase |
userName, fetchData() |
HttpRequest, not HTTPRequest.E (element), K/V (key/value), T/S/U (generic types).final, sealed, interface, base, mixin) to control whether a class can be extended or implemented.dynamic instead of letting inference fail.Future<void> as the return type of async members that do not produce values.// Prefer: explicit class modifier
final class AppConfig {
final String apiUrl;
final int timeout;
const AppConfig({required this.apiUrl, required this.timeout});
}
// Prefer: sealed for exhaustive pattern matching
sealed class Result<T> {}
class Success<T> extends Result<T> { final T value; Success(this.value); }
class Failure<T> extends Result<T> { final Exception error; Failure(this.error); }
dart format .
dart format — don't manually format.final over var when variable values won't change.const for compile-time constants.src directory of another package.lib./lib/ or ../ in import paths.final.const if the class supports it.// Adjacent string concatenation (not +)
final greeting = 'Hello, '
'world!';
// Collection literals
final list = [1, 2, 3];
final map = {'key': 'value'};
// Initializing formals
class Point {
final double x, y;
Point(this.x, this.y);
}
// Empty constructor body
class Empty {
Empty(); // not Empty() {}
}
// rethrow to preserve stack trace
try {
doSomething();
} catch (e) {
log(e);
rethrow;
}
whereType<T>() to filter a collection by type.var and final on local variables.hashCode if you override ==; ensure == obeys mathematical equality rules.on SomeException catch (e) instead of broad catch (e) or .catchError handlers./// Returns the sum of [a] and [b].
///
/// Throws [ArgumentError] if either value is negative.
int add(int a, int b) { ... }
/// doc comments — not /* */ block comments — for types and members.[identifier] in doc comments to refer to in-scope identifiers.group and descriptive test names:import 'package:test/test.dart';
void main() {
group('CartService', () {
late CartService cart;
setUp(() => cart = CartService());
test('addItem increases item count', () {
cart.addItem(Product(id: '1', name: 'Widget', price: 9.99));
expect(cart.items, hasLength(1));
});
test('removeItem decreases total price', () {
final product = Product(id: '1', name: 'Widget', price: 9.99);
cart.addItem(product);
cart.removeItem(product.id);
expect(cart.totalPrice, equals(0.0));
});
});
}
testWidgets and WidgetTester:import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('LoginButton shows loading indicator when tapped',
(WidgetTester tester) async {
await tester.pumpWidget(const MaterialApp(home: LoginScreen()));
await tester.tap(find.byType(ElevatedButton));
await tester.pump();
expect(find.byType(CircularProgressIndicator), findsOneWidget);
});
}
When reviewing Dart code for Effective Dart compliance, the agent should check:
final, sealed, or interface is used where appropriate./// doc comments with a single-sentence summary.dart format --output=none --set-exit-if-changed . to verify formatting.dart analyze and confirm zero issues.