Skip to content

App Flow | Style Guide

Linting Rules

The project's linting setup incorporates Flutter's official recommended rules from Flutter Lints to ensure best practices for Flutter development.

Beyond these, custom linting rules are applied based on the 'Strict' rules from the Lint package, following the configuration in strict.yaml.

Additionally, since the project uses Riverpod, Riverpod Lint is included to enforce rules specific to Riverpod usage.

Line Length

Following Flutter's official recommendation, we enforce a soft limit of 80 characters per line to improve readability.

Exceeding this limit often indicates overly long statements or excessive nesting. To improve clarity, we recommend breaking down long statements with variables and extracting nested widgets where appropriate.

However, recent and ongoing discussions are reconsidering the 80-character convention as the standard. For more information, see Issue #833 on Dart Format (dartfmt) and Linus Torvalds' statement on the 80-character limit. Based on this and internal preferences the limit may increase to 100 characters in the future.

Naming Conventions

We adhere to Flutter's recommended identifier naming scheme: Effective Dart: Style.

File Naming

Library, package, directory and source file name's should be defined in lower_snake_case.

lib/my_utils/calculator_service.dart

Class Members

Use lowerCamelCase for all class members, including variables, constants, functions/methods and parameters.

class Car {
  final String modelName;           // Variable (constant)
  int year;                         // Variable
  void startEngine() {}             // Method
  Car({this.modelName, this.year}); // Constructor parameters
}

Classes, Types and Extensions

Classes, Types and Extensions should be defined in UpperCamelCase.

// Class
class CarService {
}

// Type Definition
typedef StringCallback = void Function(String); 

// Extension
extension StringExtensions on String {
  bool get isNullOrEmpty => this == null || isEmpty;
}

File Structure

We use a Feature-First file structure inspired by Andrea Bizzotto’s article: Flutter Project Structure: Feature-first or Layer-first?

Key Principles

  • Feature-Centric Folders: For every new feature, create a dedicated folder. Within each feature folder, organize related layers (e.g., models, views, controllers) as sub-folders.
  • Defining a Feature: A feature is defined not by what a user sees but rather by what a user does.

This structure enhances modularity, maintainability, and focus on user actions within the app’s architecture.

‣ lib
  ‣ src
    ‣ features
      ‣ feature1
        ‣ presentation
        ‣ application
        ‣ domain
        ‣ data
      ‣ feature2
        ‣ presentation
        ‣ application
        ‣ domain
        ‣ data
‣ lib
  ‣ src
    ‣ presentation
      ‣ feature1
      ‣ feature2
    ‣ application
      ‣ feature1
      ‣ feature2
    ‣ domain
      ‣ feature1
      ‣ feature2
    ‣ data
      ‣ feature1
      ‣ feature2

Advantages of Feature-First vs Layer-First

  • Whenever we want to add a new feature or modify an existing one, we can focus on just one folder.
  • If we want to delete a feature, there's only one folder to remove (two if we count the corresponding tests folder)