Привет, Хаброжители!
Книга «Основы Dart» адресована тем, кто интересуется этим удивительным языком программирования. Вы узнаете об истории создания, синтаксисе и особенностях языка, таких как встроенные типы данных, и многом другом. В главе 2 вас ждет проект, который будет изменяться и расти вместе с вашими знаниями и навыками, а к главе 6 преобразится в полноценное клиент-серверное приложение. После каждой новой итерации проекта вас будут ждать предложения по внесению изменений в его кодовую базу, что позволит прокачать свои hard-скиллы. Исходный код рассматриваемых в книге примеров можно найти в GitHub-репозитории автора (весь код в книге соответствует Dart 3.4).
В данной главе мы рассмотрим флаги сборки приложений и то, как их применять на практике. Кроме того, поговорим о конфигурации приложения путем передачи необходимых данных через терминал в момент его запуска. Отдельно рассмотрим механизмы Dart для работы с файлами и каталогами.
Файлы могут выступать в различном амплуа: от конфигурационных до хранилищ. Например, в конфигурационные выносится информация, которую пользователь может изменять в настройках приложения и которая влияет на логику его работы. Это делается для большей гибкости, поскольку хранение такой информации в самом коде программного продукта подразумевает, что при малейшем ее изменении необходимо заново выполнять сборку (компиляцию) программы. А в качестве примера использования файлов как хранилищ реализуем простую базу данных на основе односвязного списка.
Для сборки приложений используется команда dart compile, имеющая ряд конфигурационных флагов, отвечающих за режим компиляции [11] (табл. 5.1).
В данной таблице под целевой платформой понимается та, на которой производится компиляция приложения (Windows, Linux и т. д.). Если вам нужен полностью автономный файл приложения, то используйте флаг exe. Если важна скорость и оптимизация — поможет jit-snapshot. Если хотите, чтобы приложение запустилось на любой платформе, — используйте kernel.
У каждого из имеющихся флагов есть свои плюсы и минусы. Например, exe и aot-snapshot не поддерживают библиотеки dart:mirrors и dart:developer. Флаг kernel не предоставляет стабильного API, поэтому нет гарантии, что при сборке приложения на одной версии Dart оно запустится на другой. Для запуска файла, скомпилированного с флагом aot-snapshot, требуется утилита dartaotruntime, предоставляющая среду выполнения Dart. А если вы хотите запустить файлы, скомпилированные с флагом jit-snapshot или kernel, то требуется наличие установленного на платформе Dart SDK.
Далее рассмотрим, как осуществлять сборку приложения и его запуск (за исключением использования флага js). И начнем с создания нового консольного приложения my_app, в котором не надо ничего добавлять или удалять.
Откройте терминал Terminal New Terminal и введите команду:
в которой после флага сборки указывается путь до компилируемого файла. (Будьте внимательны: если у вас Mac или Linux, то используйте другой формат пути — bin/my_app.dart.)
В каталоге bin проекта my_app должен появиться скомпилированный файл с расширением .exe (рис. 5.1).
Вне зависимости от того, какая у вас операционная система, файл будет иметь такое расширение. Это не значит, что он собран только для Windows! У каждого флага компиляции свое выходное расширение, в данном случае — exe.
Если необходимо поменять путь, указать, куда переместить собранное приложение или имя компилируемого файла, то воспользуйтесь дополнительным параметром -о:
или
Для запуска приложения, скомпилированного таким образом, достаточно указать в терминале путь до него и нажать Enter (рис. 5.2).
Удалите скомпилированные ранее файлы из каталога bin, после чего введите в терминале следующую команду:
Как и с флагом exe, можно использовать дополнительный параметр -о, чтобы указать, куда и с каким именем поместить скомпилированный файл:
Для запуска приложения, скомпилированного с таким флагом, понадобится утилита dartaotruntime, предоставляющая среду выполнения Dart. Еще в самом начале после установки Dart SDK мы прописывали необходимые пути в переменной среды path, поэтому просто начните команду со слова dartaotruntime (рис. 5.3):
Данный флаг не поддерживает параметр -о, так как в момент компиляции осуществляется обучающий запуск приложения и то, насколько качественно он будет выполнен, отразится на итоговой оптимизации приложения. В некоторых случаях удается достичь значительного прироста быстродействия.
Удалите скомпилированные ранее файлы из каталога bin и введите следующую команду (рис. 5.4):
В каталоге bin проекта my_app должен появиться скомпилированный файл с расширением .jit (рис. 5.5).
Для запуска приложения, скомпилированного с таким флагом, понадобится установленный на целевой платформе Dart SDK. В нашем случае все уже установлено и настроено, поэтому мы можем сразу перейти к последнему шагу. Для этого введите в терминале следующую команду (рис. 5.6):
Использование этого флага для компиляции ничем не отличается от флага exe:
или
После передачи полученного файла третьей стороне убедитесь, что там имеется установленный Dart SDK (рис. 5.7):
Бывают случаи, когда в момент старта приложения ему необходимо передать какой-то набор параметров (данных) для последующей корректной работы. В принципе, нет четкого стандарта, как эти данные окажутся в программе: считаются ли с конфигурационного файла, с базы данных либо передадутся напрямую с терминала в команде запуска.
Поскольку работе с файлами посвящены следующие разделы главы, здесь мы сосредоточимся на последнем варианте и рассмотрим, зачем в главной функции main такой входной аргумент, как List arguments.
Для начала немного перепишем тело функции main в файле my_app.dart каталога bin:
Теперь скомпилируйте приложение с флагом exe и запустите его следующим образом (рис. 5.8):
Обратите внимание, что все данные, которые были указаны в качестве параметров (-имяПараметра) приложения при запуске, и следующие за ними данные были переданы на вход функции main в списке arguments.
Немного перепишем код и сложим два числа, подающихся при запуске приложения:
Снова скомпилируйте приложение и запустите его, используя следующие команды (рис. 5.9).
Но если на вход приложения не подать ни одного или одно значение, то его работа сразу завершится исключением. Поэтому при взаимодействии с позиционными аргументами нужно учитывать множество факторов, особенно когда их огромное количество. Из-за этого и используются флаги и параметры (свойства — флаг с данными после него), которые позволяют понять, есть в передаваемых на вход данных нужные значения или нет.
Не будем изобретать велосипед и воспользуемся уже готовым пакетом: args (https://pub.dev/packages/args), позволяющим задать имена параметров и флагов для их поиска и извлечения данных, а также использования значений по умолчанию, если их не передали в момент запуска приложения.
Откройте файл pubspec.yaml и добавьте в раздел с зависимостями пакет args:
Вернемся к файлу my_app.dart из каталога bin и внесем в него следующие изменения:
Скомпилируйте приложение и запустите его с различными параметрами (рис. 5.10). Обратите внимание: вне зависимости от количества передаваемых на старте приложения значений оно работает нормально. Это связано с тем, что для каждого свойства и флага было указано значение по умолчанию.
Более подробно с книгой можно ознакомиться на сайте издательства:
» Оглавление
» Отрывок
По факту оплаты бумажной версии книги на e-mail высылается электронная книга.
Для Хаброжителей скидка 25% по купону — Dart
P.S. 31 мая после выступления Станислава Чернышева на Mobius 2024 Spring можно будет приобрести печатный экземпляр книги и взять автограф автора у стенда издательства.
Благодарим компанию Friflex за помощь в работе над книгой и Станислава Чернышева за вклад в популяризацию языка программирования Dart.
P.P.S. Обращаем ваше внимание на то, что у нас на сайте проходит распродажа.
Книга «Основы Dart» адресована тем, кто интересуется этим удивительным языком программирования. Вы узнаете об истории создания, синтаксисе и особенностях языка, таких как встроенные типы данных, и многом другом. В главе 2 вас ждет проект, который будет изменяться и расти вместе с вашими знаниями и навыками, а к главе 6 преобразится в полноценное клиент-серверное приложение. После каждой новой итерации проекта вас будут ждать предложения по внесению изменений в его кодовую базу, что позволит прокачать свои hard-скиллы. Исходный код рассматриваемых в книге примеров можно найти в GitHub-репозитории автора (весь код в книге соответствует Dart 3.4).
СБОРКА ПРИЛОЖЕНИЯ. РАБОТА С ФАЙЛАМИ И КАТАЛОГАМИ
В данной главе мы рассмотрим флаги сборки приложений и то, как их применять на практике. Кроме того, поговорим о конфигурации приложения путем передачи необходимых данных через терминал в момент его запуска. Отдельно рассмотрим механизмы Dart для работы с файлами и каталогами.
Файлы могут выступать в различном амплуа: от конфигурационных до хранилищ. Например, в конфигурационные выносится информация, которую пользователь может изменять в настройках приложения и которая влияет на логику его работы. Это делается для большей гибкости, поскольку хранение такой информации в самом коде программного продукта подразумевает, что при малейшем ее изменении необходимо заново выполнять сборку (компиляцию) программы. А в качестве примера использования файлов как хранилищ реализуем простую базу данных на основе односвязного списка.
Сборка приложения
Для сборки приложений используется команда dart compile, имеющая ряд конфигурационных флагов, отвечающих за режим компиляции [11] (табл. 5.1).
В данной таблице под целевой платформой понимается та, на которой производится компиляция приложения (Windows, Linux и т. д.). Если вам нужен полностью автономный файл приложения, то используйте флаг exe. Если важна скорость и оптимизация — поможет jit-snapshot. Если хотите, чтобы приложение запустилось на любой платформе, — используйте kernel.
У каждого из имеющихся флагов есть свои плюсы и минусы. Например, exe и aot-snapshot не поддерживают библиотеки dart:mirrors и dart:developer. Флаг kernel не предоставляет стабильного API, поэтому нет гарантии, что при сборке приложения на одной версии Dart оно запустится на другой. Для запуска файла, скомпилированного с флагом aot-snapshot, требуется утилита dartaotruntime, предоставляющая среду выполнения Dart. А если вы хотите запустить файлы, скомпилированные с флагом jit-snapshot или kernel, то требуется наличие установленного на платформе Dart SDK.
Далее рассмотрим, как осуществлять сборку приложения и его запуск (за исключением использования флага js). И начнем с создания нового консольного приложения my_app, в котором не надо ничего добавлять или удалять.
Флаг exe
Откройте терминал Terminal New Terminal и введите команду:
dart compile exe bin\my_app.dart
в которой после флага сборки указывается путь до компилируемого файла. (Будьте внимательны: если у вас Mac или Linux, то используйте другой формат пути — bin/my_app.dart.)
В каталоге bin проекта my_app должен появиться скомпилированный файл с расширением .exe (рис. 5.1).
Вне зависимости от того, какая у вас операционная система, файл будет иметь такое расширение. Это не значит, что он собран только для Windows! У каждого флага компиляции свое выходное расширение, в данном случае — exe.
Если необходимо поменять путь, указать, куда переместить собранное приложение или имя компилируемого файла, то воспользуйтесь дополнительным параметром -о:
dart compile exe bin\my_app.dart -o bin\new_app
или
dart compile exe bin\my_app.dart -o bin\new_app.exe
Для запуска приложения, скомпилированного таким образом, достаточно указать в терминале путь до него и нажать Enter (рис. 5.2).
Флаг aot-snapshot
Удалите скомпилированные ранее файлы из каталога bin, после чего введите в терминале следующую команду:
dart compile aot-snapshot bin\my_app.dart
Как и с флагом exe, можно использовать дополнительный параметр -о, чтобы указать, куда и с каким именем поместить скомпилированный файл:
dart compile aot-snapshot bin\my_app.dart -o C:\code\new_app.aot
Для запуска приложения, скомпилированного с таким флагом, понадобится утилита dartaotruntime, предоставляющая среду выполнения Dart. Еще в самом начале после установки Dart SDK мы прописывали необходимые пути в переменной среды path, поэтому просто начните команду со слова dartaotruntime (рис. 5.3):
dartaotruntime bin\my_app.aot
Флаг jit-snapshot
Данный флаг не поддерживает параметр -о, так как в момент компиляции осуществляется обучающий запуск приложения и то, насколько качественно он будет выполнен, отразится на итоговой оптимизации приложения. В некоторых случаях удается достичь значительного прироста быстродействия.
Удалите скомпилированные ранее файлы из каталога bin и введите следующую команду (рис. 5.4):
dart compile jit-snapshot bin\my_app.dart
В каталоге bin проекта my_app должен появиться скомпилированный файл с расширением .jit (рис. 5.5).
Для запуска приложения, скомпилированного с таким флагом, понадобится установленный на целевой платформе Dart SDK. В нашем случае все уже установлено и настроено, поэтому мы можем сразу перейти к последнему шагу. Для этого введите в терминале следующую команду (рис. 5.6):
dart run bin\my_app.jit
Флаг kernel
Использование этого флага для компиляции ничем не отличается от флага exe:
dart compile kernel bin\my_app.dart
или
dart compile kernel bin\my_app.dart -o C:\code\new_app
После передачи полученного файла третьей стороне убедитесь, что там имеется установленный Dart SDK (рис. 5.7):
dart run bin\my_app.dill
Конфигурация запускаемого приложения
Бывают случаи, когда в момент старта приложения ему необходимо передать какой-то набор параметров (данных) для последующей корректной работы. В принципе, нет четкого стандарта, как эти данные окажутся в программе: считаются ли с конфигурационного файла, с базы данных либо передадутся напрямую с терминала в команде запуска.
Поскольку работе с файлами посвящены следующие разделы главы, здесь мы сосредоточимся на последнем варианте и рассмотрим, зачем в главной функции main такой входной аргумент, как List arguments.
Для начала немного перепишем тело функции main в файле my_app.dart каталога bin:
import 'package:my_app/my_app.dart' as my_app;
void main(List<String> arguments) {
print(arguments);
print('Hello world: ${my_app.calculate()}!');
}
Теперь скомпилируйте приложение с флагом exe и запустите его следующим образом (рис. 5.8):
bin\my_app.exe
bin\my_app.exe -a 34 -b -_- -c hellow world!
Обратите внимание, что все данные, которые были указаны в качестве параметров (-имяПараметра) приложения при запуске, и следующие за ними данные были переданы на вход функции main в списке arguments.
Немного перепишем код и сложим два числа, подающихся при запуске приложения:
void main(List<String> arguments) {
print(arguments);
var a = int.tryParse(arguments[0]);
var b = int.tryParse(arguments[1]);
if (a = = null || b = = null) {
print('Invalid input');
return;
}
print('a + b = ${a + b}');
}
Снова скомпилируйте приложение и запустите его, используя следующие команды (рис. 5.9).
Но если на вход приложения не подать ни одного или одно значение, то его работа сразу завершится исключением. Поэтому при взаимодействии с позиционными аргументами нужно учитывать множество факторов, особенно когда их огромное количество. Из-за этого и используются флаги и параметры (свойства — флаг с данными после него), которые позволяют понять, есть в передаваемых на вход данных нужные значения или нет.
Не будем изобретать велосипед и воспользуемся уже готовым пакетом: args (https://pub.dev/packages/args), позволяющим задать имена параметров и флагов для их поиска и извлечения данных, а также использования значений по умолчанию, если их не передали в момент запуска приложения.
Откройте файл pubspec.yaml и добавьте в раздел с зависимостями пакет args:
# Add regular dependencies here.
dependencies:
args: ^2.4.2
# path: ^1.8.0
Вернемся к файлу my_app.dart из каталога bin и внесем в него следующие изменения:
import 'package:args/args.dart';
void main(List<String> arguments) {
var parser = ArgParser();
parser.addOption( // добавляем параметр/свойство в парсер
'firts', // по данному ключу будет осуществляться поиск данных
abbr: 'a', // имя свойства при его указании в момент запуска
help: 'First number',
defaultsTo: '1', // значение по умолчанию
);
parser.addOption(
'second',
abbr: 'b',
help: 'Second number',
defaultsTo: '5',
);
parser.addFlag( // добавляем флаг в парсер
'subtract',
abbr: 's',
help: 'Subtract mode',
defaultsTo: false,
);
var args = parser.parse(arguments);
print(arguments);
var a = int.parse(args['firts']);
var b = int.parse(args['second']);
if (args['subtract']){
print('a - b = ${a - b}');
}else{
print('a + b = ${a + b}');
}
}
Скомпилируйте приложение и запустите его с различными параметрами (рис. 5.10). Обратите внимание: вне зависимости от количества передаваемых на старте приложения значений оно работает нормально. Это связано с тем, что для каждого свойства и флага было указано значение по умолчанию.
Об авторе
Станислав Чернышев — Доцент СПбГУАП и СПбГЭУ, к.т.н. Более 10 лет в IT: работал в сфере ВПК (БПЛА, системы внешнетраекторных измерений), старшим научным сотрудником лаборатории имитационного моделирования военной академии МТО им. генерала армии А.В. Хрулева МО РФ, участвовал в различных проектах на заказ. Архитектор и ведущий разработчик сред имитационного и мультиагентного моделирования и фреймворков для их создания. После нескольких выгораний полностью перебрался в науку и преподавание, специализируется на разработке распределенных мультиагентных систем.
Лауреат премии Правительства Санкт-Петербурга в области научно-педагогической деятельности в 2021 и 2023 г.
Лауреат премии Правительства Санкт-Петербурга в области научно-педагогической деятельности в 2021 и 2023 г.
Более подробно с книгой можно ознакомиться на сайте издательства:
» Оглавление
» Отрывок
По факту оплаты бумажной версии книги на e-mail высылается электронная книга.
Для Хаброжителей скидка 25% по купону — Dart
P.S. 31 мая после выступления Станислава Чернышева на Mobius 2024 Spring можно будет приобрести печатный экземпляр книги и взять автограф автора у стенда издательства.
Благодарим компанию Friflex за помощь в работе над книгой и Станислава Чернышева за вклад в популяризацию языка программирования Dart.
P.P.S. Обращаем ваше внимание на то, что у нас на сайте проходит распродажа.