DART             Yohan BESCHI – Java Developer                     @yohanbeschi                     +Yohan Beschi2013-04-1...
2013-04-10   Introduction to Dart   2
Building UIs - Javascript ?2013-04-10                Introduction to Dart   3
Building UIs - Java ?2013-04-10                Introduction to Dart   4
Building UIs with Java - But how ?2013-04-10               Introduction to Dart   5
Programmatic Components with GWTCellTable<User> table = new CellTable<User>();                                            ...
Programmatic Components with GWTCellTable<User> table = new CellTable<User>();                                            ...
The Dart WayTable<User> table = new Table (sorting:true)  ..addColumn(ID, new TextCell((User o) => o.id))  ..addColumn(Fir...
The Dart WayTable<User> table = new Table (sorting:true)  ..addColumn(ID, new TextCell((User o) => o.id))  ..addColumn(Fir...
Dart is the winner2013-04-10               Introduction to Dart   10
Once upon a time…2013-04-10             Introduction to Dart   11
Programmer productivity2013-04-10              Introduction to Dart   12
Application scalability2013-04-10                Introduction to Dart   13
Raw execution speed2013-04-10              Introduction to Dart   14
Startup performance2013-04-10              Introduction to Dart   15
And here we are!⦿ Open Source (BSD)⦿ Structured⦿ Anti-Revolutionary⦿ Same goals as new Javascript frameworks⦿ The goal is ...
Dart Ecosystem                                      Dart Editor                                        Dartium            ...
Virtual Machines2013-04-10              Introduction to Dart   18
Dartium2013-04-10             Introduction to Dart   19
DartEditor2013-04-10                Introduction to Dart   20
Plugins2013-04-10             Introduction to Dart   21
dart2js2013-04-10             Introduction to Dart   22
dart2js2013-04-10             Introduction to Dart   23
dart2js⦿ Target HTML5⦿ Tree Shaking⦿ Aggregation/Minification⦿ Optimization2013-04-10             Introduction to Dart   24
pub2013-04-10         Introduction to Dart   25
pubpubspec.yamlname: pacifista_rocksdescription: The best application in the whole worldversion: 0.0.1dependencies:   grea...
dartdoc/// This is a single-line documentation comment./** * This is a multi-line documentation comment. * To generate the...
dartdoc2013-04-10             Introduction to Dart   28
Dart – The Languagehttps://github.com/yohanbeschi/lang.dart 2013-04-10                         Introduction to Dart   29
Entry Pointvoid main() {}2013-04-10                 Introduction to Dart   30
Commentsvoid main() {  // This is a single-line comment.     /*      * This is a      * multi-line      * comment.      */...
Types - Booleanvar boolean1 = true;var boolean2 = false;bool boolean3 = true;bool boolean4 = false;2013-04-10             ...
Types - StringString singleQuotes = Single quotes.;String doubleQuotes = "Double quotes.";// String interpolationprint(Hel...
Types - Numbersnum integer = 30;print(integer is num: ${integer is num});       // trueprint(integer is int: ${integer is ...
Types - Numbersint realInt = 3;print(realInt is num: ${realInt is num});       // trueprint(realInt is int: ${realInt is i...
Types – ListsList realList = [1, true, String, 5.6e5];// Creating an extendable listList dynamicList = new List();//dynami...
Types – MapsMap realMap = {key: value, 1: 1};Map newMap = new Map();newMap[1] = true;newMap[1] = false;print(newMap);print...
Conditionals – if/elseif (/* condition */) {  //} else if (/* other condition */) {  //} else {  //}2013-04-10            ...
Conditionals – switchswitch(variable) {  case 1:  case 2:   //   break;  case 8:  case 9:   //   break;  default:   //   b...
Loops – For invoid main() {  List<int> list = [1, 2, 3, 4, 5, 6, 7, 8, 9];  int sum = 0;     for (int element in list) {  ...
Functions – Top-level functionsvoid main() {  int squaredNum = square(2);  assert(squaredNum == 4);}int square(int i) {  r...
Functions – First-class functionsvoid main() {  List operation1 = [+, 5, 2];  num result1 = compute(operation1);  assert(r...
Functions – typedefvoid main() {  List operation1 = [+, 5, 2];  int result1 = computeList(operation1);  assert(result1 == ...
Classes abstraitesabstract class Validatable {}2013-04-10              Introduction to Dart   44
Classes abstraitesabstract class Validatable { List<Object> valuesToValidate();}2013-04-10              Introduction to Da...
Classes abstraitesabstract class Validator<T extends Validatable> {}2013-04-10              Introduction to Dart        46
Classes abstraitesabstract class Validator<T extends Validatable> {  bool validate(T object) {     }}2013-04-10           ...
Classes abstraitesabstract class Validator<T extends Validatable> {  bool validate(T object) {    for (Object obj in objec...
Classes abstraitesabstract class Validator<T extends Validatable> {  bool validate(T object) {    for (Object obj in objec...
Classes abstraitesabstract class Validator<T extends Validatable> {  bool validate(T object) {    for (Object obj in objec...
Classes concrètesclass User {}2013-04-10              Introduction to Dart   51
Classes concrètesclass User implements Validatable {}2013-04-10              Introduction to Dart   52
Classes concrètesclass User implements Validatable {  String username;  String password;}2013-04-10              Introduct...
Classes concrètesclass User implements Validatable {  String username;  String password;     User(this.username, this.pass...
Classes concrètesclass User implements Validatable {  String username;  String password;     User(this.username, this.pass...
But there is more…⦿ Mixins⦿ Optionally typed⦿ Top level functions⦿ Mono process2013-04-10              Introduction to Dar...
Dart Reference API⦿ Core                            ⦿ TU et Mocks⦿ HTML                            ⦿ Math⦿ Async          ...
Isolates2013-04-10              Introduction to Dart   58
Uses⦿ Single-page Web Apps⦿ Client and server side applications⦿ HTML Games2013-04-10           Introduction to Dart   59
RoadmapToday : M3                              ?? : M4   Summer 2013 : V1 !2013-04-10             Introduction to Dart    ...
UIs2013-04-10         Introduction to Dart   61
Objectives                                         <ul>                                           <li>School 1</li>       ...
Classesclass School {                                class Grade {  String schoolName;                            String s...
The Old-Fashioned Way2013-04-10              Introduction to Dart   64
The Old-Fashioned Wayvoid main() {  String tree = <ul>;     for (School school in schools) {       tree += <li>${school.sc...
The Old-Fashioned Wayvar grades = school.grades;if (grades != null) {  tree += <ul>;     for (Grade grade in grades) {    ...
The Old-Fashioned Wayvar students = grade.students;if (students != null) {  tree += <ul>;     for (Student student in stud...
The Old-Fashioned Wayvoid main() {                                                        tree += </ul>;  String tree = <u...
Introducing reusable components2013-04-10              Introduction to Dart   69
Is there a pattern here ?var grades = school.grades;if (grades != null) {  tree += <ul>;     for (Grade grade in grades) {...
Is there a pattern here ?var grades = school.grades; if (grades != null) {   tree += <ul>;      tree += </ul>; } 2013-04-1...
Is there a pattern here ?var grades = school.grades; if (grades != null) {   tree += <ul>;      for (Grade grade in grades...
Is there a pattern here ?var grades = school.grades; if (grades != null) {   tree += <ul>;      for (Grade grade in grades...
Recursive PatternString doSomething(/* parameters */) {  String tree = ;    var grades = school.grades;    if (grades != n...
Side note – Functions & sugar syntaxint length(String s) {   return s.length;} 2013-04-10                Introduction to D...
Side note – Functions & sugar syntaxint length(String s) {                int length(String s)   return s.length;         ...
Easy use of reusable componentsvoid main() {  final Tree tree = new Tree(...);} 2013-04-10                Introduction to ...
Easy use of reusable componentsvoid main() {  final Tree tree = new Tree(...);  tree.setData(schools);  tree.addTo(body, a...
Easy use of reusable componentsvoid main() {  final Tree tree = new Tree(     [new TreeConfig((School s) => s.schoolName, ...
Easy use of reusable componentsclass School {                                class Grade {  String schoolName;            ...
Implementing a reusable componentstypedef dynamic Accessor(dynamic data);class TreeConfig {  Accessor _value;  Accessor _c...
Implementing a reusable componentstypedef dynamic Accessor(dynamic data);class TreeConfig {  Accessor _value;  Accessor _c...
Implementing a reusable componentstypedef dynamic Accessor(dynamic data);class TreeConfig {  Accessor _value;  Accessor _c...
Implementing a reusable componentstypedef dynamic Accessor(dynamic data);class TreeConfig {  Accessor _value;  Accessor _c...
Implementing a reusable componentsclass Tree {  List<TreeConfig> treeConfigs;     String tree;     Tree(this.treeConfigs);...
Implementing a reusable componentsclass Tree {  List<TreeConfig> treeConfigs;     String tree;     Tree(this.treeConfigs);...
Implementing a reusable componentsclass Tree {  List<TreeConfig> treeConfigs;     String tree;     Tree(this.treeConfigs);...
Implementing a reusable componentsclass Tree {  List<TreeConfig> treeConfigs;     String tree;     Tree(this.treeConfigs);...
Implementing a reusable componentsclass Tree {  List<TreeConfig> treeConfigs;     String tree;     Tree(this.treeConfigs);...
Implementing a reusable componentsString buildOneLevelTree(final List data,                         final List<TreeConfig>...
Implementing a reusable componentsString buildOneLevelTree(final List data,                         final List<TreeConfig>...
Implementing a reusable componentsString buildOneLevelTree(final List data,                         final List<TreeConfig>...
Implementing a reusable componentsString buildOneLevelTree(final List data, final List<TreeConfig> treeNodes,             ...
Implementing a reusable componentsclass Tree {  List<TreeConfig> treeConfigs;  String tree;    Tree(this.treeConfigs);    ...
Getting ride of StringsElement buildOneLevelTree(final List data, final List<TreeConfig> treeNodes,                       ...
Getting ride of Stringsclass Tree {  List<TreeConfig> treeConfigs;  Element tree; // String tree;    Tree(this.treeConfigs...
web_ui2013-04-10            Introduction to Dart   97
web_ui⦿ Based on HTML5 Web Components Spec⦿ Syntax and uses similar to JSP tags⦿ Template Engine – Compilation needed⦿ Reu...
web_ui and Single-Page Webapps<!DOCTYPE html><html>  <head>    <title>01_web_ui</title>  </head>  <body>    <script type="...
web_ui - The template<!DOCTYPE html><html> <body> </body></html> 2013-04-10                 Introduction to Dart   100
web_ui - The template<!DOCTYPE html><html> <body>  <element>  </element> </body></html> 2013-04-10                 Introdu...
web_ui - The template<!DOCTYPE html><html> <body>  <element name="x-click-counter">  </element> </body></html>  2013-04-10...
web_ui - The template<!DOCTYPE html><html> <body>  <element name="x-click-counter" constructor="CounterComponent">  </elem...
web_ui - The template<!DOCTYPE html><html> <body>  <element name="x-click-counter" constructor="CounterComponent" extends=...
web_ui - The template<!DOCTYPE html><html> <body>  <element name="x-click-counter" constructor="CounterComponent" extends=...
web_ui - The template<!DOCTYPE html><html> <body>  <element name="x-click-counter" constructor="CounterComponent" extends=...
web_ui - The template<!DOCTYPE html><html> <body>  <element name="x-click-counter" constructor="CounterComponent" extends=...
web_ui - The template<!DOCTYPE html><html> <body>  <element name="x-click-counter" constructor="CounterComponent" extends=...
web_ui – Extending WebComponentclass CounterComponent {}    2013-04-10                Introduction to Dart   109
web_ui – Extending WebComponentclass CounterComponent extends WebComponent {}    2013-04-10                    Introductio...
web_ui – Extending WebComponentclass CounterComponent extends WebComponent { @observable int count = 0;}    2013-04-10    ...
web_ui – Extending WebComponentclass CounterComponent extends WebComponent { @observable int count = 0;    void increment(...
web_ui – Extending WebComponentclass CounterComponent extends WebComponent { @observable int count = 0;    void increment(...
web_ui and Single-Page Webapps<!DOCTYPE html><html>  <head>    <title>01_web_ui</title>    <link rel="components" href="xc...
web_ui – The applicationvoid main() {}    2013-04-10                 Introduction to Dart   115
web_ui – The applicationvoid main() {  var element = new Element.html(     <x-click-counter id="click_counter"></x-click-c...
web_ui – The applicationvoid main() {  var element = new Element.html(     <x-click-counter id="click_counter"></x-click-c...
web_ui – The applicationvoid main() {  var element = new Element.html(     <x-click-counter id="click_counter"></x-click-c...
web_ui – The applicationvoid main() {  var element = new Element.html(    <x-click-counter id="click_counter"></x-click-co...
A word about Layouts2013-04-10              Introduction to Dart   120
A word about Layouts2013-04-10              Introduction to Dart   121
A word about Layouts2013-04-10              Introduction to Dart   122
A word about Layouts2013-04-10              Introduction to Dart   123
A word about Layouts2013-04-10              Introduction to Dart   124
A word about Layoutsbuilder()  ..div({id : banner})   ..div({id : head}, Dart Playground)   ..div({id : controls})     ..s...
A word about Layoutsbuilder()  ..div({id : banner})   ..div({id : head}, Dart Playground)   ..div({id : controls})     ..s...
A word about Layoutsbuilder()  ..div({id : banner})   ..div({id : head}, Dart Playground)   ..div({id : controls})     ..s...
A word about Layoutsbuilder()  ..div({id : banner})   ..div({id : head}, Dart Playground)   ..div({id : controls})     ..s...
The Future of Dart ?2013-04-10               Introduction to Dart   129
Want to know more ?DartLangFR        ⦿    Mailing-list : dartlangfr (https://groups.google.com/forum/?fromgroups=&hl=en#!f...
Github⦿ Paris JUG        ⦿    https://github.com/yohanbeschi/parisjug_20130409.dart⦿ DevoxxFR 2013        ⦿    https://git...
What’s next ?        https://github.com/yohanbeschi/soat_20130410.dart2013-04-10                    Introduction to Dart  ...
Questions ?2013-04-10      Introduction to Dart   133
Upcoming SlideShare
Loading in...5
×

Introduction to dart - So@t - 20130410

181

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
181
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
19
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Introduction to dart - So@t - 20130410

  1. 1. DART Yohan BESCHI – Java Developer @yohanbeschi +Yohan Beschi2013-04-10 Introduction to Dart 1
  2. 2. 2013-04-10 Introduction to Dart 2
  3. 3. Building UIs - Javascript ?2013-04-10 Introduction to Dart 3
  4. 4. Building UIs - Java ?2013-04-10 Introduction to Dart 4
  5. 5. Building UIs with Java - But how ?2013-04-10 Introduction to Dart 5
  6. 6. Programmatic Components with GWTCellTable<User> table = new CellTable<User>(); } });TextColumn<User> idColumn = new TextColumn<User>() { columnSortHandler.setComparator(firstNameColumn, @Override new Comparator<Tester.User>() { public String getValue(User user) { public int compare(User o1, User o2) { return user.id; if (o1 == o2) { } return 0;}; }TextColumn<User> firstNameColumn = new TextColumn<User>() { if (o1 != null) { @Override return (o2 != null) ? o1.firstName.compareTo(o2.firstName) : 1; public String getValue(User user) { } return user.firstName; return -1; } }}; }); columnSortHandler.setComparator(lasteNameColumn,TextColumn<User> lastNameColumn = new TextColumn<User>() { new Comparator<Tester.User>() { @Override public int compare(User o1, User o2) { public String getValue(User user) { if (o1 == o2) { return user.lastName; return 0; } }}; if (o1 != null) {TextColumn<User> ageColumn = new TextColumn<User>() { return (o2 != null) ? o1.lasteName.compareTo(o2.lasteName) : 1; @Override } public String getValue(User user) { return -1; return user.age; } } });}; columnSortHandler.setComparator(ageColumn, new Comparator<Tester.User>() {idColumn.setSortable(true); public int compare(User o1, User o2) {firstNameColumn.setSortable(true); if (o1 == o2) {lastNameColumn.setSortable(true); return 0;ageColumn.setSortable(true); }table.addColumn(idColumn, "ID"); if (o1 != null) {table.addColumn(firstNameColumn, "First name"); return (o2 != null) ? o1.age.compareTo(o2.age) : 1;table.addColumn(lastNameColumn, "Lats name"); }table.addColumn(ageColumn, "Age"); return -1; }ListDataProvider<User> dataProvider = new ListDataProvider<User>(); });dataProvider.addDataDisplay(table); table.addColumnSortHandler(columnSortHandler); table.getColumnSortList().push(firstNameColumn);List<User> list = dataProvider.getList();for (User user : USERS) { list.add(user);}ListHandler<User> columnSortHandler = new ListHandler<Tester.User>(list);columnSortHandler.setComparator(idColumn, new Comparator<Tester.User>() { public int compare(User o1, User o2) { if (o1 == o2) { return 0; } if (o1 != null) { return (o2 != null) ? o1.id.compareTo(o2.id) : 1; } return -1;2013-04-10 Introduction to Dart 6
  7. 7. Programmatic Components with GWTCellTable<User> table = new CellTable<User>(); } });TextColumn<User> idColumn = new TextColumn<User>() { columnSortHandler.setComparator(firstNameColumn, @Override new Comparator<Tester.User>() { public String getValue(User user) { public int compare(User o1, User o2) { return user.id; if (o1 == o2) { } return 0;}; }TextColumn<User> firstNameColumn = new TextColumn<User>() { if (o1 != null) { @Override return (o2 != null) ? o1.firstName.compareTo(o2.firstName) : 1; public String getValue(User user) { } return user.firstName; return -1; } }}; }); columnSortHandler.setComparator(lasteNameColumn,TextColumn<User> lastNameColumn = new TextColumn<User>() { new Comparator<Tester.User>() { @Override public int compare(User o1, User o2) { public String getValue(User user) { if (o1 == o2) { return user.lastName; return 0; } }}; if (o1 != null) {TextColumn<User> ageColumn = new TextColumn<User>() { return (o2 != null) ? o1.lasteName.compareTo(o2.lasteName) : 1; @Override } public String getValue(User user) { return -1; return user.age; } } });}; columnSortHandler.setComparator(ageColumn, new Comparator<Tester.User>() {idColumn.setSortable(true); public int compare(User o1, User o2) {firstNameColumn.setSortable(true); if (o1 == o2) {lastNameColumn.setSortable(true); return 0;ageColumn.setSortable(true); }table.addColumn(idColumn, "ID"); if (o1 != null) {table.addColumn(firstNameColumn, "First name"); return (o2 != null) ? o1.age.compareTo(o2.age) : 1;table.addColumn(lastNameColumn, "Lats name"); }table.addColumn(ageColumn, "Age"); return -1; }ListDataProvider<User> dataProvider = new ListDataProvider<User>(); });dataProvider.addDataDisplay(table); table.addColumnSortHandler(columnSortHandler); table.getColumnSortList().push(firstNameColumn);List<User> list = dataProvider.getList();for (User user : USERS) { list.add(user);}ListHandler<User> columnSortHandler = new ListHandler<Tester.User>(list);columnSortHandler.setComparator(idColumn, new Comparator<Tester.User>() { public int compare(User o1, User o2) { if (o1 == o2) { return 0; } if (o1 != null) { return (o2 != null) ? o1.id.compareTo(o2.id) : 1; } return -1;2013-04-10 Introduction to Dart 7
  8. 8. The Dart WayTable<User> table = new Table (sorting:true) ..addColumn(ID, new TextCell((User o) => o.id)) ..addColumn(First name, new TextCell((User o) => o.firstName)) ..addColumn(Last name, new TextCell((User o) => o.lastName)) ..addColumn(Age, new TextCell((User o) => o.age)) ..setData(objs);2013-04-10 Introduction to Dart 8
  9. 9. The Dart WayTable<User> table = new Table (sorting:true) ..addColumn(ID, new TextCell((User o) => o.id)) ..addColumn(First name, new TextCell((User o) => o.firstName)) ..addColumn(Last name, new TextCell((User o) => o.lastName)) ..addColumn(Age, new TextCell((User o) => o.age)) ..setData(objs); 6 lines2013-04-10 Introduction to Dart 9
  10. 10. Dart is the winner2013-04-10 Introduction to Dart 10
  11. 11. Once upon a time…2013-04-10 Introduction to Dart 11
  12. 12. Programmer productivity2013-04-10 Introduction to Dart 12
  13. 13. Application scalability2013-04-10 Introduction to Dart 13
  14. 14. Raw execution speed2013-04-10 Introduction to Dart 14
  15. 15. Startup performance2013-04-10 Introduction to Dart 15
  16. 16. And here we are!⦿ Open Source (BSD)⦿ Structured⦿ Anti-Revolutionary⦿ Same goals as new Javascript frameworks⦿ The goal is to not break the web2013-04-10 Introduction to Dart 16
  17. 17. Dart Ecosystem Dart Editor Dartium Tools dart2js pub Dart dartdoc Server dart:io VMs Browser dart:html2013-04-10 Introduction to Dart 17
  18. 18. Virtual Machines2013-04-10 Introduction to Dart 18
  19. 19. Dartium2013-04-10 Introduction to Dart 19
  20. 20. DartEditor2013-04-10 Introduction to Dart 20
  21. 21. Plugins2013-04-10 Introduction to Dart 21
  22. 22. dart2js2013-04-10 Introduction to Dart 22
  23. 23. dart2js2013-04-10 Introduction to Dart 23
  24. 24. dart2js⦿ Target HTML5⦿ Tree Shaking⦿ Aggregation/Minification⦿ Optimization2013-04-10 Introduction to Dart 24
  25. 25. pub2013-04-10 Introduction to Dart 25
  26. 26. pubpubspec.yamlname: pacifista_rocksdescription: The best application in the whole worldversion: 0.0.1dependencies: great_lib: any2013-04-10 Introduction to Dart 26
  27. 27. dartdoc/// This is a single-line documentation comment./** * This is a multi-line documentation comment. * To generate the documentation: * $ dartdoc <filename> */void main() {}2013-04-10 Introduction to Dart 27
  28. 28. dartdoc2013-04-10 Introduction to Dart 28
  29. 29. Dart – The Languagehttps://github.com/yohanbeschi/lang.dart 2013-04-10 Introduction to Dart 29
  30. 30. Entry Pointvoid main() {}2013-04-10 Introduction to Dart 30
  31. 31. Commentsvoid main() { // This is a single-line comment. /* * This is a * multi-line * comment. */}2013-04-10 Introduction to Dart 31
  32. 32. Types - Booleanvar boolean1 = true;var boolean2 = false;bool boolean3 = true;bool boolean4 = false;2013-04-10 Introduction to Dart 32
  33. 33. Types - StringString singleQuotes = Single quotes.;String doubleQuotes = "Double quotes.";// String interpolationprint(Hello $singleQuotes ${doubleQuotes.toUpperCase()});// Multi-line Stringprint(With triple simple quotes I can define a string over multiple lines);// Raw Stringprint(rHello n $singleQuotes ${doubleQuotes.toUpperCase()});2013-04-10 Introduction to Dart 33
  34. 34. Types - Numbersnum integer = 30;print(integer is num: ${integer is num}); // trueprint(integer is int: ${integer is int}); // trueprint(integer is double: ${integer is double}); // falsenum intgerToo = 3.0;print(intgerToo is num: ${intgerToo is num}); // trueprint(intgerToo is int: ${intgerToo is int}); // trueprint(intgerToo is double: ${intgerToo is double}); // falsenum doubl = 1.1;print(doubl is num: ${doubl is num}); // trueprint(doubl is int: ${doubl is int}); // falseprint(doubl is double: ${doubl is double}); // true2013-04-10 Introduction to Dart 34
  35. 35. Types - Numbersint realInt = 3;print(realInt is num: ${realInt is num}); // trueprint(realInt is int: ${realInt is int}); // trueprint(realInt is double: ${realInt is double}); // falsedouble realDouble = 1.1;print(realDouble is num: ${realDouble is num}); // trueprint(realDouble is int: ${realDouble is int}); // falseprint(realDouble is double: ${realDouble is double}); // true2013-04-10 Introduction to Dart 35
  36. 36. Types – ListsList realList = [1, true, String, 5.6e5];// Creating an extendable listList dynamicList = new List();//dynamicList[0] = 1; // throws an exceptiondynamicList.add(1);dynamicList.add(true);dynamicList.add(String);dynamicList.add(5.6e5);// Creating an empty fixed size list// List fixedList = [null, null, null, null];List fixedList = new List(4);//fixedList.add(1); // throws an ExceptionfixedList[0] = 1;fixedList[1] = true;fixedList[2] = String;fixedList[3] = 5.6e5;2013-04-10 Introduction to Dart 36
  37. 37. Types – MapsMap realMap = {key: value, 1: 1};Map newMap = new Map();newMap[1] = true;newMap[1] = false;print(newMap);print(${newMap[1]} ${newMap[1]});Map<String, int> genericMap = new Map();genericMap[one] = 1;genericMap[2] = 2; // Warning, but doesnt really matterprint(genericMap);2013-04-10 Introduction to Dart 37
  38. 38. Conditionals – if/elseif (/* condition */) { //} else if (/* other condition */) { //} else { //}2013-04-10 Introduction to Dart 38
  39. 39. Conditionals – switchswitch(variable) { case 1: case 2: // break; case 8: case 9: // break; default: // break;}2013-04-10 Introduction to Dart 39
  40. 40. Loops – For invoid main() { List<int> list = [1, 2, 3, 4, 5, 6, 7, 8, 9]; int sum = 0; for (int element in list) { sum += element; } assert(sum == 45);}2013-04-10 Introduction to Dart 40
  41. 41. Functions – Top-level functionsvoid main() { int squaredNum = square(2); assert(squaredNum == 4);}int square(int i) { return i * i;}2013-04-10 Introduction to Dart 41
  42. 42. Functions – First-class functionsvoid main() { List operation1 = [+, 5, 2]; num result1 = compute(operation1); assert(result1 == 7);}num compute(List operation) { Function operator = findOperator(operation[0]); double left = double.parse(operation[1]); double right = double.parse(operation[2]); return operator(left, right);}2013-04-10 Introduction to Dart 42
  43. 43. Functions – typedefvoid main() { List operation1 = [+, 5, 2]; int result1 = computeList(operation1); assert(result1 == 7);}typedef int Operator(num left, num right);int computeList(List operation) { Operator operator = findOperator(operation[0]); int left = int.parse(operation[1]); int right = int.parse(operation[2]); return operator(left, right);}2013-04-10 Introduction to Dart 43
  44. 44. Classes abstraitesabstract class Validatable {}2013-04-10 Introduction to Dart 44
  45. 45. Classes abstraitesabstract class Validatable { List<Object> valuesToValidate();}2013-04-10 Introduction to Dart 45
  46. 46. Classes abstraitesabstract class Validator<T extends Validatable> {}2013-04-10 Introduction to Dart 46
  47. 47. Classes abstraitesabstract class Validator<T extends Validatable> { bool validate(T object) { }}2013-04-10 Introduction to Dart 47
  48. 48. Classes abstraitesabstract class Validator<T extends Validatable> { bool validate(T object) { for (Object obj in object.valuesToValidate()) { } }}2013-04-10 Introduction to Dart 48
  49. 49. Classes abstraitesabstract class Validator<T extends Validatable> { bool validate(T object) { for (Object obj in object.valuesToValidate()) { if (StringUtils.isEmpty(obj.toString())) { } } }}2013-04-10 Introduction to Dart 49
  50. 50. Classes abstraitesabstract class Validator<T extends Validatable> { bool validate(T object) { for (Object obj in object.valuesToValidate()) { if (StringUtils.isEmpty(obj.toString())) { return false; } } return true; }}2013-04-10 Introduction to Dart 50
  51. 51. Classes concrètesclass User {}2013-04-10 Introduction to Dart 51
  52. 52. Classes concrètesclass User implements Validatable {}2013-04-10 Introduction to Dart 52
  53. 53. Classes concrètesclass User implements Validatable { String username; String password;}2013-04-10 Introduction to Dart 53
  54. 54. Classes concrètesclass User implements Validatable { String username; String password; User(this.username, this.password);}2013-04-10 Introduction to Dart 54
  55. 55. Classes concrètesclass User implements Validatable { String username; String password; User(this.username, this.password); List<Object> valuesToValidate() { return [username, password]; }}2013-04-10 Introduction to Dart 55
  56. 56. But there is more…⦿ Mixins⦿ Optionally typed⦿ Top level functions⦿ Mono process2013-04-10 Introduction to Dart 56
  57. 57. Dart Reference API⦿ Core ⦿ TU et Mocks⦿ HTML ⦿ Math⦿ Async ⦿ Logging⦿ IO ⦿ URI⦿ Crypto ⦿ I18N⦿ JSON ⦿ etc.⦿ Mirrors⦿ UTF2013-04-10 Introduction to Dart 57
  58. 58. Isolates2013-04-10 Introduction to Dart 58
  59. 59. Uses⦿ Single-page Web Apps⦿ Client and server side applications⦿ HTML Games2013-04-10 Introduction to Dart 59
  60. 60. RoadmapToday : M3 ?? : M4 Summer 2013 : V1 !2013-04-10 Introduction to Dart 60
  61. 61. UIs2013-04-10 Introduction to Dart 61
  62. 62. Objectives <ul> <li>School 1</li> <li>School 2 <ul> <li>Grade 2.1</li> <li>Grade 2.2 <ul> <li>Person 2.2.1</li> <li>Person 2.2.2</li> </ul> </li> </ul> </li> <li>School 3 <ul> <li>Grade 3.1</li> </ul> </li> <li>School 4</li> </ul>2013-04-10 Introduction to Dart 62
  63. 63. Classesclass School { class Grade { String schoolName; String schoolGrade; List<Grade> grades; List<Student> students; School(this.schoolName, Grade(this.schoolGrade, [this.grades]); [this.students]);} } class Student { String firstname; String lastname; Student(this.firstname, this.lastname); }2013-04-10 Introduction to Dart 63
  64. 64. The Old-Fashioned Way2013-04-10 Introduction to Dart 64
  65. 65. The Old-Fashioned Wayvoid main() { String tree = <ul>; for (School school in schools) { tree += <li>${school.schoolName}; // Grades tree += </li>; } tree += </ul>; query(body).insertAdjacentHtml(afterBegin, tree);} 2013-04-10 Introduction to Dart 65
  66. 66. The Old-Fashioned Wayvar grades = school.grades;if (grades != null) { tree += <ul>; for (Grade grade in grades) { tree += <li>${grade.schoolGrade}; // Students tree += </li>; } tree += </ul>;} 2013-04-10 Introduction to Dart 66
  67. 67. The Old-Fashioned Wayvar students = grade.students;if (students != null) { tree += <ul>; for (Student student in students) { tree += <li>${student.firstname} ${student.lastname}</li>; } tree += </ul>;} 2013-04-10 Introduction to Dart 67
  68. 68. The Old-Fashioned Wayvoid main() { tree += </ul>; String tree = <ul>; } for (School school in schools) { tree += </li>; tree += <li>${school.schoolName}; } var grades = school.grades; tree += </ul>; if (grades != null) { tree += <ul>; query(body) .insertAdjacentHtml(afterBegin, tree); for (Grade grade in grades) { } tree += <li>${grade.schoolGrade}; var students = grade.students; if (students != null) { tree += <ul>; for (Student student in students) { tree += <li>${student.firstname} ${student.lastname}</li>; } tree += </ul>; } tree += </li>; } 2013-04-10 Introduction to Dart 68
  69. 69. Introducing reusable components2013-04-10 Introduction to Dart 69
  70. 70. Is there a pattern here ?var grades = school.grades;if (grades != null) { tree += <ul>; for (Grade grade in grades) { tree += <li>${grade.schoolGrade}; // Students tree += </li>; } tree += </ul>;} 2013-04-10 Introduction to Dart 70
  71. 71. Is there a pattern here ?var grades = school.grades; if (grades != null) { tree += <ul>; tree += </ul>; } 2013-04-10 Introduction to Dart 71
  72. 72. Is there a pattern here ?var grades = school.grades; if (grades != null) { tree += <ul>; for (Grade grade in grades) { tree += <li>${grade.schoolGrade}; tree += </li>; } tree += </ul>; } 2013-04-10 Introduction to Dart 72
  73. 73. Is there a pattern here ?var grades = school.grades; if (grades != null) { tree += <ul>; for (Grade grade in grades) { tree += <li>${grade.schoolGrade}; // Do the same with children tree += </li>; } tree += </ul>; } 2013-04-10 Introduction to Dart 73
  74. 74. Recursive PatternString doSomething(/* parameters */) { String tree = ; var grades = school.grades; if (grades != null) { tree += <ul>; for (Grade grade in grades) { tree += <li>${grade.schoolGrade}; tree += doSomething(/* parameters */); tree += </li>; } tree += </ul>; } return tree;} 2013-04-10 Introduction to Dart 74
  75. 75. Side note – Functions & sugar syntaxint length(String s) { return s.length;} 2013-04-10 Introduction to Dart 75
  76. 76. Side note – Functions & sugar syntaxint length(String s) { int length(String s) return s.length; => s.length;} 2013-04-10 Introduction to Dart 76
  77. 77. Easy use of reusable componentsvoid main() { final Tree tree = new Tree(...);} 2013-04-10 Introduction to Dart 77
  78. 78. Easy use of reusable componentsvoid main() { final Tree tree = new Tree(...); tree.setData(schools); tree.addTo(body, afterBegin);} 2013-04-10 Introduction to Dart 78
  79. 79. Easy use of reusable componentsvoid main() { final Tree tree = new Tree( [new TreeConfig((School s) => s.schoolName, (School s) => s.grades), new TreeConfig((Grade g) => g.schoolGrade, (Grade g) => g.students), new TreeConfig((Student s) => ${s.firstname} ${s.lastname})] ); tree.setData(schools); tree.addTo(body, afterBegin);} 2013-04-10 Introduction to Dart 79
  80. 80. Easy use of reusable componentsclass School { class Grade { String schoolName; String schoolGrade; List<Grade> grades; List<Student> students; School(this.schoolName, Grade(this.schoolGrade, [this.grades]); [this.students]);} } class Student{ String firstname; String lastname; Student(this.firstname, this.lastname); }2013-04-10 Introduction to Dart 80
  81. 81. Implementing a reusable componentstypedef dynamic Accessor(dynamic data);class TreeConfig { Accessor _value; Accessor _children; TreeConfig(Accessor this._value, [Accessor this._children]); Accessor get value => _value; Accessor get children => _children;} 2013-04-10 Introduction to Dart 81
  82. 82. Implementing a reusable componentstypedef dynamic Accessor(dynamic data);class TreeConfig { Accessor _value; Accessor _children; TreeConfig(Accessor this._value, [Accessor this._children]); Accessor get value => _value; Accessor get children => _children;} 2013-04-10 Introduction to Dart 82
  83. 83. Implementing a reusable componentstypedef dynamic Accessor(dynamic data);class TreeConfig { Accessor _value; Accessor _children; TreeConfig(Accessor this._value, [Accessor this._children]); Accessor get value => _value; Accessor get children => _children;} 2013-04-10 Introduction to Dart 83
  84. 84. Implementing a reusable componentstypedef dynamic Accessor(dynamic data);class TreeConfig { Accessor _value; Accessor _children; TreeConfig(Accessor this._value, [Accessor this._children]); Accessor get value => _value; Accessor get children => _children;} 2013-04-10 Introduction to Dart 84
  85. 85. Implementing a reusable componentsclass Tree { List<TreeConfig> treeConfigs; String tree; Tree(this.treeConfigs); String setData(final List data) { // Build tree } void addTo(String selector, [String where = afterEnd]) { query(selector).insertAdjacentHtml(where, this.tree); }} 2013-04-10 Introduction to Dart 85
  86. 86. Implementing a reusable componentsclass Tree { List<TreeConfig> treeConfigs; String tree; Tree(this.treeConfigs); String setData(final List data) { // Build tree } void addTo(String selector, [String where = afterEnd]) { query(selector).insertAdjacentHtml(where, this.tree); }} 2013-04-10 Introduction to Dart 86
  87. 87. Implementing a reusable componentsclass Tree { List<TreeConfig> treeConfigs; String tree; Tree(this.treeConfigs); String setData(final List data) { // Build tree } void addTo(String selector, [String where = afterEnd]) { query(selector).insertAdjacentHtml(where, this.tree); }} 2013-04-10 Introduction to Dart 87
  88. 88. Implementing a reusable componentsclass Tree { List<TreeConfig> treeConfigs; String tree; Tree(this.treeConfigs); String setData(final List data) { // Build tree } void addTo(String selector, [String where = afterEnd]) { query(selector).insertAdjacentHtml(where, this.tree); }} 2013-04-10 Introduction to Dart 88
  89. 89. Implementing a reusable componentsclass Tree { List<TreeConfig> treeConfigs; String tree; Tree(this.treeConfigs); String setData(final List data) { // Build tree } void addTo(String selector, [String where = afterEnd]) { query(selector).insertAdjacentHtml(where, this.tree); }} 2013-04-10 Introduction to Dart 89
  90. 90. Implementing a reusable componentsString buildOneLevelTree(final List data, final List<TreeConfig> treeNodes, [final int depth = 0]) { String tree = ; if (data != null && !data.isEmpty) { } return tree;} 2013-04-10 Introduction to Dart 90
  91. 91. Implementing a reusable componentsString buildOneLevelTree(final List data, final List<TreeConfig> treeNodes, [final int depth = 0]) { String tree = ; if (data != null && !data.isEmpty) { final TreeConfig treeNode = treeNodes[depth]; tree += <ul>; for (dynamic element in data) { } tree += </ul>; } return tree;} 2013-04-10 Introduction to Dart 91
  92. 92. Implementing a reusable componentsString buildOneLevelTree(final List data, final List<TreeConfig> treeNodes, [final int depth = 0]) { String tree = ; if (data != null && !data.isEmpty) { final TreeConfig treeNode = treeNodes[depth]; tree += <ul>; for (dynamic element in data) { tree += <li>${treeNode.value(element)}; tree += </li>; } tree += </ul>; } return tree;} 2013-04-10 Introduction to Dart 92
  93. 93. Implementing a reusable componentsString buildOneLevelTree(final List data, final List<TreeConfig> treeNodes, [final int depth = 0]) { String tree = ; if (data != null && !data.isEmpty) { final TreeConfig treeNode = treeNodes[depth]; tree += <ul>; for (dynamic element in data) { tree += <li>${treeNode.value(element)}; if (treeNode.children != null) { tree += buildOneLevelTree(treeNode.children(element), treeNodes, depth + 1); } tree += </li>; } tree += </ul>; } return tree;} 2013-04-10 Introduction to Dart 93
  94. 94. Implementing a reusable componentsclass Tree { List<TreeConfig> treeConfigs; String tree; Tree(this.treeConfigs); String setData(final List data) { this.tree = buildOneLevelTree(data, this.treeConfigs); return this.tree; } String buildOneLevelTree(final List data, final List<TreeConfig> treeNodes, [final int depth = 0]) { // Implementation } void addTo(String selector, [String where = afterEnd]) { query(selector).insertAdjacentHtml(where, this.tree); }} 2013-04-10 Introduction to Dart 94
  95. 95. Getting ride of StringsElement buildOneLevelTree(final List data, final List<TreeConfig> treeNodes, [final int depth = 0]) { Element tree; // String tree = ; if (data != null && !data.isEmpty) { final TreeConfig treeNode = treeNodes[depth]; tree = new UListElement(); // tree += <ul>; for (dynamic element in data) { final LIElement li = new LIElement(); // <li>; li.text = treeNode.value(element); // ${treeNode.value(element)} if (treeNode.children != null) { final UListElement ulChild = // buildOneLevelTree(treeNode.children(element), treeNodes, depth + 1); if (ulChild != null) { // li.append(ulChild); // tree += buildOneLevelTree(...) } // } tree.append(li); // tree += <li>${treeNode.value(element)}; } } return tree;} 2013-04-10 Introduction to Dart 95
  96. 96. Getting ride of Stringsclass Tree { List<TreeConfig> treeConfigs; Element tree; // String tree; Tree(this.treeConfigs); Element setData(final List data) { this.tree = buildOneLevelTree(data, this.treeConfigs); return this.tree; } Element buildOneLevelTree(final List data, final List<TreeConfig> treeNodes, [final int depth = 0]) { // Implementation } void addTo(String selector, [String where = afterEnd]) { query(selector).insertAdjacentElement(where, this.tree); }} 2013-04-10 Introduction to Dart 96
  97. 97. web_ui2013-04-10 Introduction to Dart 97
  98. 98. web_ui⦿ Based on HTML5 Web Components Spec⦿ Syntax and uses similar to JSP tags⦿ Template Engine – Compilation needed⦿ Reusable components⦿ CSS encapsulation⦿ Data-binding⦿ Complex for real life use-cases⦿ Doesn’t solve layouting problems2013-04-10 Introduction to Dart 98
  99. 99. web_ui and Single-Page Webapps<!DOCTYPE html><html> <head> <title>01_web_ui</title> </head> <body> <script type="application/dart" src="01_web_ui.dart"> </script> <script src="packages/browser/dart.js"></script> </body></html> 2013-04-10 Introduction to Dart 99
  100. 100. web_ui - The template<!DOCTYPE html><html> <body> </body></html> 2013-04-10 Introduction to Dart 100
  101. 101. web_ui - The template<!DOCTYPE html><html> <body> <element> </element> </body></html> 2013-04-10 Introduction to Dart 101
  102. 102. web_ui - The template<!DOCTYPE html><html> <body> <element name="x-click-counter"> </element> </body></html> 2013-04-10 Introduction to Dart 102
  103. 103. web_ui - The template<!DOCTYPE html><html> <body> <element name="x-click-counter" constructor="CounterComponent"> </element> </body></html> 2013-04-10 Introduction to Dart 103
  104. 104. web_ui - The template<!DOCTYPE html><html> <body> <element name="x-click-counter" constructor="CounterComponent" extends="div"> </element> </body></html> 2013-04-10 Introduction to Dart 104
  105. 105. web_ui - The template<!DOCTYPE html><html> <body> <element name="x-click-counter" constructor="CounterComponent" extends="div"> <template> </template> </element> </body></html> 2013-04-10 Introduction to Dart 105
  106. 106. web_ui - The template<!DOCTYPE html><html> <body> <element name="x-click-counter" constructor="CounterComponent" extends="div"> <template> <div> <button>Click me</button><br /> <span>(click count: {{count}})</span> </div> </template> </element> </body></html> 2013-04-10 Introduction to Dart 106
  107. 107. web_ui - The template<!DOCTYPE html><html> <body> <element name="x-click-counter" constructor="CounterComponent" extends="div"> <template> <div> <button>Click me</button><br /> <span>(click count: {{count}})</span> </div> </template> </element> </body></html> 2013-04-10 Introduction to Dart 107
  108. 108. web_ui - The template<!DOCTYPE html><html> <body> <element name="x-click-counter" constructor="CounterComponent" extends="div"> <template> <div> <button>Click me</button><br /> <span>(click count: {{count}})</span> </div> </template> <script type="application/dart" src="xclickcounter.dart"></script> </element> </body></html> 2013-04-10 Introduction to Dart 108
  109. 109. web_ui – Extending WebComponentclass CounterComponent {} 2013-04-10 Introduction to Dart 109
  110. 110. web_ui – Extending WebComponentclass CounterComponent extends WebComponent {} 2013-04-10 Introduction to Dart 110
  111. 111. web_ui – Extending WebComponentclass CounterComponent extends WebComponent { @observable int count = 0;} 2013-04-10 Introduction to Dart 111
  112. 112. web_ui – Extending WebComponentclass CounterComponent extends WebComponent { @observable int count = 0; void increment(Event event) { count++; }} 2013-04-10 Introduction to Dart 112
  113. 113. web_ui – Extending WebComponentclass CounterComponent extends WebComponent { @observable int count = 0; void increment(Event event) { count++; } void inserted() { this.query(button).onClick.listen(increment); }} 2013-04-10 Introduction to Dart 113
  114. 114. web_ui and Single-Page Webapps<!DOCTYPE html><html> <head> <title>01_web_ui</title> <link rel="components" href="xclickcounter.html"> </head> <body> <script type="application/dart" src="01_web_ui.dart"> </script> <script src="packages/browser/dart.js"></script> </body></html> 2013-04-10 Introduction to Dart 114
  115. 115. web_ui – The applicationvoid main() {} 2013-04-10 Introduction to Dart 115
  116. 116. web_ui – The applicationvoid main() { var element = new Element.html( <x-click-counter id="click_counter"></x-click-counter> );} 2013-04-10 Introduction to Dart 116
  117. 117. web_ui – The applicationvoid main() { var element = new Element.html( <x-click-counter id="click_counter"></x-click-counter> ); var counter = new CounterComponent() ..host = element ..count = 25;} 2013-04-10 Introduction to Dart 117
  118. 118. web_ui – The applicationvoid main() { var element = new Element.html( <x-click-counter id="click_counter"></x-click-counter> ); var counter = new CounterComponent() ..host = element ..count = 25; var lifecycleCaller = new ComponentItem(counter) ..create(); query(body).append(counter.host); lifecycleCaller.insert();} 2013-04-10 Introduction to Dart 118
  119. 119. web_ui – The applicationvoid main() { var element = new Element.html( <x-click-counter id="click_counter"></x-click-counter> ); var counter = new CounterComponent() ..host = element ..count = 25; var lifecycleCaller = new ComponentItem(counter)..create(); query(body).append(counter.host); lifecycleCaller.insert(); var button = new ButtonElement() ..text = Update ..onClick.listen((e) { counter.count = 100; watchers.dispatch(); }); query(body).append(button);} 2013-04-10 Introduction to Dart 119
  120. 120. A word about Layouts2013-04-10 Introduction to Dart 120
  121. 121. A word about Layouts2013-04-10 Introduction to Dart 121
  122. 122. A word about Layouts2013-04-10 Introduction to Dart 122
  123. 123. A word about Layouts2013-04-10 Introduction to Dart 123
  124. 124. A word about Layouts2013-04-10 Introduction to Dart 124
  125. 125. A word about Layoutsbuilder() ..div({id : banner}) ..div({id : head}, Dart Playground) ..div({id : controls}) ..span(null, Environment: ) ..addElement(listboxEnv) ..addElement(runButton) ..end() // controls ..end() // banner ..div({id:wrap}) ..addElement(e(linedTextarea.element)) ..end() // wraps ..addElement(output); 2013-04-10 Introduction to Dart 125
  126. 126. A word about Layoutsbuilder() ..div({id : banner}) ..div({id : head}, Dart Playground) ..div({id : controls}) ..span(null, Environment: ) ..addElement(listboxEnv) ..addElement(runButton) ..end() // controls ..end() // banner ..div({id:wrap}) ..addElement(e(linedTextarea.element)) ..end() // wraps ..addElement(output); 2013-04-10 Introduction to Dart 126
  127. 127. A word about Layoutsbuilder() ..div({id : banner}) ..div({id : head}, Dart Playground) ..div({id : controls}) ..span(null, Environment: ) ..addElement(listboxEnv) ..addElement(runButton) ..end() // controls ..end() // banner ..div({id:wrap}) ..addElement(e(linedTextarea.element)) ..end() // wraps ..addElement(output); 2013-04-10 Introduction to Dart 127
  128. 128. A word about Layoutsbuilder() ..div({id : banner}) ..div({id : head}, Dart Playground) ..div({id : controls}) ..span(null, Environment: ) ..addElement(listboxEnv) ..addElement(runButton) ..end() // controls ..end() // banner ..div({id:wrap}) ..addElement(e(linedTextarea.element)) ..end() // wraps ..addElement(output); 2013-04-10 Introduction to Dart 128
  129. 129. The Future of Dart ?2013-04-10 Introduction to Dart 129
  130. 130. Want to know more ?DartLangFR ⦿ Mailing-list : dartlangfr (https://groups.google.com/forum/?fromgroups=&hl=en#!forum/dartlangfr) ⦿ Google+ : DartlangFR (https://plus.google.com/u/0/communities/104813951711720144450) ⦿ Twitter : @dartlang_fr ⦿ Blog : dartlangfr.netDartLang ⦿ Official website: www.dartlang.org ⦿ Mailing-list : dartlang (https://groups.google.com/a/dartlang.org/forum/?fromgroups&hl=en#!forum/misc) ⦿ Google+ : Dart (https://plus.google.com/+dartlang) ⦿ Google+ : Dartisans (https://plus.google.com/communities/114566943291919232850) ⦿ Twitter : @dart_lang ⦿ Blog : blog.dartwatch.com ⦿ Newsletter : Dart weekly2013-04-10 Introduction to Dart 130
  131. 131. Github⦿ Paris JUG ⦿ https://github.com/yohanbeschi/parisjug_20130409.dart⦿ DevoxxFR 2013 ⦿ https://github.com/yohanbeschi/devoxxfr_20130327.dart⦿ Widgets ⦿ https://github.com/yohanbeschi/pwt_proto.dart⦿ Web Editor for Dart ⦿ https://github.com/yohanbeschi/web_editor.dart2013-04-10 Introduction to Dart 131
  132. 132. What’s next ? https://github.com/yohanbeschi/soat_20130410.dart2013-04-10 Introduction to Dart 132
  133. 133. Questions ?2013-04-10 Introduction to Dart 133
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×