This document outlines the standards and best practices for Dart development at Bayat.
- Follow the official Dart Style Guide
- Use
dart format
or the Flutter/Dart IDE formatter with default settings - Maximum line length should be 80 characters
- Use 2 spaces for indentation, not tabs
- Files should be encoded in UTF-8
- Files should end with a newline
-
Classes, Enums, Typedefs, and Extensions:
- Use UpperCamelCase (e.g.,
HttpRequest
,UserRepository
) - Be descriptive and avoid abbreviations
- For extensions, name them based on what they add or the type they extend (e.g.,
StringExtension
)
- Use UpperCamelCase (e.g.,
-
Libraries, Packages, Directories, and Source Files:
- Use lowercase_with_underscores (e.g.,
dart_style
,user_repository.dart
) - Make file names match the primary class or functionality they contain
- Prefix library names with the package name for public libraries
- Use lowercase_with_underscores (e.g.,
-
Variables, Constants, and Parameters:
- Use lowerCamelCase for variables and parameters (e.g.,
itemCount
,userName
) - Use descriptive names that reflect the purpose
- For boolean variables, consider using prefixes like
is
,has
, orshould
(e.g.,isEnabled
)
- Use lowerCamelCase for variables and parameters (e.g.,
-
Private Members:
- Use a leading underscore for private members (e.g.,
_privateField
,_privateMethod()
) - Follow the same casing conventions otherwise (lowerCamelCase)
- Use a leading underscore for private members (e.g.,
-
Constants:
- Use lowerCamelCase for constant variables (e.g.,
const pi = 3.14
) - Static and top-level constants follow the same naming convention
- Use lowerCamelCase for constant variables (e.g.,
-
File Structure:
- One primary class, enum, or mixin per file
- Group related functionality in the same directory
- Follow the standard Dart project structure:
lib/ # Main package code src/ # Implementation code [module_name]/ # Feature-specific modules test/ # Test files bin/ # Executable files
-
Import Directives Order:
- Dart SDK imports first
- Package imports next
- Relative imports last
- Within each group, sort imports alphabetically
- Add a blank line between each import group
- Example:
import 'dart:async'; import 'dart:math'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../models/user.dart'; import 'utils.dart';
-
Code Comments:
- Use
///
for documentation comments (dartdoc) - Use
//
for implementation comments - Write comments in complete sentences with proper grammar
- Document all public APIs
- Use
-
Class and Member Documentation:
- Document the purpose of all public classes, methods, and properties
- Specify parameter types, return values, and thrown exceptions
- Use Markdown syntax within documentation comments
- Example:
/// Returns a [User] object with the given ID. /// /// Throws a [NotFoundException] if the user is not found. /// /// Parameters: /// - [id] The unique identifier for the user User getUserById(String id) { ... }
-
Type Safety:
- All new code should use sound null safety
- Minimize the use of nullable types (
Type?
) - Use late variables only when initialization is guaranteed
-
Handling Null Values:
- Use the null-aware operators (
?.
,??
,??=
,!
) appropriately - Avoid using the
!
operator when possible - Consider using
if (value != null)
checks over the!
operator for clarity
- Use the null-aware operators (
-
Exceptions:
- Define custom exception classes for specific error cases
- Use
try/catch
blocks for exceptional conditions, not for control flow - Propagate exceptions to appropriate layers
- Avoid catching general
Exception
types; catch specific exceptions
-
Async Code:
- Always handle errors in async code either with try/catch or
.catchError()
- Ensure
Future
chains have proper error handling - Consider using
async
/await
for improved readability
- Always handle errors in async code either with try/catch or
-
Recommended Approaches:
- For Flutter applications:
- Use Provider, Riverpod, Bloc/Cubit, or Redux depending on project complexity
- Use StatefulWidget when the state is local to a single widget
- Document the state management approach in project README
- For Flutter applications:
-
Best Practices:
- Separate business logic from UI code
- Keep state immutable when possible
- Minimize the scope of state
-
Unit Tests:
- Aim for high test coverage of business logic
- Use the
test
package for Dart code andflutter_test
for Flutter code - Structure tests using
group
andtest
functions - Use descriptive test names that describe the behavior being tested
-
Mock Objects:
- Use the
mockito
package ormocktail
for mocks - Create mock classes for external dependencies
- Use the
-
Widget Tests (for Flutter):
- Test widget rendering and behavior
- Test user interactions
-
Integration Tests:
- Implement integration tests for critical user flows
- Use
integration_test
package for Flutter applications
-
General Guidelines:
- Avoid expensive operations in the UI thread
- Use asynchronous operations for potentially long-running tasks
- Optimize list rendering by using appropriate widgets (e.g., ListView.builder)
- Minimize rebuilds by using const constructors where appropriate
-
Memory Management:
- Close streams when they're no longer needed
- Dispose controllers and other resources in the
dispose
method - Be careful of memory leaks due to closures that capture objects
-
Measurement and Profiling:
- Use the Dart DevTools for profiling and debugging
- Establish performance benchmarks for critical code paths
- Measure performance changes when optimizing code
-
Dependency Management:
- Specify version constraints in pubspec.yaml
- Prefer using caret syntax (
^
) for version constraints - Document the purpose of all dependencies
- Keep dependencies up to date
-
Package Selection:
- Prefer established packages with good documentation and support
- Evaluate package quality, maintenance, and community support
- Consider licensing and compatibility
- Balance functionality with package size
-
Data Security:
- Use secure storage solutions for sensitive data (e.g.,
flutter_secure_storage
) - Never hard-code sensitive information such as API keys
- Use environment-specific configurations for different environments
- Use secure storage solutions for sensitive data (e.g.,
-
Code Security:
- Validate all user inputs
- Sanitize data from external sources
- Use HTTPS for network communications
- Implement proper authentication and authorization
-
Internationalization (i18n):
- Use the
intl
package for internationalization - Externalize user-facing strings
- Support right-to-left (RTL) layouts
- Use the
-
Accessibility:
- Ensure proper contrast ratios for text
- Provide appropriate semantic labels for UI elements
- Support screen readers with semantic labels
- Test with accessibility tools
-
Commit Guidelines:
- Follow the project's commit message format
- Make atomic commits that represent a logical change
- Verify that the code compiles and tests pass before committing
-
Pull Requests:
- Include descriptive titles and descriptions
- Reference related issues in descriptions
- Keep PRs focused on a single issue or feature
- Recommended Practices:
- Run static analysis (
dart analyze
) in CI - Execute all tests in CI
- Automate build and deployment processes
- Use code coverage tools to maintain or improve test coverage
- Run static analysis (