To learn about the next Flutter and Dart coding standards?

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/weixin_44339238/article/details/100019578

dart official document [Effective Dart]

Specification is divided into four parts:

  • Style specifications
  • Document specification
  • Terms of Use
  • Design Specification

Each section has a number of examples, each example will in the following five words as some of the beginning:

  • DO : You need to follow the practice of representation
  • DONT : represents this approach is very bad
  • PREFER : In most cases, the recommended practice
  • AVOID : In most cases, the practice should be avoided
  • CONSIDER : you need to practice discretion

In my opinion, coding habits are personal, and no such thing as the best solution.

If you are a person develop, of course, we do not need to care about these issues, but if your code needs to show to others, or if you need to develop synergies with others, coding standards it is very necessary.

The following will be selected from the official document, the most basic, the most typical, a higher incidence in some cases, as a specification.

✅ expressed positive approach, ❌ represents the opposite approach

Style specifications

name

DO: class, enumeration, type definitions, as well as generic, require the use of capital at the start hump nomenclature

class SliderMenu { ... }

class HttpRequest { ... }

typedef Predicate<T> = bool Function(T value);

In use annotations, it should be like this



class Foo {
  const Foo([arg]);
}

@Foo(anArg)
class A { ... }

@Foo()
class B { ... }

But when a class constructor add annotations, you may need to create a lowercase beginning of the comment variables



const foo = Foo();

@foo
class C { ... }

DO: Naming library package, directory, dart files should be lowercase underlined



library peg_parser.source_scanner;

import 'file_system.dart';
import 'slider_menu.dart';


library pegparser.SourceScanner;

import 'file-system.dart';
import 'SliderMenu.dart';

DO: Use as a reference to the name of the conversion should also be underlined lowercase



import 'dart:math' as math;
import 'package:angular_components/angular_components'
    as angular_components;
import 'package:js/js.dart' as js;


import 'dart:math' as Math;
import 'package:angular_components/angular_components'
    as angularComponents;
import 'package:js/js.dart' as JS;

DO: variable name, method, parameter names should be lowercase beginning of the hump nomenclature



var item;

HttpRequest httpRequest;

void align(bool clearItems) {
  // ...
}


const pi = 3.14;
const defaultTimeout = 1000;
final urlScheme = RegExp('^([a-z]+):');

class Dice {
  static final numberGenerator = Random();
}


const PI = 3.14;
const DefaultTimeout = 1000;
final URL_SCHEME = RegExp('^([a-z]+):');

class Dice {
  static final NUMBER_GENERATOR = Random();
}

curly braces

DO: Only when a statement and if there is no else, and can be a good show in a row, you can not braces



if (arg == null) return defaultValue;

However, if one line to show more reluctant, then you need to use the braces:



if (overflowChars != other.overflowChars) {
  return overflowChars < other.overflowChars;
}


if (overflowChars != other.overflowChars)
  return overflowChars < other.overflowChars;

Document specification

DO: In the comments dart, the more recommended to use /// instead of //



/// The number of characters in this chunk when unsplit.
int get length => ...


// The number of characters in this chunk when unsplit.
int get length => ...

As for why, the official said that due to historical reasons and they feel that in some cases seem easier to read.

DO: Doc comments should begin with a simple word



/// Deletes the file at [path] from the file system.
void delete(String path) {
  ...
}


/// Depending on the state of the file system and the user's permissions,
/// certain operations may or may not be possible. If there is no file at
/// [path] or it can't be accessed, this function throws either [IOError]
/// or [PermissionError], respectively. Otherwise, this deletes the file.
void delete(String path) {
  ...
}

DO: The first sentence of the comments and other content separates



/// Deletes the file at [path].
///
/// Throws an [IOError] if the file could not be found. Throws a
/// [PermissionError] if the file is present but could not be deleted.
void delete(String path) {
  ...
}


/// Deletes the file at [path]. Throws an [IOError] if the file could not
/// be found. Throws a [PermissionError] if the file is present but could
/// not be deleted.
void delete(String path) {
  ...
}

DO: Use square brackets to declare parameters, return values, and exceptions thrown



