Part 1 - Introduction à Dart
Dart s'inscrit dans la mouvance des frameworks JavaScript (Node.js, Backbone, AngularJS, etc,) et des langages compilés en JavaScript (CoffeeScript, TypeScipt, etc.) dans l'objectif de faciliter le développement Web.
Les applications Web sont depuis quelques années le type d'application privilégié des développeurs. Néanmoins, les outils que nous possédions jusqu'à très récemment n'étaient absolument pas adaptés au monde professionnel.
Dart offre la possibilité de développer, dans un langage structuré et objet, des applications clients et serveurs, et ceci en un temps record.
Mais Dart n'est pas seulement un langage c'est aussi tout un écosystème au service de l'industrialisation.
Au cours de cette présentation nous verrons :
• comment Dart permet de développer des applications clientes aussi bien que serveurs,
• quelques éléments du langage,
• mais aussi les outils permettant un développement industrialisé et une productivité accrue
Durée : 45min/1h
Part 2 - Live Coding - Développer une application à page unique en Dart
Bien que la version finale de Dart ne soit pas encore disponible (pour cela il faudra attendre cet été), il est utilisable dès aujourd'hui. Et c'est ce que nous verrons au cours de cette deuxième partie en nous appuyant sur une application simple.
Durée : 45min/1h
16. And here we are!
⦿ Open Source (BSD)
⦿ Structured
⦿ Anti-Revolutionary
⦿ Same goals as new Javascript frameworks
⦿ The goal is to not break the web
2013-04-10 Introduction to Dart 16
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
31. Comments
void main() {
// This is a single-line comment.
/*
* This is a
* multi-line
* comment.
*/
}
2013-04-10 Introduction to Dart 31
32. Types - Boolean
var boolean1 = true;
var boolean2 = false;
bool boolean3 = true;
bool boolean4 = false;
2013-04-10 Introduction to Dart 32
33. Types - String
String singleQuotes = 'Single quotes.';
String doubleQuotes = "Double quotes.";
// String interpolation
print('Hello $singleQuotes ${doubleQuotes.toUpperCase()}');
// Multi-line String
print('''With
triple simple quotes
I can define
a string
over multiple
lines''');
// Raw String
print(r'Hello n $singleQuotes ${doubleQuotes.toUpperCase()}');
2013-04-10 Introduction to Dart 33
34. Types - Numbers
num integer = 30;
print('integer is num: ${integer is num}'); // true
print('integer is int: ${integer is int}'); // true
print('integer is double: ${integer is double}'); // false
num intgerToo = 3.0;
print('intgerToo is num: ${intgerToo is num}'); // true
print('intgerToo is int: ${intgerToo is int}'); // true
print('intgerToo is double: ${intgerToo is double}'); // false
num doubl = 1.1;
print('doubl is num: ${doubl is num}'); // true
print('doubl is int: ${doubl is int}'); // false
print('doubl is double: ${doubl is double}'); // true
2013-04-10 Introduction to Dart 34
35. Types - Numbers
int realInt = 3;
print('realInt is num: ${realInt is num}'); // true
print('realInt is int: ${realInt is int}'); // true
print('realInt is double: ${realInt is double}'); // false
double realDouble = 1.1;
print('realDouble is num: ${realDouble is num}'); // true
print('realDouble is int: ${realDouble is int}'); // false
print('realDouble is double: ${realDouble is double}'); // true
2013-04-10 Introduction to Dart 35
36. Types – Lists
List realList = [1, true, 'String', 5.6e5];
// Creating an extendable list
List dynamicList = new List();
//dynamicList[0] = 1; // throws an exception
dynamicList.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 Exception
fixedList[0] = 1;
fixedList[1] = true;
fixedList[2] = 'String';
fixedList[3] = 5.6e5;
2013-04-10 Introduction to Dart 36
40. Loops – For in
void 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. Functions – Top-level functions
void main() {
int squaredNum = square(2);
assert(squaredNum == 4);
}
int square(int i) {
return i * i;
}
2013-04-10 Introduction to Dart 41
42. Functions – First-class functions
void 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. Functions – typedef
void 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
53. Classes concrètes
class User implements Validatable {
String username;
String password;
}
2013-04-10 Introduction to Dart 53
54. Classes concrètes
class User implements Validatable {
String username;
String password;
User(this.username, this.password);
}
2013-04-10 Introduction to Dart 54
55. Classes concrètes
class 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. But there is more…
⦿ Mixins
⦿ Optionally typed
⦿ Top level functions
⦿ Mono process
2013-04-10 Introduction to Dart 56
57. Dart Reference API
⦿ Core ⦿ TU et Mocks
⦿ HTML ⦿ Math
⦿ Async ⦿ Logging
⦿ IO ⦿ URI
⦿ Crypto ⦿ I18N
⦿ JSON ⦿ etc.
⦿ Mirrors
⦿ UTF
2013-04-10 Introduction to Dart 57
65. The Old-Fashioned Way
void 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. The Old-Fashioned Way
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 66
67. The Old-Fashioned Way
var 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. The Old-Fashioned Way
void 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
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. Is there a pattern here ?
var grades = school.grades;
if (grades != null) {
tree += '<ul>';
tree += '</ul>';
}
2013-04-10 Introduction to Dart 71
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. 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. Recursive Pattern
String 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. Side note – Functions & sugar syntax
int length(String s) {
return s.length;
}
2013-04-10 Introduction to Dart 75
76. Side note – Functions & sugar syntax
int length(String s) { int length(String s)
return s.length; => s.length;
}
2013-04-10 Introduction to Dart 76
77. Easy use of reusable components
void main() {
final Tree tree = new Tree(...);
}
2013-04-10 Introduction to Dart 77
78. Easy use of reusable components
void main() {
final Tree tree = new Tree(...);
tree.setData(schools);
tree.addTo('body', 'afterBegin');
}
2013-04-10 Introduction to Dart 78
79. Easy use of reusable components
void 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. Easy use of reusable components
class 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. Implementing a reusable components
typedef 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. Implementing a reusable components
typedef 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. Implementing a reusable components
typedef 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. Implementing a reusable components
typedef 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. Implementing a reusable components
class 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. Implementing a reusable components
class 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. Implementing a reusable components
class 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. Implementing a reusable components
class 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. Implementing a reusable components
class 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. Implementing a reusable components
String 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. Implementing a reusable components
String 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. Implementing a reusable components
String 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. Implementing a reusable components
String 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. Implementing a reusable components
class 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. Getting ride of Strings
Element 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. Getting ride of Strings
class 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
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 problems
2013-04-10 Introduction to Dart 98
115. web_ui – The application
void main() {
}
2013-04-10 Introduction to Dart 115
116. web_ui – The application
void main() {
var element = new Element.html(
'<x-click-counter id="click_counter"></x-click-counter>'
);
}
2013-04-10 Introduction to Dart 116
117. web_ui – The application
void 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. web_ui – The application
void 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. web_ui – The application
void 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. A word about Layouts
2013-04-10 Introduction to Dart 120
121. A word about Layouts
2013-04-10 Introduction to Dart 121
122. A word about Layouts
2013-04-10 Introduction to Dart 122
123. A word about Layouts
2013-04-10 Introduction to Dart 123
124. A word about Layouts
2013-04-10 Introduction to Dart 124
125. A word about Layouts
builder()
..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. A word about Layouts
builder()
..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. A word about Layouts
builder()
..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. A word about Layouts
builder()
..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. The Future of Dart ?
2013-04-10 Introduction to Dart 129