worldhopper/.serena/memories/code_style_and_conventions.md
2026-01-27 00:56:46 +01:00

3.5 KiB

Code Style and Conventions

Linting

  • Uses package:flutter_lints/flutter.yaml - Flutter's recommended lint rules
  • Configuration in analysis_options.yaml
  • Run linter: flutter analyze
  • All lints must pass before committing

Dart/Flutter Conventions

Naming

  • Classes/Enums/Typedefs: PascalCase (e.g., OPDSFeed, DatabaseHelper)
  • Variables/Functions/Parameters: camelCase (e.g., fetchFeed, serverId)
  • Private members: Prefix with underscore (e.g., _database, _authService)
  • Constants: lowerCamelCase for const variables (e.g., const defaultTimeout)
  • Files: snake_case (e.g., opds_service.dart, server_list_screen.dart)

Widget Construction

  • Use const constructors wherever possible for performance
  • Use super.key for widget keys
  • Mark widget fields as final
  • Prefer StatelessWidget over StatefulWidget when no state is needed
  • Use trailing commas for better formatting (especially in widget trees)

State Management - Riverpod

  • Use riverpod_annotation with code generation for providers
  • Provider files should have corresponding .g.dart files
  • Use @riverpod annotation for provider functions
  • Run flutter pub run build_runner build to generate provider code
  • Consume providers using ref.watch() in widgets (via ConsumerWidget or Consumer)
  • Use ref.read() for one-time reads in callbacks

Data Models - Freezed

  • All data models use Freezed for immutability
  • Include both .freezed.dart and .g.dart parts
  • Use @freezed annotation for models
  • Define fromJson factory for JSON deserialization
  • Private constructor pattern: const ModelName._();
  • Run flutter pub run build_runner build to generate model code

Database Patterns

  • Singleton pattern for DatabaseHelper (DatabaseHelper.instance)
  • Table definitions as static constants in table classes
  • Use foreign key constraints
  • Repository pattern for data access
  • All database operations should be async

Service Layer

  • Services are injectable via constructor parameters
  • Default implementations provided with null coalescing
  • Use Dio for HTTP operations with proper error handling
  • Parser services are separate from network services

Code Structure

  • Imports: Organize as package imports, relative imports, then part files
  • Theme: Uses Material 3 (useMaterial3: true)
  • Documentation: Use /// for public API documentation comments
  • Regular comments: Use // for implementation comments
  • Debug output: Use debugPrint() instead of print()

Type Annotations

  • Prefer explicit types for public APIs and class fields
  • Type inference acceptable for local variables when obvious
  • Always specify return types for functions and methods

Error Handling

  • Use try-catch for async operations that may fail
  • Provide meaningful error messages
  • Handle HTTP errors appropriately
  • Log errors with debugPrint() for debugging

Authentication

  • Credentials stored encrypted in SQLite
  • Authentication handled via AuthService
  • Dio clients created per-server with auth configuration

File Organization

  • Group related functionality in directories (screens, services, models, etc.)
  • Keep widget files focused on single widgets or screens
  • Extract reusable widgets to lib/widgets/
  • Screen-specific widgets can go in screens/<feature>/widgets/

Code Generation

Run code generation after modifying:

  • Models with @freezed annotation
  • Providers with @riverpod annotation
  • Models with @JsonSerializable annotation

Command: flutter pub run build_runner build --delete-conflicting-outputs