Flutter π¦
Development Environment
Code Editor
There is no specific editor is enforced at the team level. Flutter developers can pick what they are comfortable with but also what does not hinder their productivity.
The following options are the most widely used:
In addition, this will be needed:
- Xcode for iOS code inspection and editing.
Version Management
Due to the diversity of projects the team works on, each application usually requires different versions of Flutter. Version management allows developers to install and switch between different versions effortlessly.
- fvm is the recommended version management for Flutter.
Project Structure
Generally speaking, a Flutter application can include multi-platforms codebase structure as a cross-platform framework. So itβs important to follow the corresponding project structure when it comes to a specific platform, for instance:
The following structure and directories must be followed for the core Flutter directories (lib/
):
{project_name}
βββ android/
βββ ios/
βββ web/
βββ assets/
βββ lib/
β βββ app/
β β βββ resources/
β β βββ routes/
β β βββ screens/
β β β βββ home/
β β β βββ ...
β β βββ widgets/
β βββ di/
β β βββ interceptors/
β β βββ authenticators/
β β βββ modules/
β β βββ providers/
β β βββ di.dart
β βββ data/
β β βββ local/
β β β βββ models/
β β β βββ storages/
β β β βββ preferences/
β β βββ remote/
β β β βββ datasources/
β β β βββ models/
β β β βββ requests/
β β β βββ responses/
β β βββ repositories/
β βββ domain/
β β βββ exceptions/
β β βββ models/
β β βββ usecases/
β βββ l10n/
β βββ utils (helpers)/
β βββ main.dart
βββ integration_test/
βββ test/
β βββ app/
β βββ data/
β βββ domain/
βββ pubspec.yaml
-
android/
,ios/
(alsoweb/
,macos/
, orwindows/
): contains all the platform-specific configurations corresponding to Android, iOS, web, or desktop compilation. -
assets
: static assets (images, videos, fontsβ¦) included for the application to use at the compile time. -
lib
: the core logic and presentation for the whole Flutter application. Following Clean Architecture with MVVM, the lib folder includes 3 main layers:app
(presentation),data
, anddomain
. -
test
: contains all the unit test suites for each layer. -
integration_test
: contains all the integration test suites. -
pubspec.yaml
: specifies dependencies that the project requires, such as particular packages (and their versions), fonts, or assets files (images, videoβ¦).
Exclusion of Generated Files
The team follows βWhat not to commitβ documentation to not include most of the files that the IDE, code editor, pub tool, and other tools generate. This also includes these various generated file extensions:
*.g.dart
*.gen.dart
*.config.dart
*.freezed.dart
*.mocks.dart
etc...
Excluding them benefits the team to:
- LinearB with substantial code changes from gen code.Avoid wrong statistics from
-
-
Hence, a code generator is necessary for local development or CI:
$ flutter packages pub run build_runner build --delete-conflicting-outputs
Formatting
Methods
- Use soft-tabs with a two-space indent. For more indentation and spacing rules, follow the
-
-
Separate each abstract method using a blank line for better readability.
abstract class Human { void speak(); void run(); }
-
-
- Use the line break before each parameter in a method when it exceeds the line length.
-
Always use a line break for the method with more than two parameters.
void createAccount(String firstName, String lastName, String email, String phoneNumber) { // Your code }
void createAccount( String firstName, String lastName, String email, String phoneNumber, ) { // Your code }
-
Commas: Prefer to add a trailing comma
,
when there are more than 2 parameters in a method for auto-formatting in VSCode or Android Studio. This applies to Widget also.void setReminder({String? label, DateTime? datetime, bool? enableSnooze}) { // Your code }
void setReminder({ String? label, DateTime? datetime, bool? enableSnooze, }) { // Your code }
-
-
required
: should be at the same line as the parameters.void disableButton({ required Widget button, required Color color, })
void disableButton({ required Widget button, required Color color, })
-
Comments
- Comment should follow the
Widgets
-
Add
const
before the widget whenever possible. By adding this keyword, the constant widget is NOT re-rendered when rebuilding the parent widget, improving the application performance. Read further in this article The Flutter const keyword demystified.Center( child: const Text('Hello World!'), );
-
Prefer to split the code into small widgets to avoid
large nested trees
. The debugging process will become easy for checking the UI issue. Besides, the widget tree is readable and clean. This could be flexible when creating a widget class or a function that returns a widget.Scaffold( body: Column( children: [ // The Header Container( child: Stack( children: [ Column( children: [ Row( children: [ Column( children: [ Container( // A child ), ], ), ], ), Container( // A child ), ], ), ], ), ), // The Body Expanded( child: Row( children: [ Column( children: [ Row( children: [ ListTile( leading: Column( children: [ Container( // A child ), ], ), ), ], ), Container( // A child ), ], ), ], ), ), // The Footer Expanded( child: Column( children: [ Row( children: [ Container( // A child ), Container( // A child ), ], ), ], ), ), ], ), );
Scaffold( body: Column( children: [ _buildHeaderWidget(), BodyWidget(), FooterWidget(), ], ), ); Widget _buildHeaderWidget() { return Container( // The Header ); } class BodyWidget extends StatelessWidget { ... } class FooterWidget extends StatelessWidget { ... }
Naming
The standardized naming conventions from Effective Dart style are used and respected by the team, with a minor exception as outlined in the following guideline.
-
Capitalize acronyms and abbreviations no matter the length of letters.
class HTTPRequest {} class DBIOPort {} class TVVcr {}
class HttpRequest {} class DbIoPort {} class TvVcr {}
Assets & Resources
-
All resources must follow the basic resource naming principle:
-
<WHAT>
indicates what the resource actually represents - optionally, mostly for images. -
<WHERE>
describes where it logically belongs in the app - optionally, common resources could omit this part; all others use the custom part of the screen/feature they are in. -
<DESCRIPTION>
differentiates multiple elements in one screen/feature. -
<SIZE>
is either a precise size or size bucket - optionally used for images and dimensions.
-
-
Resources in the
assets
folder must follow the snake_case format in their names. -
Resources in the
lib
folder must be defined as constants and follow Dartβs naming conventions for constants.
Images
-
assets
folder. -
Images naming must follow the basic resource naming principle above. The
<WHAT>
part for images is the type such as:-
Icon
images start with anic_
prefix. -
Background
images start with abg_
prefix. - The rest starts with an
img_
prefix.
close.svg selected_home_tab.svg splashBackground.png empty_image.png
ic_close.svg ic_tab_home_selected.svg bg_splash.png img_empty.png
-
Colors
-
lib
folder. -
Colors naming must follow the basic resource naming principle above.
static const Color Blue700 = Color(0xFF004370); static const Color button_main = Blue700; static const Color contentBackgroundColor = Colors.white;
static const Color blue700 = Color(0xFF004370); static const Color buttonPrimaryBackground = blue700; static const Color contentBackground = Colors.white;
Dimensions
-
lib
folder. -
Dimensions naming must follow the basic resource naming principle above.
static const double spacing12 = 12; static const double spacingXX = 16; static const double spacingXXX = 24; static const double date_picker_height_200 = 200;
static const double spacingSmall = 12; static const double spacingMedium = 16; static const double spacingLarge = 24; static const double datePickerHeight = 200;
Localization
- l10n as a main localization.The team uses
-
.arb
files should follow the pattern{feature}{optionalWidgetName}{stringType}
and use camelCase format. For example:-
loginTitle
:login
is afeature
, andtitle
is astringType
. Thereβs only one title forlogin
, so thereβs no need to specifywidgetName
. -
loginPhoneNumberTitle
: This string looks similar to the above string, but this string is for thePhoneNumber
field. To differentiate from other titles,PhoneNumber
is specified as awidgetName
. -
errorInvalidPassword
: In this case,error
is a special type offeature
, andInvalidPassword
is astringType
.
-
-
feature
types can be named according to the application features list.
Package Id
-
-
application id
is used for an Android application, iOS applications call itbundle identifier
.- A valid
application id
allows alphanumeric characters, periods (.
), and underscores (_
). Read more about Application Id. - A valid
bundle identifier
allows alphanumeric characters, periods (.
), and hyphens (-
). Read more about CFBundleIdentifier.
- A valid