/// Defines a flag with the given name and abbreviation.
///
/// @param name The name of the flag.
/// @param abbr The abbreviation for the flag.
/// @returns The new flag.
/// @throws ArgumentError If there is already an option with
///     the given name or abbreviation.
Flag addFlag(String name, String abbr) => ...


/// Defines a flag.
///
/// Throws an [ArgumentError] if there is already an option named [name] or
/// there is already an option using abbreviation [abbr]. Returns the new flag.
Flag addFlag(String name, String abbr) => ...

Terms of Use

rely

PREFER: recommended to use a relative path to import dependence

If the project is structured as follows:

my_package
└─ lib
   ├─ src
   │  └─ utils.dart
   └─ api.dart

Want to import utils.dart in api.dart in



import 'src/utils.dart';


import 'package:my_package/src/utils.dart';

Assignment

** DO: Use null values ​​?? will do a conversion **

In the dart will represent operator ?? ?? behind it a value when a data value is blank



if (optionalThing?.isEnabled) {
  print("Have enabled thing.");
}

When optionalThing is empty, the above will be a null pointer anomaly.

Explain here. ?. Operators equivalent of doing a sentence air operation only when optionalThing not empty when the only call isEnabled parameters, when optionalThing is empty, then default returns null, if used in determining the sentence to die naturally

Here's the right approach



// 如果为空的时候你想返回false的话:
optionalThing?.isEnabled ?? false;

// 如果为空的时候你想返回ture的话:
optionalThing?.isEnabled ?? true;


optionalThing?.isEnabled == true;

optionalThing?.isEnabled == false;

String

In the dart is not recommended to use two strings are connected to +

DO: Use directly the Enter key partition string



raiseAlarm(
    'ERROR: Parts of the spaceship are on fire. Other '
    'parts are overrun by martians. Unclear which are which.')


raiseAlarm('ERROR: Parts of the spaceship are on fire. Other ' +
    'parts are overrun by martians. Unclear which are which.');

PREFER: $ {} is connected using the variable value string



'Hello, $name! You are ${year - birth} years old.';


'Hello, ' + name + '! You are ' + (year - birth).toString() + ' y...';

set

dart create an empty Extensible List two ways: [] and List (); Create an empty HashMap three ways: {}, the Map (), and a LinkedHashMap ()

If you want to create a non-expandable list or some other custom collection types, so be sure to use the constructor.

DO: create a collection using a simple literal as possible



var points = [];
var addresses = {};


var points = List();
var addresses = Map();

When you want to specify the type of



var points = <Point>[];
var addresses = <String, Address>{};


var points = List<Point>();
var addresses = Map<String, Address>();

DO NOT: Do not use the .lenght to represent a set is empty



if (lunchBox.isEmpty) return 'so hungry...';
if (words.isNotEmpty) return words.join(' ');


if (lunchBox.length == 0) return 'so hungry...';
if (!words.isEmpty) return words.join(' ');

CONSIDER: Consider using higher-order conversion method sequence

var aquaticNames = animals
    .where((animal) => animal.isAquatic)
    .map((animal) => animal.name);

AVOID: Avoid using Iterable.forEach functions with literals ()

forEach () function is widely used in JavaScript, because the built-for-in loop can not achieve the effect you usually want. In Dart, if you want iterative sequence, then the conventional method is to use a loop.



for (var person in people) {
  ...
}


people.forEach((person) {
  ...
});

DO NOT: Do not use List.from () unless you plan to change the type of results

There are two ways to get Iterable, respectively List.from () and Iterable.toList ()



// 创建一个List<int>:
var iterable = [1, 2, 3];

// 输出"List<int>":
print(iterable.toList().runtimeType);


// 创建一个List<int>:
var iterable = [1, 2, 3];

// 输出"List<dynamic>":
print(List.from(iterable).runtimeType);

DO: Use WhereType () to set a filtered type



var objects = [1, "a", 2, "b", 3];
var ints = objects.where((e) => e is int);


var objects = [1, "a", 2, "b", 3];
var ints = objects.where((e) => e is int).cast<int>();


var objects = [1, "a", 2, "b", 3];
var ints = objects.whereType<int>();

parameter

DO: using a default value to the parameter setting =


void insert(Object item, {int at = 0}) { ... }


