Install
$ agentstack add skill-python51888-studydart-skills-dart-effective-dart ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Writing Effective Dart Code
Contents
- [Style](#style-guidelines): naming, ordering, formatting
- [Documentation](#documentation-guidelines): doc comments structure and wording
- [Usage](#usage-guidelines): leveraging language features correctly
- [Design](#design-guidelines): API architecture and type safety
- [Workflow](#workflow-applying-effective-dart-to-your-code): step-by-step application with feedback loop
- [Examples](#examples-violation-vs-compliant-code): violation vs. compliant code
Style Guidelines
Naming
- Use
UpperCamelCasefor types (classes, enums, typedefs), extensions, and type parameters.
class SliderMenu {}, typedef Predicate = bool Function(T);
- Use
lowercase_with_underscoresfor packages, directories, source files, and import prefixes.
my_package/lib/file_system.dart, import 'dart:math' as math;
- Use
lowerCamelCasefor variables, methods, parameters, and constants (including enum values).
var itemCount = 3;, const defaultTimeout = 1000;
- Capitalize acronyms/abbreviations longer than two letters as regular words:
Http,Uri.
Two‑letter acronyms keep their English capitalization: IO, UI. When they start a lowerCamelCase identifier, make them all lowercase: var httpConnection = ...;.
- Don’t use a leading underscore for non‑private identifiers.
- Don’t use Hungarian notation or prefix letters.
- Don’t explicitly name libraries (legacy
library my_library;is discouraged). - Prefer wildcard
_for unused callback parameters (Dart ≥3.7).
Ordering
- Place
dart:imports first, thenpackage:imports, then relative imports. - Put
exportdirectives in a separate section after all imports. - Sort each section alphabetically.
Formatting
- Run
dart formaton every file before committing. - Keep lines to 80 characters or fewer; break long expressions manually if needed.
- Always use curly braces for flow control structures (one‑line
ifwithoutelseis the only exception).
Documentation Guidelines
- Use
///(C# style) for documentation comments, not/** */. - Write doc comments for all public APIs. Consider library‑level doc comments and private member documentation.
- Start every doc comment with a single‑sentence summary, separated from the rest by a blank line.
- For side‑effect‑centric functions/methods: begin with a third‑person verb.
/// Deletes the file at [path] from the file system.
- For non‑boolean properties/variables: use a noun phrase.
/// The number of checked buttons on the page.
- For boolean properties/variables: start with “Whether” followed by a noun or gerund phrase.
/// Whether the modal is currently displayed to the user.
- For methods that return a value (conceptually like a property): use a noun phrase or non‑imperative verb phrase.
/// The [index]th element of this iterable.
- For library/class comments: start with a noun phrase describing the instance or entity.
- Don’t document both getter and setter; document the property once on the getter.
- Include inline code samples using fenced code blocks with
`dart. - Use square brackets
[identifier]to link to in‑scope identifiers (classes, methods, fields). - Explain parameters, return values, and exceptions in prose, not with formal
@paramtags. Put doc comments before metadata annotations. - Prefer brevity; avoid abbreviations unless they are obvious; use “this” instead of “the” to refer to the instance.
Usage Guidelines
Null safety
- Don’t explicitly initialize variables to
null. - Don’t use explicit default
nullfor optional parameters. - Don’t write
if (bool == true); useif (bool). For nullable booleans, useif (nullableBool ?? false)orif (b != null && b). - Avoid
latevariables if you need to check initialization; use a nullable field and testnullinstead. - Use type promotion or null‑check patterns to safely unwrap nullable types. Prefer private
finalfields for promotion.
Strings
- Concatenate adjacent string literals without
+. - Prefer interpolation:
'Hello, $name!'over'Hello, ' + name + '!'. - Omit curly braces in interpolation when the expression is a simple identifier.
Collections
- Use collection literals (
[],{},{}) instead of constructors likeList(),Map(). - Use
.isEmpty/.isNotEmptyinstead of.length == 0. - Avoid
Iterable.forEach()with a function literal; use afor‑in loop unless the function already exists (e.g.,forEach(print)). - Use
toList()to copy an iterable; reserveList.from()for changing the element type. - Use
whereType()to filter by type; avoidwhere((e) => e is T).cast(). - Avoid
cast(); prefer creating a properly typed collection, casting elements on access, or usingList.from().
Functions
- Bind a name with a function declaration (
void localFunc() { ... }) instead of assigning a lambda to a variable. - Use tear‑offs instead of wrapping a method in an unnecessary lambda:
charCodes.forEach(print); not (code) { print(code); }.
Variables
- Choose a consistent rule for
varvsfinalon local variables and stick to it throughout the project. - Prefer computing values on demand (via getters) instead of caching them in extra fields, unless profiling proves a performance problem.
Members
- Don’t wrap a public field in a trivial getter/setter; expose the field directly.
- Use
finalfields to make read‑only properties. - Use
=>for single‑expression members; avoid deep nesting. - Don’t write
this.except to avoid shadowing (parameter and field have the same name) or to redirect a named constructor. - Initialize fields at their declaration whenever the value does not depend on constructor arguments.
Constructors
- Use initializing formals (
Point(this.x, this.y);). - Prefer constructor initializer lists over
latefields. - Use
;instead of{}for empty constructor bodies. - Don’t use
new(it’s optional and unnecessary). - Don’t redundantly add
constin a constant context (collection literal, const constructor call, switch case expression, etc.).
Error handling
- Catch errors only with
onclauses that specify the expected type. - Never silently swallow exceptions; always log, handle, or rethrow.
- Throw objects that implement
Erroronly for programmatic bugs; throwExceptionfor runtime failures. - Don’t explicitly catch
Error; let them propagate. - Use
rethrowto preserve the original stack trace.
Asynchrony
- Prefer
async/awaitover rawFuture.then()chains. - Don’t add
asyncwhen the function body just returns a future and never usesawait. - Use higher‑order methods on streams (
map,where, etc.) instead of manual listeners. - Avoid
Completer; useasync/awaitorFuture.then()instead. - When testing a
FutureOrwhereTcould beObject, test forFutureto disambiguate.
Design Guidelines
Names
- Use terms consistently across the API.
- Place the most descriptive noun last (
pageCount,ConversionSink). - Name non‑boolean properties/variables with noun phrases (
list.length). - Name boolean properties/variables with non‑imperative verb phrases (
isEmpty,hasElements). - For named boolean parameters, consider omitting the verb (
paused: false). - Prefer the positive form for booleans (
isConnectedoverisDisconnected). - Name side‑effecting methods with imperative verb phrases (
list.add(),window.refresh()). - Avoid starting a method name with
get; use getters or choose a more descriptive verb. - Name conversion methods
to___()(creates a new object) oras___()(different representation backed by original). - Follow mnemonic conventions for type parameters:
Efor element,K/Vfor key/value,T/S/Uotherwise. - Don’t embed parameter descriptions in method names.
Libraries
- Make declarations private (prepend
_) unless they are intended as public API. - It’s fine to define multiple related classes in the same library (class‑level privacy is library‑scoped).
Classes and mixins
- Don’t define a single‑member abstract class when a plain function (
typedef) suffices. - Don’t define a class that contains only static members; use top‑level functions/variables instead.
- Don’t extend or implement a class that isn’t explicitly designed for it; respect
final,base,interface,sealedmodifiers. - Use class modifiers to communicate intent (e.g.,
final class,base class). - Prefer pure
mixinor pureclassovermixin classin new code.
Constructors
- Make the constructor
constif all fields arefinaland the constructor does no work beyond initialization.
Members
- Prefer
finalfor fields and top‑level variables unless the value must change. - Use getters for operations that conceptually access a property (no arguments, no visible side effects, consistent result).
- Use setters for operations that conceptually change a property (one argument, idempotent).
- Don’t define a setter without a corresponding getter.
- Avoid faking overloading with runtime type tests; define separate methods for different types if callers usually know which operation they want.
- Avoid public
late finalfields without initializers; they unintentionally expose a setter. - Never return a nullable
Future,Stream, or collection type. Return an empty container or a future of a nullable type. - Don’t return
thisfrom methods just to enable a fluent interface; use cascades (..).
Types
- Type annotate variables without initializers.
- Annotate fields and top‑level variables if the type isn’t obvious from the initializer.
- Don’t redundantly annotate initialized local variables; let inference work.
- Annotate return types and parameter types on function declarations.
- Don’t annotate function expression parameters when they are inferred.
- Don’t type annotate initializing formals (
this.x). - Write type arguments on generic invocations only when not inferred from context.
- Avoid incomplete generic types (
Listwithout<>); write the full typeList. - Use
dynamicexplicitly when inference would fail and you actually wantdynamic. - In function type annotations, prefer full signatures:
bool Function(String)over justFunction. - Don’t specify a return type for a setter.
- Use the modern
typedefsyntax (typedef Comparison = int Function(T, T);). - Prefer inline function types over a
typedefunless the type is lengthy or reused often. - Use
Futurefor async methods that return no value. - Avoid
FutureOras a return type; useFutureand keep the function consistently async. (In contravariant positions, like a callback parameter, it is acceptable.)
Parameters
- Avoid positional boolean parameters; use named parameters or named constructors.
- Avoid optional positional parameters when callers may want to skip earlier ones; use named parameters instead.
- Don’t force callers to pass a special “no value” like
null; make the parameter optional. - Use inclusive‑start, exclusive‑end parameters for ranges (consistent with
substring,sublist).
Equality
- Override
hashCodewhenever you override==. - Ensure
==is reflexive, symmetric, and transitive. - Avoid custom equality for mutable classes.
- The parameter of
==must be non‑nullable (Object), notObject?.
Workflow: Applying Effective Dart to Your Code
Task Progress
- [ ] 1. Format codebase
- [ ] 2. Audit naming conventions
- [ ] 3. Add/improve documentation
- [ ] 4. Refactor usage patterns
- [ ] 5. Review API design
- [ ] 6. Run static analysis and tests
- [ ] 7. Final review and merge
Step 1: Format the codebase
Run dart format lib/ test/ on the project directory. If the output shows changes, then review them to ensure logic is unaffected.
Step 2: Audit naming conventions
Check each identifier:
- If a type/extension/typedef name is not
UpperCamelCase, then rename it. - If a file/directory/package/import prefix uses underscores incorrectly, then rename to
lowercase_with_underscores. - If a variable, method, or constant uses
SCREAMING_CAPSin new code, then convert tolowerCamelCase. - If an acronym longer than two letters is all‑caps, then follow the capitalization rule.
- If there are unused callback parameters named anything other than
_(in local anonymous functions), then replace with_.
Step 3: Add/improve documentation
For every public declaration (class, mixin, extension, top‑level function/variable, enum, method, getter, setter):
- If no doc comment exists, then add
///with a one‑sentence summary. - If the member is a side‑effecting function, then start with a third‑person verb (
/// Deletes ...). - If the member is a non‑boolean property/getter, then start with a noun phrase.
- If the member is boolean, then start with “Whether”.
- If the documentation is redundant with the name or repeats obvious context, then remove or rewrite to explain what the reader doesn’t know.
- If a code example would clarify usage, then include a fenced ```
dartblock. - If any referenced identifier exists in scope, then surround it with
[ ]brackets. - If there are
@paramor@returnstags, then rewrite them as prose.
Step 4: Refactor usage patterns
Search the codebase for anti‑patterns and replace:
new Type()→Type()(removenew)const const ...→ singleconstor remove entirely where context is constant.if (b == true)→if (b);if (b == false)→if (!b).var list = List.empty()→var list = [].collection.length == 0→collection.isEmpty.collection.where((e) => e is T).cast()→collection.whereType().var foo = () { ... };→void foo() { ... }for named local functions.predicate.forEach((e) => f(e))→predicate.forEach(f)(tear‑off).list = list.cast()→List.from(list)if the whole list is needed.- Unnecessary
this.(except for shadowing and constructor redirection) → remove it. StringBuffer(); buffer.write(...)with cascade →StringBuffer()..write(...).return Future.value(...)in anasyncfunction that does nothing else → removeasyncand return the future directly, or keepasynconly if necessary.- Direct
Completerusage → rewrite withasync/await.
Step 5: Review API design
Examine class and function signatures:
- If a class has only static members, then convert to top‑level functions/variables (unless grouping constants like
Color). - If an abstract class has a single abstract method, then replace it with a
typedef. - If a public field is mutable but should logically be read‑only, then make it
final. - If a getter does work that is heavy or has side effects, then consider converting to a method with a verb name.
- If a method returns
nullfor a collection/future/stream, then change to return an empty collection or a future of a nullable value; document accordingly. - If boolean parameters are positional, then convert to named parameters.
- If optional positional parameters force callers to pass a placeholder to reach a later argument, then switch to named optional parameters.
- If
==is overridden withouthashCode, then add ahashCodeoverride that obeys the contract.
Step 6: Run static analysis and tests
Execute dart analyze and dart test. If the analyzer reports warnings/errors, then fix them, focusing first on potential violations of the rules above. If tests fail after refactoring, then revert the smallest possible chang
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: Python51888
- Source: Python51888/StudyDart-Skills
- License: BSD-3-Clause
- Homepage: https://zread.ai/Python51888/StudyDart-Skills
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.