origin

As the core gene of a research and development team, how to effectively inherit the code specification in the team is a challenge. Flutter, as a new framework for mobile applications, is attracting more and more developers to enter the field. However, faced with a completely new technical framework and the dart language, how to write properly Flutter code has puzzled countless Flutter learners. This article focuses on some of the practices that the Idle Fish Flutter team did with respect to the underlying code specification.

Flutter static code scan

Native developers all know that Android/iOS have a matching Linter check mechanism. Developers can use Linter checks to unify code styles and check for obvious flaws in their code. The Flutter can do the same. Linter checking is the easiest and most efficient way to unify your code style.

Flutter Linter mechanism

The mechanism of the Flutter Linter check is rooted in the Dart Linter check, while at the same time doing a lot of functional expansion. The Linter rules for Flutter are recorded in the analysis_options.yaml file in the project level directory. You can customize this file to get code rules that are appropriate for your team.

The Flutter Linter rules all belong to three main sets:

1.ERROR

Rules identify errors that may occur in code

2.Style

Rules identify code style issues

3.Pub

Rules identify problems related to the management of Flutter packages

It is important to note that stability is considered in a real development scenario. When adjusting Linter rules, you need to pay attention to the maturity of the rules. The main maturity levels currently include:

  • Stable Stable –
  • Experimental – An Experimental rule that can be unstable
  • Deprecated – a rule that is no longer recommended and Deprecated

A common Linter rule set

1.effective_dart

Effective_dart Indicates the Linter rule supported by dart. The rules come from the Effective Dart documentation. This document contains various specifications for efficient use of the Dart language. Effective_dart [2] is old and deprecated.

2.pedantic

Google’s internal collection of DART development specifications. It is now abandoned.

3.flutter_lints

Is a set of Flutter rules recommended by the Flutter team. Recommended use of Flutter apps, packages, and plugins. Is itself an extended version of the DART Recommended Rule set. This specification affects the score of the package published in pub.dev[5].

4.lints[6]

The rule set recommended by the Dart team. A core consists of two subsets: Core & Recommended.

The choice of idle fish norms

Of all the Liner rules, it can be a challenge to choose one that fits your team’s needs. In the process of making idle fish, some basic principles are followed.

Be concise

In the case of semantic equivalence, the advanced syntax of the DART language is fully utilized to reduce the complexity of the expression. Conciseness not only improves your coding efficiency, it also improves your code reading efficiency. A few examples:

  • 【 necessary_new】

There is a lot of code in the idle fish code base that uses the new keyword for class initialization. On the one hand, idle fish entered into Flutter earlier and had historical burden. It is also because the client students have carried the coding habits of other languages (such as Java) into Flutter. Although there are a lot of changes to be made, for the sake of simplicity, we still firmly add this rule.

  • Prefer_conditional_assignment, prefer_null_aware_operators

Dart syntax has a lot of syntax sugar for null handling, which can greatly improve null-detection efficiency and robustness of code. This includes? Judgment,?? And null safety. It is necessary to continuously guide the students in the team to use more such syntax to improve efficiency, rather than continue to use the miscellaneous expression of if else.

To reduce ambiguity

The code presentation needs to be accurate and as consistent as possible between students. Reduce the “think” outside the code and increase the “sure” between the lines. Typical examples are as follows:

  • Explicit variable types [always_specify_types]

There was a big disagreement among students with different technology stack backgrounds in the team about whether to specify variable types. Students with front-end background tend to name variables by inference, which is good for concise expression. The background of the client tends to be directly and clearly defined, which is intuitive and reduces unnecessary inference. Finally, after a heated discussion, we decided to use the explicit variable type scheme. From a practical point of view, the direct definition of variable types is slightly complicated in terms of expression, but it is indeed less ambiguous.

  • Annotate_overrides, prefer_const_declarations, prefer_final_fields

If a variable or method is overridden, specify the override annotation. If a variable is determined to be const, use the const keyword. A variable that has not been assigned a value is defined as final. Adhere to minimize the expression, has the following benefits:

  • Minimized variable state expression can accurately describe variable state

