Привет, если вы на пути изучения Flutter/Dart или вам просто интересно почитать про путь изучения, подписывайтесь на мой канал в telegram, буду рад вас видеть! А сегодня поговорим про руководство по стилю в Dart!
Содержание:
DO имена пакетов, каталогов и исходных файлов, используя lowercase_with_underscores
DO имена import префиксов с использованием lowercase_with_underscores
DO используйте заглавные буквы в аббревиатурах и сокращениях длиной более двух букв
PREFER используя _, __ и т.д. для неиспользуемых параметров обратного вызова
DON’T не используйте начальное подчеркивание для идентификаторов, которые не являются частными
CONSIDER подумайте об изменении своего кода, чтобы сделать его более удобным для форматирования
DO используйте фигурные скобки для всех операторов управления потоком
Удивительно важной частью хорошего кода является хороший стиль. Согласованное присвоение имен, упорядочение и форматирование помогают одинаковому коду выглядеть одинаково. В нем используются преимущества мощного аппаратного обеспечения для сопоставления с образцом, которое есть у большинства из нас в наших зрительных системах. Если мы используем единый стиль во всей экосистеме Dart, всем нам будет легче учиться на коде друг друга и вносить свой вклад в него.
Идентификаторы
Идентификаторы в Dart бывают трех видов.
В названиях
UpperCamelCase
заглавными буквами пишутся первые буквы каждого слова, включая первую.В названиях
lowerCamelCase
заглавными буквами пишется первая буква каждого слова, за исключением первой, которая всегда пишется строчными буквами, даже если это аббревиатура.в именах
lowercase_with_underscores
используются только строчные буквы, даже для сокращений, и разделяются слова символом _.
DO типы имен используя UpperCamelCase
Правило Линтера: camel_case_types
Классы, enum типы, typedefs и параметры типа должны содержать заглавную букву каждого слова (включая первое слово) и не использовать разделителей.
?хорошо
class SliderMenu { ... }
class HttpRequest { ... }
typedef Predicate<T> = bool Function(T value);
Это даже включает классы, предназначенные для использования в аннотациях к метаданным.
?хорошо
class Foo {
const Foo([Object? arg]);
}
@Foo(anArg)
class A { ... }
@Foo()
class B { ... }
Если конструктор класса аннотаций не принимает параметров, вы можете захотеть создать для него отдельную константу lowerCamelCase.
?хорошо
const foo = Foo();
@foo
class C { ... }
DO расширения имен, используя UpperCamelCase
Правило Линтер: camel_case_extensions
Как и в типах, в расширениях первая буква каждого слова должна быть заглавной (включая первое слово) и не использовать разделителей.
?хорошо
extension MyFancyList<T> on List<T> { ... }
extension SmartIterable<T> on Iterable<T> { ... }
DO имена пакетов, каталогов и исходных файлов, используя lowercase_with_underscores
Правила Линтер: file_names, package_names
Некоторые файловые системы не учитывают регистр, поэтому во многих проектах требуется, чтобы все имена файлов были строчными. Использование разделительного символа позволяет именам оставаться читаемыми в таком виде. Использование подчеркивания в качестве разделителя гарантирует, что имя по-прежнему является допустимым идентификатором Dart, что может быть полезно, если язык позже поддержит символьный импорт.
?хорошо
my_package
└─ lib
└─ file_system.dart
└─ slider_menu.dart
?плохо
mypackage
└─ lib
└─ file-system.dart
└─ SliderMenu.dart
DO имена import префиксов с использованием lowercase_with_underscores
Правило Линтер: library_prefixes
?хорошо
import 'dart:math' as math;
import 'package:angular_components/angular_components.dart' as angular_components;
import 'package:js/js.dart' as js;
?плохо
import 'dart:math' as Math;
import 'package:angular_components/angular_components.dart' as angularComponents;
import 'package:js/js.dart' as JS;
DO именуйте другие идентификаторы, используя lowerCamelCase
Правило Линтер: non_constant_identifier_names
Члены класса, определения верхнего уровня, переменные, параметры и именованные параметры должны начинаться с заглавной буквы каждого слова, за исключением первого слова, и не использовать разделителей.
?хорошо
var count = 3;
HttpRequest httpRequest;
void align(bool clearItems) {
// ...
}
PREFER используйте lowerCamelCase для имен констант
Правило Линтер: constant_identifier_names
В новом коде используйте lowerCamelCase
для постоянных переменных, включая значения перечисления.
?хорошо
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();
}
Вы можете использовать SCREAMING_CAPS
для согласования с существующим кодом, как в следующих случаях:
При добавлении кода в файл или библиотеку, в которых уже используется
SCREAMING_CAPS
.При генерации кода Dart, параллельного коду Java, например, в перечисляемых типах, сгенерированных из protobufs.
⚠️ Изначально мы использовали стиль Java SCREAMING_CAPS
для констант. Мы изменили его по нескольким причинам:
SCREAMING_CAPS
во многих случаях выглядит плохо, особенно перечислимые значения для таких вещей, как цвета CSS.Константы часто заменяются конечными неконстантными переменными, что потребовало бы изменения имени.
Свойство
values
, автоматически определяемое для типа enum, имеет значение const и нижний регистр.
DO используйте заглавные буквы в аббревиатурах и сокращениях длиной более двух букв
Аббревиатуры с заглавной буквы могут быть трудночитаемыми, а несколько соседних аббревиатур могут привести к неоднозначным названиям. Например, учитывая имя, начинающееся с HTTPSFTP
, невозможно определить, относится ли оно к HTTPS FTP или HTTP SFTP.
Чтобы избежать этого, сокращения пишутся с заглавной буквы, как обычные слова.
Исключение: Двухбуквенные сокращения, такие как IO (ввод/вывод), пишутся полностью с заглавной буквы: IO. С другой стороны, двухбуквенные сокращения, такие как ID (идентификация), по-прежнему пишутся с заглавной буквы, как обычные слова: Id
.
?хорошо
class HttpConnection {}
class DBIOPort {}
class TVVcr {}
class MrRogers {}
var httpRequest = ...
var uiHandler = ...
var userId = ...
Id id;
?плохо
class HTTPConnection {}
class DbIoPort {}
class TvVcr {}
class MRRogers {}
var hTTPRequest = ...
var uIHandler = ...
var userID = ...
ID iD;
PREFER используя _, __ и т.д. для неиспользуемых параметров обратного вызова
Иногда сигнатура типа функции обратного вызова требует параметра, но реализация обратного вызова этот параметр не использует. В этом случае идиоматично называть неиспользуемый параметр _. Если функция имеет несколько неиспользуемых параметров, используйте дополнительные символы подчеркивания, чтобы избежать коллизий имен: _, __ и т.д.
?хорошо
futureOfVoid.then((_) {
print('Operation complete.');
});
Это руководство предназначено только для функций, которые являются как анонимными, так и локальными. Эти функции обычно используются непосредственно в контексте, где ясно, что представляет собой неиспользуемый параметр. Напротив, функции верхнего уровня и объявления методов не имеют такого контекста, поэтому их параметры должны быть названы так, чтобы было ясно, для чего предназначен каждый параметр, даже если он не используется.
DON’T не используйте начальное подчеркивание для идентификаторов, которые не являются частными
Dart использует начальное подчеркивание в идентификаторе, чтобы пометить элементы и объявления верхнего уровня как частные. Это обучает пользователей связывать начальное подчеркивание с одним из таких типов объявлений. Они видят "_" и думают "private".
Не существует понятия "private" для локальных переменных, параметров, локальных функций или библиотечных префиксов. Когда у одной из них есть имя, начинающееся с подчеркивания, это посылает читателю сбивающий с толку сигнал. Чтобы избежать этого, не используйте начальные символы подчеркивания в этих именах.
DON’T не используйте префиксные буквы
Венгерская нотация и другие схемы возникли во времена BCPL, когда компилятор мало что делал, чтобы помочь вам понять ваш код. Поскольку Dart может сообщить вам тип, область видимости, изменяемость и другие свойства ваших объявлений, нет причин кодировать эти свойства в именах идентификаторов.
?хорошо
defaultTimeout
?плохо
kDefaultTimeout
DON’T не присваивайте библиотекам явных имен
Добавление имени к директиве library
технически возможно, но является устаревшей функцией и не рекомендуется.
Dart генерирует уникальный тег для каждой библиотеки на основе ее пути и имени файла. Присвоение имен библиотекам переопределяет этот сгенерированный URI. Без URI инструментам может быть сложнее найти основной файл библиотеки, о котором идет речь.
?плохо
library my_library;
?хорошо
/// A really great test library.
@TestOn('browser')
library;
Чтобы сохранить порядок в преамбуле вашего файла, у нас есть предписанный порядок, в котором должны отображаться директивы. Каждый "раздел" должен быть разделен пустой строкой.
Одно правило компоновки обрабатывает все рекомендации по упорядочению: directives_ordering.
DO размещайте dart: imports перед другими imports
Правило Линтер: directives_ordering
?хорошо
import 'dart:async';
import 'dart:html';
import 'package:bar/bar.dart';
import 'package:foo/foo.dart';
DO размещайте package: imports перед другими imports
Правило Линтер: directives_ordering
?хорошо
import 'package:bar/bar.dart';
import 'package:foo/foo.dart';
import 'util.dart';
DO укажите экспорт в отдельном разделе после всего импорта
Правило Линтер: directives_ordering
?хорошо
import 'src/error.dart';
import 'src/foo_bar.dart';
export 'src/error.dart';
?плохо
import 'src/error.dart';
export 'src/error.dart';
import 'src/foo_bar.dart';
DO сортировка разделов в алфавитном порядке
Правило Линтер: directives_ordering
?хорошо
import 'package:bar/bar.dart';
import 'package:foo/foo.dart';
import 'foo.dart';
import 'foo/foo.dart';
?плохо
import 'package:foo/foo.dart';
import 'package:bar/bar.dart';
import 'foo/foo.dart';
import 'foo.dart';
Форматирование
Как и многие языки, Dart игнорирует пробелы. Однако люди этого не делают. Наличие согласованного стиля пробелов помогает гарантировать, что читатели-люди видят код так же, как это делает компилятор.
Отформатируйте свой код с помощью dart format
Форматирование - утомительная работа, особенно отнимающая много времени при рефакторинге. К счастью, вам не нужно беспокоиться об этом. Мы предоставляем сложный автоматический форматировщик кода под названием dart format
, который сделает это за вас. У нас есть некоторая документация о правилах, которые он применяет, но официальные правила обработки пробелов для Dart - это то, что создает dart format
.
Остальные рекомендации по форматированию касаются тех немногих вещей, которые dart format
не может исправить за вас.
CONSIDER подумайте об изменении своего кода, чтобы сделать его более удобным для форматирования
Форматировщик делает все возможное с любым кодом, который вы ему вводите, но он не может творить чудеса. Если в вашем коде особенно длинные идентификаторы, глубоко вложенные выражения, смесь различных типов операторов и т.д. отформатированный вывод все еще может быть трудночитаемым.
Когда это произойдет, реорганизовывайте или упростите свой код. Рассмотрите возможность сокращения имени локальной переменной или переноса выражения в новую локальную переменную. Другими словами, внесите те же изменения, которые вы бы внесли, если бы форматировали код вручную и пытались сделать его более читабельным. Думайте о dart format
как о партнерстве, в котором вы работаете вместе, иногда итеративно, над созданием красивого кода.
AVOID избегайте строк длиной более 80 символов
Правило линтера: lines_longer_than_80_chars
Исследования удобочитаемости показывают, что длинные строки текста труднее читать, потому что вашему глазу приходится перемещаться дальше при переходе к началу следующей строки. Вот почему газеты и журналы используют несколько колонок текста.
Если вам действительно нужны строки длиной более 80 символов, наш опыт показывает, что ваш код, скорее всего, слишком многословен и мог бы быть немного компактнее. Основным нарушителем обычно являются VeryLongCamelCaseClassNames
. Спросите себя: "Сообщает ли мне каждое слово в названии этого типа что-то важное или предотвращает конфликт имен?" Если нет, подумайте о том, чтобы опустить его.
Обратите внимание, что dart format
выполняет 99% этого за вас, но последний 1% - это вы сами. Он не разбивает длинные строковые литералы так, чтобы они помещались в 80 столбцов, поэтому вам придется сделать это вручную.
Исключение: Когда URI или путь к файлу встречается в комментарии или строке (обычно при импорте или экспорте), он может остаться целым, даже если длина строки превышает 80 символов. Это упрощает поиск пути к исходным файлам.
Исключение: Многострочные строки могут содержать строки длиной более 80 символов, поскольку новые строки являются значимыми внутри строки, а разбиение строк на более короткие может привести к изменению программы.
DO используйте фигурные скобки для всех операторов управления потоком
Правило линтера: curly_braces_in_flow_control_structures
Это позволяет избежать проблемы с зависанием else.
?хорошо
if (isWeekDay) {
print('Bike to work!');
} else {
print('Go dancing or read a book!');
}
Исключение: Когда у вас есть оператор if без предложения else и весь оператор if помещается в одной строке, вы можете опустить фигурные скобки, если предпочитаете:
?хорошо
if (arg == null) return defaultValue;
Однако, если тело переходит к следующей строке, используйте фигурные скобки:
?хорошо
if (overflowChars != other.overflowChars) {
return overflowChars < other.overflowChars;
}
?плохо
if (overflowChars != other.overflowChars)
return overflowChars < other.overflowChars;
webhamster
Такое впечатление, что писала нейросетка.