Нехайповый Dart, который стоит попробовать
Тимофей Лавренюк
Corcentric
Дисклеймер
Целью этой презентации не является обидеть любитей TypeScript-а, а лишь показать преимущества и недостатки одной технологии перед другой
- Что мы знаем о Dart
- Как я пришел к Dart
- Особенности Dart
- Экосистема Dart
План
Что мы знаем о Dart?
1
A client-optimized language for fast apps on any platform
Кто использует
Немного истории...
2011
Появился
2011
2018
Появился
медленно развивался
Как я пришел к Dart?
2
Research: на чем можно писать front-end, кроме TypeScript?
- Язык от JetBrains
- Много информации
- Сыроват для Web
- Нет UI-фреймворка
- Нет пакетного менеджера
- Синтаксис OCaml от Facebook
- Мало информации
- Есть UI-framework
- Есть пакетный манеджер
- Много функциональщины
- Язык от Mozilla
- Компилируется в WebAssembly, может общаться с JS кодом
- Нет стабильного UI-фреймворка
- Есть пакетный менеджер
- Язык от Google
- Не много, но и не мало информации
- Есть UI-фреймворк
- Есть пакетный менеджер
Мой выбор
Почему не TypeScript?
Обучение и документация
Надежность
Вывод ошибок
Как начать работать с Dart?
SDK
IDE
void main() {
print('Hello, World!');
}
Как научиться писать хорошо на Dart?
Как учат JS?
МНОГО
Что предлагает Dart?
Особенности Dart
3
2011
2018
Появился
медленно развивался
Dart 2.0
Строгая типизация
Типизация в Javascript (ее нет)
Типизация в TypeScript (гибкая)
The Dart language is type safe: it uses a combination of static type checking and runtime checks to ensure that a variable’s value always matches the variable’s static type. Although types are mandatory, type annotations are optional because of type inference.
- Numbers
- Strings
- Booleans
- Lists
- Sets
- Maps
Типы данных
Простота
List numbers = [1,2,3];
print(numbers.first); // 1
print(numbers.last); // 3
Map<String, String> users =
{"1": "Foo", "2": "Bar"};
List<String> usernames = users.values;
List<String> userIds = users.keys;
class SomeClass {
double number;
callFunction() {}
}
SomeClass nullClass;
final value = nullClass ?? SomeClass();
final number ??= SomeClass().number;
print(nullClass?.callFunction());
class Foo {
Foo({
this.paramOneName = '1',
this.paramTwoName = '2' });
String paramOneName;
String paramTwoName;
}
var foo = Foo(paramTwoName: '3');
class Bar {
Bar();
Foo f1;
Foo f2;
}
Bar bar = Bar()
..f1 = Foo(paramTwoName: '2')
..f2 = Foo(paramOneName: '10');
mixin Musical {
bool canPlayPiano = false;
bool canCompose = false;
bool canConduct = false;
void entertainMe() {
if (canPlayPiano) {
print('Playing piano');
} else if (canConduct) {
print('Waving hands');
} else {
print('Humming to self');
}
}
}
class Musician extends Performer with Musical {
// ···
}
class Maestro extends Person
with Musical, Aggressive, Demented {
Maestro(String maestroName) {
name = maestroName;
canConduct = true;
}
}
Вспомогательные классы
- DateTime
- Duration
- Uri
this не теряется
Core libraries
- dart:core
- dart:async
- dart:collection
- dart:html
- dart:io
- ...
dart:async
Future<int> future = Future(asyncFunction);
future.then((int value) {
print(value);
}).catchError((e) {
print('Error');
});
someFunc () async {
try {
int value = await future;
} catch(e) {
print('Error');
}
}
Streams
Stream<int> timedCounter(Duration interval, [int maxCount]) async* {
int i = 0;
while (true) {
await Future.delayed(interval);
yield i++;
if (i == maxCount) break;
}
}
var counterStream = timedCounter(const Duration(seconds: 1), 15)
counterStream.listen(print);
someStream
.map(...)
.reduce(...)
.skip(...)
.take(...)
.timeout(...)
.transform(...)
.listen((result) {
print(result);
})
stream_transform
rx_dart
dart:collection
dart:convert
- Base64Encoder
- Base64decoder
- JsonDecoder
- JsonEncoder
- HtmlEscape
- ...
dart:html
Stream
Это все из коробки (SDK)
Сторонние библиотеки
json_serializer
{
"name": "Foo",
"email": "somemail@example.com"
}
JSON response
import 'package:json_annotation/json_annotation.dart';
part 'user.g.dart';
@JsonSerializable()
class User {
User(this.name, this.email);
String name;
String email;
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
Map<String, dynamic> toJson() => _$UserToJson(this);
}
built_value
built_collection
abstract class User implements Built<User, UserBuilder> {
factory User([updates(UserBuilder b)]) = _$User;
User._();
@nullable
String get firstName;
@nullable
String get lastName;
}
User user = User((builder) =>
builder..firstName = 'One'
..lastName = 'Two'
);
User secondUser = user.rebuild((builder) =>
builder..lastName = 'Three'
);
// user != secondUser
intl
http
...
Экосистема Dart
4
Форматирование кода
class User
{
String paramNumberOne = 1;
String paramNumbeTwo = 2;
String paramNumbeThree = 3;
num age;
num get age => _age;
set age (num age)
{
_age = age;
}
}
class User {
String paramNumberOne = 1;
String paramNumbeTwo = 2;
String paramNumbeThree = 3;
num age;
}
Dart Formatter
dartfmt -w --fix lib
Dart 👍
Linter
analysis_options.yaml
dartanalyzer --fatal-warnings lib
Dart 👍👍👍
Документация
Dart documentation guide
dartdoc
F1
Dart 👍👍👍
Пакетный менеджер
name: project name
version: 0.0.1
environment:
sdk: '>=2.4.0 <3.0.0'
dependencies:
intl: ^0.15.7
pubspec.yaml
Dart 👍👍
Разработка приложений
Web
import 'package:angular/angular.dart';
@Component(
selector: 'user-info',
templateUrl: 'user_info.html')
class UserInfo implements OnInit {
User(this.dataController)
DataController dataController;
Stream<String> userName;
void ngOnInit() {
userName = dataController.info.userName;
}
}
НО
Мало информации
Велосипедостроение
Подключение JS библиотек
@JS('draw2d')
library draw2d;
@JS('Canvas')
class Canvas {
external factory Canvas(String name, [num x, num y]);
external Canvas add(Figure figure, [num x, num y]);
external Canvas addSelection(ArrayList /*Figure|List<Figure>*/ object);
external Canvas clear();
external void destroy();
external void fireEvent(String name, [dynamic attr]); /*Object*/
external Point fromCanvasToDocumentCoordinate(num x, num y);
external Point fromDocumentToCanvasCoordinate(num x, num y);
external num getAbsoluteX();
external num getAbsoluteY();
}
Build system
Debug
Chrome Dev Tools
Выводы
Batteries included
iOS
Android
- Меньше устройств
- Меньше приложений
- Больше качественных приложений
- Залиться в AppStore - Challenge
- Больше устройств
- Больше приложений
- Меньше качественных приложений
- Залиться в Play Market - Easy
Dart
JS/TS
- Мало кто использует
- Мало библиотек
- Много качественных библиотек
- Залиться в Pub - Challenge
- Тяжело начать, легче поддерживать.
- Отличная документация
- Очень многие используют
- Очень много библиотек
- Мало качественных библиотек
- Залиться в NPM - Easy
- Легко начать, тяжелее поддерживать.
- Документаций много и все разные
Продуктивность разработки
TS
Dart
Dart хорош, но не везде
Стоит попробовать Dart, если хочется:
- Почувствовать себя крутым девелопером уровня C#/Java
- Повышать кругозор новых языков, оставаясь писать frontend
- Забыть про многие странные вещи из JS
- Не жить в мире, где на все случаи есть библиотека и подробная документация к ней
2011
2018
Появился
2019
медленно развивался
Dart 2.0
Flutter-Хайп
2011
2018
Появился
2019
Будущее
медленно развивался
Dart 2.0
Flutter-Хайп
Dart 2.5 ML Completion
Dart 2.7 Extensions
Null safety
Вопросы?
Нехайповый Dart, который стоит попробовать
By Timofey Lavrenyuk
Нехайповый Dart, который стоит попробовать
- 473