DART

for

HIPSTERs







dominik.wronski@gmail.com







      @DominikWro


AGENDA


What is DART


Why it's cool


MV* APP

What is DART

Short answer:

                                              javascript Google way

Longer (technical) answer:

Purely Object-Oriented, optionally typed, class-based, single inheritance with actor-based concurrency language.

Hello World

// Define a function. 
printHello(String aword) {
print('Hello $aword!');
}
 
// This is where the app starts executing.
main() {
var word = "world";
printHello(word);
}

Hello World

AGAIN :)


// simple web server
runServer(String basePath) {
  HttpServer server = new HttpServer();
  server.defaultRequestHandler = new StaticFileHandler(basePath).onRequest;
  server.listen('127.0.0.1', 1337);
}

main() { File script = new File(new Options().script); script.directory().then((Directory d) { runServer(d.path); }); }


DARTIUM


dart2js




GOALS


PERFORMANCE


BIG WEBSITES


NICE TO WORK WITH

PERFORMANCE

amazon.com    600 kb

cnn.com            1.5 mb 

https://www.dartlang.org/performance/


Why dart is faster


simpler object model

programs are declared not constructed at a runtime
fewer special corner cases

DART VM

Sophisticade hacks
(i.e. tree shaking)

Biger Websites

Source: Google I/O 2013 https://www.dartlang.org/slides/

Solution


core libraries

  • dart: core

  • dart: async

  • dart: html

  • dart: io

  • ...


Languages features 


or

 
why it's nice to write in dart

  • Good core library

  • Syntax

  • Futures

  • Streames

  • Mixins

  • Isolates



CORE Libraries


Dart:html


// No jQuery:
var elements = document.querySelectorAll('slide');
for(int i = 0 ; i < elements.length; i++) { 
elements[i].class Name = element.className + 'swing';
} // jQuery: $('slide').addClass('swing');

// Dart
queryAll('slide').classes.add('swing')


Syntax

Optionaly typed

multiply(num x, num factor) {
  return x * factor;
}

