Dart, как возможность перенести нативное приложение в web

KeepSolid

Тимофей Лавренюк

План доклада

  • Попытки перенести нативные приложения в web
  • Почему мы выбрали Dart
  • Что такое Dart?
  • Особенности Dart
  • Экосистема Dart
  • Сложности перехода с C++ на веб-разработку
  • Выводы
 

Кто я

Из Одессы

Более 8 лет в веб-разработке

Работаю в KeepSolid

Попытки перенести нативное приложение в web

1

Ядро

RPC Server

  • Монолитное C++ ядро
  • Отсутствие помощи
  • Некомпилируемые библиотеки

WEB-Версия

Криптография

Offline

Работа с PDF

Общение с RPC-сервером

  • Говнокод + утечки памяти
  • Сложный дебаг
  • CMake

Команда

Нужно писать на TypeScript

?

Research: на чем можно писать Front-End, кроме TypeScript

  • Язык от JetBrains
  • Много информации
  • Сыроват для Web
  • Нет UI-фреймворка
  • Нет пакетного менеджера
  • Синтаксис OCaml от Facebook
  • Мало информации
  • Есть UI-framework
  • Есть пакетный манеджер
  • Много функциональщины
  • Язык от Mozilla
  • Компилируется в WebAssembly, может общаться с JS кодом
  • Нет стабильного UI-фреймворка
  • Есть пакетный менеджер
  • Язык от Google
  • Не много, но и не мало информации
  • Есть UI-фреймворк
  • Есть пакетный менеджер

Почему мы выбрали Dart?

2

class SomeClass {
  sayHello(value) {
    alert(value);
  }
  static #privateField = 2;
  callPrivate(obj) {
    alert(obj.value)
  }
}
interface ISomeClassMain {
  sayHello: (value: string) => void;
}

interface ISomeObject {
  value: 'one' | 'two' | null | undefined;
  zalepon: any;
}

class SomeClass implements ISomeClassMain {
  sayHello(value: string) {
    alert(value);
  }
  private static privateField = 2;
  private callPrivate(obj: ISomeObject): void {
    alert(obj.value);
  }
}

Вывод ошибок 

Что такое Dart?

3

A client-optimized language for fast apps on any platform

Google

Кто использует

2011

Появился

2011

2018

Появился

медленно развивался

С чего мы начали?

SDK

IDE

Java

JS

Победил

void main() {
  print('Hello, World!');
}

Как мы смогли выучить язык?

Как учат JS?

МНОГО

Что предлагает Dart?

Круто, что еще нужно?

Особенности Dart

4

Строгая типизация

Типизация в Javascript (ее нет)

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.

List numbers = [1,2,3];

print(numbers.first); // 1
print(numbers.last); // 3

print(numbers.isEmpty); // false
print(numbers.isNotEmpty); // true
Map<String, String> users =
	{"1": "Foo", "2": "Bar"};
    
List<String> usernames = users.values;
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(paramOneName: '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

Core libraries

  • dart:core
  • dart:async
  • dart:collection
  • dart:html
  • dart:io
  • ...

dart:async

Dart - однопоточный язык, как и JS

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

controller = StreamController<int>(
  onListen: startTimer,
  onPause: stopTimer,
  onResume: startTimer,
  onCancel: stopTimer);
      
controller.stream.listen((timer) {
  print(timer);
});
someStream
  .map(...)
  .reduce(...)
  .skip(...)
  .take(...)
  .timeout(...)
  .transform(...)
  .listen((result) {
     print(result);
  })

stream_transform

rx_dart

Event Loop

"многопоточности" быть

Web Workers

Isolates

dart:collection

dart:convert

  • Base64Encoder
  • Base64decoder
  • JsonDecoder
  • JsonEncoder
  • HtmlEscape
  • ...

dart:html

Stream

Все из коробки

Сторонние библиотеки

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

5

UI

Веб-разработка

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;
    }
}
<div>{{userName | async}}</div>

А что если нужна библиотека, которой нет на Dart?

Подключаем 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();
}

Кроссплатформенная разработка

2011

2018

Появился

2019

медленно развивался

Dart 2.0

Flutter-Хайп

Хайп Flutter-а двигает разработку Dart вперед

Форматирование кода

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

+ pre-commit hook

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

pub get

Когда либа импортится за 10 секунд

Dart 👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍

Debug

console.log("Best debug ever (No)");

Chrome Dev Tools

Build system

Сложности перехода с C++ на веб-разработку

6

Забить на потребление памяти

JS Garbage Collector

Сложности web-разработки на Dart 

Бывает недостаточно информации

Велосипедо-строение

Выводы

7

Batteries included

Веб разработка быстрее нативной

Реализованные проекты

Roadmap Planner Web Viewer

KeepSolid Goals

Dart хорош, но не везде

2011

2018

Появился

2019

медленно развивался

Dart 2.0

Flutter-Хайп

2011

2018

Появился

2019

Будущее

медленно развивался

Dart 2.0

Flutter-Хайп

Dart 2.5

ML Autocomplete

Dart 2.6

Extensions

К плюсам возвращаться не хочется

Итого:

С++ разработчики

Dart C++

By Timofey Lavrenyuk

Dart C++

  • 413