void insert(Object item, {int at: 0}) { ... }

DO NOT: Do not use the default value of the parameter is set to null



void error([String message]) {
  stderr.write(message ?? '\n');
}


void error([String message = null]) {
  stderr.write(message ?? '\n');
}

variable

AVOID: Avoid the calculated value can be stored



class Circle {
  num _radius;
  num get radius => _radius;
  set radius(num value) {
    _radius = value;
    _recalculate();
  }

  num _area;
  num get area => _area;

  num _circumference;
  num get circumference => _circumference;

  Circle(this._radius) {
    _recalculate();
  }

  void _recalculate() {
    _area = pi * _radius * _radius;
    _circumference = pi * 2.0 * _radius;
  }
}


class Circle {
  num radius;

  Circle(this.radius);

  num get area => pi * radius * radius;
  num get circumference => pi * 2.0 * radius;
}

member

DO NOT: Do not write unnecessary getter and setter



class Box {
  var contents;
}


class Box {
  var _contents;
  get contents => _contents;
  set contents(value) {
    _contents = value;
  }
}

Constructor

DO: Whenever possible, use a simple form initialization



class Point {
  num x, y;
  Point(num x, num y) {
    this.x = x;
    this.y = y;
  }
}


class Point {
  num x, y;
  Point(this.x, this.y);
}

DO NOT: Do not use new to create an object

dart does not require new



Widget build(BuildContext context) {
  return Row(
    children: [
      RaisedButton(
        child: Text('Increment'),
      ),
      Text('Click!'),
    ],
  );
}


Widget build(BuildContext context) {
  return new Row(
    children: [
      new RaisedButton(
        child: new Text('Increment'),
      ),
      new Text('Click!'),
    ],
  );
}

DO NOT: Do not use excess const modified objects



const primaryColors = [
  Color("red", [255, 0, 0]),
  Color("green", [0, 255, 0]),
  Color("blue", [0, 0, 255]),
];


const primaryColors = const [
  const Color("red", const [255, 0, 0]),
  const Color("green", const [0, 255, 0]),
  const Color("blue", const [0, 0, 255]),
];

Exception Handling

: Use rethrow rethrows



try {
  somethingRisky();
} catch (e) {
  if (!canHandle(e)) throw e;
  handle(e);
}


try {
  somethingRisky();
} catch (e) {
  if (!canHandle(e)) rethrow;
  handle(e);
}

design

AVOID: Avoid To achieve the streaming method to return this call and let



var buffer = StringBuffer()
  ..write('one')
  ..write('two')
  ..write('three');


var buffer = StringBuffer()
    .write('one')
    .write('two')
    .write('three');

AVOID: Avoid using FutureOr as the return type



Future<int> triple(FutureOr<int> value) async => (await value) * 3;


FutureOr<int> triple(FutureOr<int> value) {
  if (value is int) return value * 3;
  return (value as Future<int>).then((v) => v * 3);
}

AVOID: Avoid as an input parameter values ​​directly bool



new Task(true);
new Task(false);
new ListBox(false, true, true);
new Button(false);


Task.oneShot();
Task.repeating();
ListBox(scroll: true, showScrollbars: true);
Button(ButtonState.enabled);

DO NOT: Do not empty == operator sentenced method in a custom



class Person {
  final String name;
  // ···
  bool operator ==(other) => other is Person && name == other.name;

  int get hashCode => name.hashCode;
}


class Person {
  final String name;
  // ···
  bool operator ==(other) => other != null && ...
}

At last

If you think the article is well written give a praise chant? If you think there need to be improved, please give me a message. Will be serious inquiry, insufficiently corrected. Thank you.

I hope you can read this and look forward to share my future will update the technology of dry cargo, thank you for your support!

Here, I share the video and data from a philosophical level framework to analyze the share for everyone to sort out the many years of experience in architecture, nearly a month preparatory latest record, I believe that this video will give you a different inspiration, reward

image.png

Receive mode: Get a free bit architecture video material please me

+ + Forwarding thumbs attention, the first time to obtain the latest knowledge points

Android architects of the road is long, encourage each other with it!

Guess you like

Origin blog.csdn.net/weixin_44339238/article/details/100019578