Minimizing the state of a variable means describing the variable with the strictest attributes. For example, if a variable is assigned at one place instead of multiple places, it can be assigned at one place. So the variable actually has the final invisible property. Minimal state representation requires that the final keyword be included, not final inferred. If the final keyword is added, subsequent assignments will report an error. This reduces unnecessary understanding costs and minimizes invisible changes in variable states.

  • Improving code performance

The addition of the final const keyword allows the compiler to do more optimization and improve the overall performance of the code.

Style is consistent

In a multiplayer team, everyone has their own preferences. Code management should avoid the “broken window effect.” One person wrote bad code, the students in the back to write bad. As they say, nothing can be accomplished without rules. The expression of basic code does not pursue absolute right and wrong, but as unified as possible in style. Here are too many examples:

1. Naming conventions generally follow the hump pattern [camel_case_types, non_constant_identifier_names, constant_identifier_names]

2. Use curly braces as much as possible in control flow [curly_braces_IN_FLOW_control_structures] 3. Import modules according to dart reference, package reference, and relative reference. [Directives_ordering] 4. Always_put_required_named_parameters_first 5. Use SizedBox instead of Container in the flutter layout. 6. Flutter color definition Use_full_HEX_values_for_flutter_colors is an 8-bit hexadecimal integer. 7 Widget adds the key argument to the constructor [use_KEY_IN_widget_constructors]

There is no reason why any of these should be so. But when you’re writing code, you have to follow this specification. For nothing but the unity of style, in order to improve the efficiency of business rotation of the team.

The code quality

Another important goal of Linter inspection is to find potential code defects. This is even more important for code management, because it is directly related to the overall stability. Stability is the bottom line for developers, and you can’t be too careful. Here are also some typical examples:

1. Avoid void_checks

2. Check the types before comparing variables [unrelated_type_equality_checks]

3. Avoid “catch” “empty_catch”

4. Avoid_shadowing_type_parameters

5. Avoid await non-future objects

List_remove_unrelated_type = list_remove_unrelated_type

If the problematic code is brought into production, it can cause exceptions or functionality to become unavailable. Nip them in the bud and deal with them at the beginning of the code to make it more robust.

Maintenance costs

Efficiency is important to a team, but it is shortsighted to pursue efficiency in a moment rather than overall efficiency throughout the code lifecycle. We are increasingly concerned today with the cost of maintaining code in the future. For this reason, documentation & comments are becoming more and more important. A good comment saves a lot of questions, a lot of trial and error, a lot of doubt. Constantly guiding people to write and maintain documentation and comments is the explicit goal of the Idle Fish code specification. A few clear examples:

1.Deprecated functions need to be explicitly commented [provide_deprecation_message]

2. Variable references in comments that comply with the reference constraints [comment_references]

Rules of the authority

The formulation of the Liner rules of the Idle Fish team is not a single opinion. All students in the team were invited to participate in the rule-making process. The authority of a rule comes from the heartfelt approval of all its practitioners. Take a typical example:

When discussing standard formatting, the team members focused on one rule:

[-lines_longer_than_80_chars # dispute rule, each line length should not exceed 80 characters]

Everyone agrees on the importance of a uniform formatting code style. At issue: 80 characters is too short on many high-resolution monitors. This leads to a lot of unnecessary line breaks, which detracts from the code reading experience. We listened to the feedback of the development students and removed the specification. Change to a unified Android Studio configuration. The final standard is a 12 character line with a maximum of 160 characters.

Write in the last

Of course, just doing the above part is only the first step in the long march. In the case of basic code specifications, we are not looking for rules as much as we are looking for the actual efficiency benefits of rules. In the process of making rules, we listened to the real feedback of the developers and deleted many unnecessary rules. Simplicity, efficiency, not specification for specification sake is our core goal. Of course, we should try our best to ensure the implementation of the final rules. At present, we are actively building a more perfect CI system and standardizing it. Through continuous rapid testing, real-time feedback to users, reduce the cost of specification implementation. Code is the core asset of the r&d team, and we need to protect it together.

The appendix

If the details of the rules described above are unclear, you can find a more detailed explanation in the links below. linter-rules[7]

Idle fish core Liner rules

Attached are the core Liner rules of idle fish for your reference. named The sorting formatting comments Library use NULL string A collection of function

Member variables The constructor Exception handling Mixin type parameter The quality of The fusion part of Core collection Recommended collection fusion section The Flutter gathers the fusion part Other rule fusion parts