Dart Style Guide
This guide offers comprehensive insights into writing idiomatic, clean, and maintainable Dart code, aligning with Dart's conventions and best practices.
Foundational Code Standards provide the foundation, this guide extends them for Dart.
Formatting
The formatting rules for Dart adhere to our foundational formatting standards:
- Consistent Indentation: Use 2 spaces for indentation, 4 spaces for continuation lines.
- Line Length: Aim for 100 characters, but allow flexibility for readability.
- Whitespace: Use spaces around operators, parentheses, braces, colons, commas, and keywords.
- Brace Style: Follow K&R style (opening brace on same line, closing brace on new line).
- Blank Lines: Use 1 line to separate code sections.
- Alignment: Align elements in documentation comments and parameter lists.
Naming Conventions
Dart employs specific naming conventions to enhance readability and maintain consistency:
- PascalCase for classes, enum types, and type parameters.
- snake_case for libraries, packages, directories, and source files.
- camelCase for functions, variables, properties.
- Prefix booleans with
is
orhas
for clarity.
- Prefix booleans with
- camelCase for functions, variables, constants, and parameters.
- Prefix global constants with a lowercase
k
beforeCamelCase
.
- Prefix global constants with a lowercase
Example
/**
* This class demonstrates proper code formatting following the specified style guide.
*
* **Formatting Rules:**
* - 2 spaces for indentation (Dart standard).
* - Max line length of 100 characters.
* - Spaces around operators, control structures, and keywords.
* - K&R brace style.
* - Consistent spacing for parameter lists and constructor arguments.
* - Doc comments with aligned descriptions.
*/
class WellFormattedCode { // (1)!
/**
* This method calculates the factorial of a given positive integer.
*
* @param n The non-negative integer for which to calculate the factorial.
* @return The factorial of n, or throws an ArgumentError if n is negative.
* @throws ArgumentError If the provided number (n) is negative.
*/
int calculateFactorial(int n) { // (2)!
if (n < 0) { // (3)!
throw ArgumentError('Factorial is not defined for negative numbers.');
}
int result = 1;
for (int i = 2; i <= n; i++) { // (4)!
result *= i;
}
return result;
}
}
- Class name in PascalCase with a doc comment.
- Method name in camelCase with a doc comment.
- K&R brace style for blocks.
- Proper spacing around operators and control structures.
Commenting and Documentation
DartDoc
Use DartDoc to document public APIs. Comments should be clear and concise, providing valuable insights into the code's purpose and usage.
Inline Comments
-
Use Sparingly: Inline comments should clarify complex algorithms, decisions not immediately obvious, or provide context not readily apparent from the code itself.
Documentation Comments
-
Use
///
for Public APIs: Document classes, methods, variables, and parameters using Dart’s///
syntax. This aids consumers of your code and supports Dart's documentation generation tools. -
Describe Parameters and Return Types: For methods and functions, describe each parameter and the return type. Use square brackets
[]
around parameter names to link them within generated docs.
Keeping Comments Up-to-Date
- Reflect Code Changes: Ensure comments are updated with code changes. Outdated comments can mislead and confuse, diminishing code quality.
TODO Comments
-
Track Future Enhancements with Ticket Numbers: Use
TODO:
comments to mark areas of the code requiring further work, including a brief description and a ticket number for tracking.
Avoid Commented-Out Code
-
Remove, Don’t Comment-Out: Commented-out code can clutter your codebase. Remove code that's no longer needed or store it elsewhere if it might be useful later.
Idioms and Best Practices
Effective Dart Guidelines
Adhere to the Effective Dart Guidelines for tips on writing clear, idiomatic Dart code.
Error Handling
-
Use
try-catch
for Exception Handling: Leverage Dart's exception handling features to gracefully handle errors and exceptions. Provide clear feedback or recovery options when possible.
Type Annotations
-
Prefer Type Annotations in Public APIs: While Dart supports type inference, explicitly annotating types in public APIs and complex code enhances clarity and ensures that your intentions are clear.
Immutable Collections
-
Favor Immutability for Collections: When collections are not meant to change, use Dart’s built-in support for immutable collections to prevent accidental or unintended modifications.
Avoiding Global Mutable State
-
Minimize Use of Global State: Global mutable state can lead to code that is hard to reason about and debug. Prefer passing objects explicitly through function parameters or using dependency injection.
Using final
and const
-
Prefer
final
andconst
Where Possible: Usefinal
for variables that you only want to assign once, andconst
for compile-time constants. This practice enhances the predictability and safety of your code.
Asynchronous Programming
-
Embrace Asynchronous Programming: Dart’s
async
andawait
keywords facilitate writing asynchronous code that is clean, straightforward, and maintainable.
Leveraging Extensions
-
Use Extensions to Add Functionality: Dart’s extension methods allow you to add functionality to existing classes without modifying them or creating subclasses, keeping your codebase flexible and clean.
Leveraging Null Safety
-
Make Use of Null Safety Features: Dart’s sound null safety is designed to eliminate null dereference errors. Use nullable types (
?
) and default values to ensure your code is more predictable and safe.
Effective Use of Collections
-
Utilize Collection Literals: Dart supports list, map, and set literals. Use these for creating collections more succinctly and readably.
Functional Programming Patterns
-
Embrace Functional Programming Constructs: Take advantage of Dart’s support for first-class functions and higher-order functions to write cleaner and more expressive code.
Extension Methods
-
Extend Existing Classes: Use extension methods to add functionality to existing classes without modifying them or creating subclasses, keeping your codebase flexible and modular.
Cascades
-
Use Cascades to Chain Operations: Dart’s cascade (
..
) operator allows you to perform a sequence of operations on the same object. This can make your code more fluent and less verbose.
Asynchronous Programming
-
Prefer async/await Over Futures: Use
async
andawait
for handling asynchronous operations to write code that is clean, simple, and easy to understand.
Using Generics
- Generics for Type Safety and Flexibility: Use generics to write flexible and reusable code
-
components while maintaining type safety.
Adopting these Dart-specific idioms and patterns not only enhances code readability and efficiency but also ensures that your Dart codebase is robust, maintainable, and idiomatic. This approach leverages Dart’s full potential to create high-quality applications.
Tools and Resources
Setting up a productive development environment is crucial for Dart developers. This section guides on configuring tools and Integrated Development Environments (IDEs) to enhance productivity, ensure code quality, and align with Dart style guidelines.
IDE Support
Visual Studio Code (VS Code)
-
Extensions: Install the Dart and Flutter (if using Flutter) extensions from the VS Code marketplace to get syntax highlighting, code completion, and debug support.
-
Format on Save: Enable "Format On Save" to automatically format your code according to Dart's formatting rules. Go to Settings → search for "Format On Save" → check the box.
-
Problem View: Use the Problems tab to quickly navigate and address issues identified by the Dart analyzer.
IntelliJ IDEA / Android Studio
-
Dart and Flutter Plugins: Install the Dart and Flutter plugins via Preferences → Plugins. These provide comprehensive Dart support, including syntax highlighting, code completion, and debugging.
-
Code Style Configuration: Configure Dart formatting in Preferences → Editor → Code Style → Dart. You can adjust settings to match your team’s style guide.
-
Dart Analysis: Use the Dart Analysis window to view and navigate to issues in your codebase. Customize analysis options with
analysis_options.yaml
.
Formatting Tools
- dart format: Use the
dart format
command to automatically format your Dart code. Integrate this command into your version control pre-commit hooks to ensure consistent formatting.
Linting
- Effective Dart: Use the linter package to enforce Dart best practices. Customize your
analysis_options.yaml
to enable preferred lint rules.
Dependency Management
- Pub: Use Dart’s package manager, pub, to manage dependencies. Regularly update your dependencies to get the latest features and security updates.
dartfmt
Utilize dartfmt
to automatically format your code, ensuring consistency with Dart's style guide.
Dart Analyzer
Use the Dart Analyzer to identify potential code issues, including syntax errors, type issues, and deprecated API usage.
Linter
Incorporate Dart Linter in your project to detect additional stylistic discrepancies and potential problems.
Additional Resources
- Dart Language Tour: Offers a comprehensive overview of Dart's features and syntax.
- Dart Effective Dart: Provides a set of guides for styling, authoring, and using Dart effectively.