main() {
  print( multiply(4, "hello") ); // WARNING at this line, string isn't assignable to number
    


Double and Integer

Integers are faster 

Futures


catService.getCatData("cute", (cat) {                //js
  catService.getCatPic(cat.ImageId, (pic) {
    imageWorker.rotate(pic, 30, (rotated) {
      draw(rotated);
    });
  });
}); 

catService.getCat("cute")                            //dart
.then((cat) => catService.getCatPicture(cat.ImageId))
.then((pic) => imageWorker.rotate(pic, 30))
.then((rotated) => draw(rotated)
)

Streams

import 'dart:async';

main() {

// Some code  >> Don't need to read this comments <<
// I already told you there is no need to read this comment

  var subscription = stream.listen(null); 
subscription.onData((value) {
print("listen: $value");
if (value == 2) subscription.cancel(); // cancel the subscription
});
subscription.onError((err) => print("error: $err"));
subscription.onDone(() => print("done")); }

MIXINS

abstract class Persistence {     
void save(String filename) {
print('saving the object as ${toJson()}');
}
void load(String filename) {
print('loading from $filename');
}
Object toJson();
}
abstract class Warrior extends Object with Persistence {
fight(Warrior other) {
// ...
}
}

class Ninja extends Warrior {
Map toJson() {
return {'throwing_stars': true};
}
}

class Zombie extends Warrior {
Map toJson() {
return {'eats_brains': true};
}
}

Isolates

  • Isolated memory heap
  • Actor-based concurrency
  • Each isolate is conceptually a process
  • Nothing shared, all communication via message passing
  • Compile to webworkers for HTML5
  • Inspired by Erlang processes
import 'dart:isolate'; 

longRunningCalculation() {
port.receive((msg, replyTo) {
if (msg == 'go') {
// do long calculation
replyTo.send(result);
}
});
}

main() {
SendPort sendPort = spawnFunction(longRunningCalculation);
SendPort.call('go').then((result) => print('Result is $result'));
// continue to respond to input events while long calculation is running
}


backbone.js style MV* app



OUR_APP/                     
                     app.dart
                    
                     /WEB
                                          index.html
                                          main.dart
                                          style.css
                      /LIB
                                          Models.ComicBook.dart
                                          Collections.Comics.dart    
                                          Views.AddComic.dart
                                          Views. AddComicForm.dart
                                          Views.Comics.dart
                                          ModalDialog.dart

                                 

index.html

<!DOCTYPE html>
<html>
<head>
  <title>Dart Comics</title>
  <link rel="stylesheet" href="/stylesheets/style.css">

  <script src="packages/browser/dart.js"></script>
  <script src="main.dart" type="application/dart"></script>
</head>

<body>
  <h1>Dart Comics</h1>
  <p>Welcome to Dart Comics</p>

  <ul id="comics-list"></ul>

  <p id="add-comic">Add a sweet comic to the collection.</p>
</body>
</html>
import 'dart:io'; // app.dart
import 'package:json/json.dart' as JSON;
import 'package:dirty/dirty.dart';
import 'package:uuid/uuid.dart';
import 'package:ansicolor/ansicolor.dart';
main() {
  var port = Platform.environment['PORT'] == null ?
    8000 : int.parse(Platform.environment['PORT']);
  HttpServer.bind('127.0.0.1', port).then((app) {
    //app.listen(Public.matcher, Public.handler);
    app.listen((req) {
      log(req)
      if (req.method == 'GET' && req.uri.path == '/comics') {
        return Comics.index(req);  }
      if (req.method == 'POST' && req.uri.path == '/comics') {
        return Comics.post(req);}
      if (req.method == 'DELETE' &&
          new RegExp(r"^/comics/[-\w\d]+$").hasMatch(req.uri.path)) {
        return Comics.delete(req);}
      if (Public.matcher(req)) {
        return Public.handler(req); }
      HttpResponse res = req.response;
      res.statusCode = HttpStatus.NOT_FOUND;
      res.write("Not found.");
      res.close();
    });
    print('Server started on port: ${port}');
  });
}

class Comics { //app.dart
  static Uuid uuid = new Uuid();
  static Dirty db = new Dirty('dart_comics.db');

  static index(HttpRequest req) {
    // print(db.values.toList());
    HttpResponse res = req.response;
    res.headers.contentType
      = new ContentType("application", "json", charset: "utf-8");

    res.write(JSON.stringify(db.values.toList()));
    res.close();
  }
static
post(HttpRequest req) {
...
}
static
delete(HttpRequest req) {
...
}

main.dart
import 'package:dart_comics/Collections.Comics.dart' as Collections;
import 'package:dart_comics/Views.Comics.dart' as Views;
import 'package:dart_comics/Views.AddComic.dart' as Views; import 'dart:html';
import 'package:json/json.dart' as JSON;
import 'package:hipster_mvc/hipster_sync.dart';

main
() {
  // HipsterSync.sync = localSync;
  var my_comics_collection = new Collections.Comics(),
     comics_view = new Views.Comics(
        el:'#comics-list',
        collection: my_comics_collection
      );
  my_comics_collection.fetch();
  new Views.AddComic(
    el:'#add-comic',
    collection: my_comics_collection
  );
}
localSync(method, model) {
  final completer = new Completer();
  print("[local_sync] $method");
  if (method == 'read') {
    var json = window.localStorage[model.url],
        data = (json == null) ? {} : JSON.parse(json);
    completer.complete(data.values);
  }
  if (method == 'create') {
    var collection = model.collection,
        attrs = model.attributes;
    if (attrs['id'] == null) {
      attrs['id'] = "${attrs['title']}:::${attrs['author']}".hashCode;
    }
    print(attrs);
collection.create(attrs);
    var id = attrs['id'];
    collection.data[id] = attrs;
    window.localStorage[collection.url]= JSON.stringify(collection.data);
  }
  return completer.future;
} 


try.dartlang.com




http://www.google.com/elections/

Dart SDK 1.0 released 14 Nov 2013



Made with Slides.com