Sort alphabetically everything you can
Why
Say you have a class like this, and you add comment
field:
Then someone else adds title
field in another branch, and your merge looks like this:
It can’t go automatically, as the two branches modified the same lines. This is because when things are not sorted, everyone adds everything to the end.
If instead you added comment
before description
, then… I can’t even show you the dialog of an easy merge, because the editor did the merge without asking anything:
What Else to Sort
This goes for:
- Class properties.
- Named arguments when calling functions.
- Named arguments at declaration. Required and non-required ones are sorted separately, required ones go first.
- References to the named arguments in doc comments.
- Enum constants at declaration and in switch.
- Map entries.
- Constants per group if you separate groups by blank lines.
- Imports.
- YAML, JSON and other map equivalents.
- Calls to
Object.hash
. - Everything else if the order does not impact the semantics.
Exceptions
Understanding
Note that the list above is not sorted alphabetically. It goes from common to rare things as this is better for understanding. Same applies to:
- Positional arguments.
— Most important ones should go first.
— Things like.range(start, end)
should putstart
beforeend
— Hinted arguments should follow the order likeEdgeInsets.fromLTRB(…)
If the order is not obvious, use named arguments. - Class methods. You usually sort them so that methods above invoke methods below, because this is better for the readers.
- Local variables if you don’t have many.
- Generic type parameters. You put the most important ones first.
- Name, description, and version in
pubspec.yaml
,package.json
and others (but not the dependency lists in them).
Special Items
- ID field.
- Widget
key
field. none
inenum
, if you have one.
They stand out. They need to be first to assure they are there. They raise questions if they are not first.
If the Order Matters
You don’t sort like that:
- Maps that are iterated in an expected order.
- Columns in a table, as their order affects speed.
- Variables initialized from one another.
- Arrays that aim to have the most used items first for faster search.
- Runtime imports like in PHP.
- Tests of variables in
&&
and||
chains because you can benefit from short circuit evaluation.
A Natural Order
If things have a natural order, and so people will not add new items to the end, keep that order:
const xs = 10;
const s = 20;
const m = 30;
const l = 40;
const xl = 50;
Long Items
In Flutter, widget’s child
and children
properties are usually the longest ones because they may construct entire inline trees. So it’s recommended to put them last.
Lints to help
Many languages have lints to force some of the rules here. In Dart, you have:
directives_ordering
to sort imports.sort_pub_dependencies
to sort dependencies inpubspec.yaml
.combinators_ordering
to sortimport … show A, B, C;
sort_unnamed_constructors_first
to sort unnamed constructors before other constructors.sort_child_properties_last
to sortchild
andchildren
last.
Read this on how to set up lints in a Dart project so that GitHub tells you if you break a rule.
How to Add to an Unsorted List
Suppose you need to add keyed_collection_widgets
package to the list:
dependencies:
flutter: { sdk: flutter }
flutter_svg: ^0.22.0
provider: ^6.0.0
code_text_field: ^1.0.0
url_launcher: ^6.0.12
expansion_widget: ^0.0.2
Maybe you cannot reorder the list right away because many people will suffer. Then you:
- Locate the first item out of order and consider the list sorted up till there:
dependencies:
flutter: { sdk: flutter } # sorted
flutter_svg: ^0.22.0 # sorted
provider: ^6.0.0 # sorted
code_text_field: ^1.0.0 # first violation, unsorted below
url_launcher: ^6.0.12
expansion_widget: ^0.0.2
2. Add to that sorted part:
dependencies:
flutter: { sdk: flutter }
flutter_svg: ^0.22.0
keyed_collection_widgets: ^0.3.2 # added
provider: ^6.0.0
code_text_field: ^1.0.0
url_launcher: ^6.0.12
expansion_widget: ^0.0.2
3. Give a hint for others to sort the rest as they change it. Depending on the syntax of the file, it can be a blank line, a blank line with TODO or something like that:
dependencies:
flutter: { sdk: flutter }
flutter_svg: ^0.22.0
keyed_collection_widgets: ^0.3.2
provider: ^6.0.0 # TODO(alexey.inkin): Sort alphabetically to the sorted part above
code_text_field: ^1.0.0
url_launcher: ^6.0.12
expansion_widget: ^0.0.2