Какая аннотация используется для классов, все поля которых должны быть final?
Anonymous Quiz
6%
2%
88%
4%
❤4
Для чего используется аннотация @visibleForTesting?
Anonymous Quiz
7%
Для генерации тестов автоматически
90%
Для обозначения элементов, предназначенных только для тестов
1%
Для скрытия кода от тестирования
3%
Для запуска тестов в production
❤4
Какая аннотация запрещает наследование класса за пределами его библиотеки?
Final Results
38%
5%
54%
3%
❤4
This media is not supported in your browser
VIEW IN TELEGRAM
Пока я готовлю пост про шейдеры, давайте обсудим, как можно создать свой CLI-пакет на Dart. Мы сталкиваемся с CLI каждый день, зачастую даже не задумываясь об этом. Когда вы вводите flutter doctor, чтобы проверить окружение, или запускаете firebase init, чтобы создать проект Firebase, вы взаимодействуете именно с CLI.
CLI (Command Line Interface) — это интерфейс взаимодействия с приложением через консоль: вы передаете команды и аргументы, а приложение что-то выполняет. Если сильно упростить, CLI — это возможность ввести в консоли:
mytool login
И программа выполнит какое-то действие, не открывая UI.
Создать свой CLI на Dart довольно просто. Для этого нужно выполнить команду:
dart create -t console-full my_cli_tool
cd my_cli_tool
После генерации у вас появится базовая структура проекта:
/bin
my_cli_tool.dart <-- точка входа
/lib
...
Все, что находится в папке bin/, является входной точкой нашего CLI.
Когда структура готова, можно добавить команды. Для обработки аргументов и команд идеально подходит пакет args. Кстати, про эту библиотеку вы можете подробнее прочитать в этом посте.
Представим, что у нас есть приложение, и мы хотим добавить CLI-команду для авторизации пользователя. Создадим команду LoginCommand:
class LoginCommand extends Command {
@override
final name = 'login'; // название команды
@override
final description = 'Login to service'; // описание, показывается при -h
@override
Future<void> run() async {
// ... логика авторизации
}
}Для взаимодействия с терминалом используем потоки: stdout, stderr и stdin.
✔️ stdout — вывод обычной информации в терминал (сообщения, результаты)
✔️ stderr — поток ошибок (то, что пользователю важно видеть, если что-то пошло не так)
✔️ stdin — ввод данных пользователем. Например, stdin.readLineSync() просто ждет, пока пользователь нажмет Enter, и возвращает введенный текст
stdout.write('📧 Enter your email: ');
final email = stdin.readLineSync();Для более удобной работы с интерактивным вводом (например, чтобы скрыть ввод пароля или добавить выбор стрелками) можно использовать библиотеку dcli.
mixin CliMixin {
String askStringField(
String prompt, {
String? defaultValue,
bool required = true,
bool hidden = false,
}) {
final result = ask(
prompt,
hidden: hidden,
defaultValue: defaultValue,
required: required,
validator: const NotEmptyValidator(),
);
return result;
}
String askSelectField(
String prompt,
List<String> options, {
String? defaultValue,
}) {
final selected = menu(
prompt,
options: options,
defaultOption: defaultValue,
);
return selected;
}
}После успешного логина данные можно сохранить на диск (например, в ~/.my_cli/config.json). В следующих командах CLI автоматически поймет, что пользователь уже авторизован.
И вот наступает самый приятный момент: CLI готов, его можно сделать глобальной системной командой. Для этого в файле pubspec.yaml нужно добавить секцию executables:
executables:
mytool: my_cli_tool
После этого выполняем:
dart pub global activate --source path
Теперь в любой директории можно набрать:
mytool login
и команда запустится, будто это встроенная системная утилита.
Если вы хотите пойти дальше, можно собрать бинарник под macOS, Linux или Windows:
dart compile exe bin/my_cli_tool.dart -o mytool
Таким образом, CLI становится полноценным инструментом, который можно использовать на любых платформах и с приложениями на разных языках программирования: его можно публиковать на pub.dev, подключить через Homebrew или распространять внутри команды.
❤️ — если нужно продолжение про публикацию CLI в Homebrew и сборку бинарников
Please open Telegram to view this post
VIEW IN TELEGRAM
❤18🔥3👍1
Поговорим сегодня про assert в Dart. Разберемся, что же это такое, как работает и почему он точно будет вам полезен.
Assert — это оператор в языке Dart для проверки утверждений в процессе отладки вашего кода. Он помогает разработчику проверить, что определенные условия выполняются корректно. В случае, если это не так, программа выдает ошибку
AssertionError. Синтаксис очень прост — в оператор требуется передать условие для проверки, а также сообщение, которое поможет разобраться в том, почему же была получена ошибка. При этом сообщение не является обязательным, но линтер все же рекомендует его добавлять.
assert(<условие>, '<сообщение об ошибке>');
Применять assert можно как в методах, так и в конструкторах для проверки входных параметров.
Для примера реализуем простую программу для вывода количества товаров. Конечно, количество не может быть представлено отрицательным числом. Поэтому здесь стоит добавить проверку, чтобы избежать логических ошибок.
void setProductsAmount(int amount) {
assert(amount >= 0, 'Количество товаров не может быть отрицательным!');
print('Количество товаров установлено: $amount');
}
void main() {
setProductsAmount(25); // Код выполняется без ошибок
setProductsAmount(-5); // Ошибка в debug режиме: Количество товаров не может быть отрицательным!
}
Возьмем еще один более сложный пример. Нам нужно создать класс данных карточки. Карточки могут быть двух типов — простая и с изображением. При этом карточка с изображением обязательно должна получить ссылку на него. Чтобы ограничить создание карточки с картинкой без ссылки на изображение, достаточно в конструктор добавить соответствующий assert.
enum CardType { simple, withImage }
class Card {
const Card({
required this.type,
required this.title,
required this.subtitle,
this.imageUrl,
}) : assert(
type != CardType.withImage || imageUrl != null,
'Для карточки типа withImage необходимо указать imageUrl!',
);
final CardType type;
final String title;
final String subtitle;
final String? imageUrl;
}
void main() {
try {
final card = Card(
type: CardType.withImage,
title: 'Карточка с картинкой',
subtitle: 'Это карточка с картинкой',
);
print('Карточка с картинкой успешно создана!');
} catch (error) {
print(error);
}
// Этот код выведет в консоль сообщение об ошибке - Для карточки типа withImage необходимо указать imageUrl!
}
Здесь важно учесть, что assert работают только в debug режиме, поэтому валидировать с помощью них действия пользователя или внешние данные нельзя. Их можно и нужно применять в тех случаях, в которых сам разработчик может допустить ошибку на этапе выполнения задачи.
Еще больше полезного можно найти здесь:
◾️ Assert Statements in Dart
◾️ Error handling, Asserts
❤️ — если было полезно
Please open Telegram to view this post
VIEW IN TELEGRAM
❤10🔥6🥰2