FP is coming... le 19/05/2016
-
Upload
loic-knuchel -
Category
Software
-
view
217 -
download
0
Transcript of FP is coming... le 19/05/2016
![Page 2: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/2.jpg)
Loïc Knuchel
Freelance
Développeur web full-stack
Entrepreneur
Cookers / SalooN
@loicknuchel
http://loic.knuchel.org/
Geek passionné
![Page 3: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/3.jpg)
![Page 6: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/6.jpg)
Front-end
![Page 7: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/7.jpg)
![Page 8: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/8.jpg)
![Page 9: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/9.jpg)
![Page 10: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/10.jpg)
![Page 11: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/11.jpg)
![Page 12: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/12.jpg)
![Page 13: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/13.jpg)
Fonctions pures
Immutabilité
![Page 14: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/14.jpg)
Fonctions pures
ImmutabilitéModifier une variable ?
Accès BDD ?
Logs ? Exceptions ?
CRUD ?
![Page 15: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/15.jpg)
Do not fear FP
![Page 16: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/16.jpg)
Au fait, c’est quoi la programmation fonctionnelle ?“La programmation fonctionnelle est un paradigme de programmation qui considère le calcul en tant qu'évaluation de fonctions mathématiques.” Wikipedia
![Page 17: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/17.jpg)
Au fait, c’est quoi la programmation fonctionnelle ?“La programmation fonctionnelle est un paradigme de programmation qui considère le calcul en tant qu'évaluation de fonctions mathématiques.” Wikipedia
“La programmation fonctionnelle est un style de programmation qui met l’accent sur les fonctions qui ne dépendent pas de l’état du programme.” Functionnal programming in scala
![Page 18: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/18.jpg)
Au fait, c’est quoi la programmation fonctionnelle ?“La programmation fonctionnelle est un paradigme de programmation qui considère le calcul en tant qu'évaluation de fonctions mathématiques.” Wikipedia
“La programmation fonctionnelle est un style de programmation qui met l’accent sur les fonctions qui ne dépendent pas de l’état du programme.” Functionnal programming in scala
“La programmation fonctionnelle permet de coder de manière plus productive et plus modulaire, avec moins de bugs.” Moi
![Page 19: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/19.jpg)
![Page 20: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/20.jpg)
Transformer un tableau
function toUpperCase(list){ var ret = []; for(var i=0; i<list.length; i++){ ret[i] = list[i].toUpperCase(); } return ret;}
var names = ['Finn', 'Rey', 'Poe'];
console.log(toUpperCase(names));// ['FINN', 'REY', 'POE']
public List<String> toUpperCase(List<String> list) { List<String> ret = new ArrayList<>(); for(String item : list){ ret.add(item.toUpperCase()); } return ret;}
List<String> names = Arrays.asList("Finn", "Rey", "Poe");
System.out.println(Arrays.toString(toUpperCase(names).toArray()));// [FINN, REY, POE]
![Page 21: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/21.jpg)
Transformer un tableau
function toUpperCase(list){ return list.map(function(item){ return item.toUpperCase(); });}
var names = ['Finn', 'Rey', 'Poe'];
console.log(toUpperCase(names));// ['FINN', 'REY', 'POE']
def toUpperCase(list: List[String]): List[String] = list.map(item => item.toUpperCase)
val names = List("Finn", "Rey", "Poe")
println(toUpperCase(names))// List(FINN, REY, POE)
![Page 22: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/22.jpg)
Transformer un tableau
function toUpperCase(list){ return list.map(function(item){ return item.toUpperCase(); });}
var names = ['Finn', 'Rey', 'Poe'];
console.log(toUpperCase(names));// ['FINN', 'REY', 'POE']
def toUpperCase(list: List[String]): List[String] = list.map(_.toUpperCase)
val names = List("Finn", "Rey", "Poe")
println(toUpperCase(names))// List(FINN, REY, POE)
![Page 23: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/23.jpg)
Créer son .map()
Array.prototype.map = function(callback){ var array = this; var result = []; for(var i=0; i<array.length; i++){ result[i] = callback(array[i]); } return result;};
![Page 24: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/24.jpg)
Séparation technique / métier
Array.prototype.map = function(callback){ var array = this; var result = []; for(var i=0; i<array.length; i++){ result[i] = callback(array[i]); } return result;};
list.map(function(item){ return item.toUpperCase();});
![Page 25: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/25.jpg)
Séparation technique / métier
Array.prototype.map = function(callback){ var array = this; var result = []; for(var i=0; i<array.length; i++){ result[i] = callback(array[i]); } return result;};
list.map(function(item){ return item.toUpperCase();});
GénériqueHaut niveau d’abstraction
Un maximum de libraires externe
![Page 26: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/26.jpg)
Séparation technique / métier
Array.prototype.map = function(callback){ var array = this; var result = []; for(var i=0; i<array.length; i++){ result[i] = callback(array[i]); } return result;};
list.map(function(item){ return item.toUpperCase();});
GénériqueHaut niveau d’abstraction
Un maximum de libraires externe
Concis / ExpressifFocalisé sur le domaine
Un minimum de libraires externe
![Page 27: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/27.jpg)
Architecture Hexagonale
![Page 28: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/28.jpg)
Manipuler des donnéesvar data = [{ id: '123', actions: [ {name: 'sendPicture', pictures: [ {path: '123/1.jpg', deleted: true, sync: false}, {path: '123/2.jpg', deleted: false, sync: true}, ]}, {name: 'sendPicture', pictures: [ {path: '123/3.jpg', deleted: false, sync: true}, {path: '123/4.jpg', deleted: false, sync: true} ]}, {name: 'sendPicture', pictures: [ {path: '123/5.jpg', deleted: true, sync: false}, {path: '123/6.jpg', deleted: false, sync: false} ]} ]}, { id: '456', actions: [ {name: 'sendPicture', pictures: [ {path: '456/1.jpg', deleted: false, sync: true}, {path: '456/2.jpg', deleted: false, sync: true}, ]}, {name: 'sendPicture', pictures: [ {path: '123/3.jpg', deleted: true, sync: false}, {path: '123/4.jpg', deleted: true, sync: false} ]} ]}];
function doSomething(items, id){ var pictures = []; for (var i=0; i<items.length; i++) { var item = items[i]; if (item.id === id) { for (var j=0; j<item.actions.length; j++) { var action = item.actions[j]; if (action.name === 'sendPicture') { for (var k=0; k<action.pictures.length; k++) { var picture = action.pictures[k]; if (!picture.deleted) { pictures.push(picture); } } } } } } return pictures;}
![Page 29: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/29.jpg)
function getPictures(items, id){ var pictures = []; for (var i=0; i<items.length; i++) { var item = items[i]; if (item.id === id) { for (var j=0; j<item.actions.length; j++) { var action = item.actions[j]; if (action.name === 'sendPicture') { for (var k=0; k<action.pictures.length; k++) { var picture = action.pictures[k]; if (!picture.deleted) { pictures.push(picture); } } } } } } return pictures;}
Manipuler des donnéespublic List<Picture> getPictures(List<Item> items, String id) { List<Picture> pictures = new ArrayList<>(); for (Item item : items) { if (item.getId() == id) { for (Action action : item.getActions()) { if (action.getName() == "sendPicture") { for (Picture picture : action.getPictures()) { if (!picture.getDeleted()) { pictures.add(picture); } } } } } } return pictures;}
![Page 30: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/30.jpg)
function getPictures(items, id){ var pictures = []; for (var i=0; i<items.length; i++) { var item = items[i]; if (item.id === id) { for (var j=0; j<item.actions.length; j++) { var action = item.actions[j]; if (action.name === 'sendPicture') { for (var k=0; k<action.pictures.length; k++) { var picture = action.pictures[k]; if (!picture.deleted) { pictures.push(picture); } } } } } } return pictures;}
Manipuler des donnéespublic List<Picture> getPictures(List<Item> items, String id) { List<Picture> pictures = new ArrayList<>(); for (Item item : items) { if (item.getId() == id) { for (Action action : item.getActions()) { if (action.getName() == "sendPicture") { for (Picture picture : action.getPictures()) { if (!picture.getDeleted()) { pictures.add(picture); } } } } } } return pictures;}
Duplication !Duplication !
![Page 31: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/31.jpg)
function getPictures(items, id){ var pictures = []; for (var i=0; i<items.length; i++) { var item = items[i]; if (item.id === id) { for (var j=0; j<item.actions.length; j++) { var action = item.actions[j]; if (action.name === 'sendPicture') { for (var k=0; k<action.pictures.length; k++) { var picture = action.pictures[k]; if (!picture.deleted) { pictures.push(picture); } } } } } } return pictures;}
Manipuler des donnéespublic List<Picture> getPictures(List<Item> items, String id) { List<Picture> pictures = new ArrayList<>(); for (Item item : items) { if (item.getId() == id) { for (Action action : item.getActions()) { if (action.getName() == "sendPicture") { for (Picture picture : action.getPictures()) { if (!picture.getDeleted()) { pictures.add(picture); } } } } } } return pictures;}
Find item by idFilter actions by nameFilter pictures not deleted
![Page 32: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/32.jpg)
function getPictures(items, id){ var pictures = []; for (var i=0; i<items.length; i++) { var item = items[i]; if (item.id === id) { for (var j=0; j<item.actions.length; j++) { var action = item.actions[j]; if (action.name === 'sendPicture') { for (var k=0; k<action.pictures.length; k++) { var picture = action.pictures[k]; if (!picture.deleted) { pictures.push(picture); } } } } } } return pictures;}
Manipuler des donnéespublic List<Picture> getPictures(List<Item> items, String id) { List<Picture> pictures = new ArrayList<>(); for (Item item : items) { if (item.getId() == id) { for (Action action : item.getActions()) { if (action.getName() == "sendPicture") { for (Picture picture : action.getPictures()) { if (!picture.getDeleted()) { pictures.add(picture); } } } } } } return pictures;}
Find item by idFilter actions by nameFilter pictures not deleted
Level up your abstraction !
![Page 33: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/33.jpg)
Manipuler des données// Finds the 1st elt of the sequence satisfying a predicate, if anydef find[A](p: (A) => Boolean): Option[A]
// Selects all elts of this collection which satisfy a predicatedef filter[A](p: (A) => Boolean): List[A]
// Builds a new list by applying a function to all elements of the listdef map[A, B](f: (A) => B): List[B]
// Applies a binary operator to all elts of this listdef reduce[A, B](f: (B, A) => B, b: B): B
![Page 34: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/34.jpg)
Manipuler des donnéesfunction getPictures(items, id){ return items .find(function(item){ return item.id === id; }).actions .filter(function(action){ return action.name === 'sendPicture'; }) .map(function(action){ return action.pictures; }) .reduce(function(a, b){ return a.concat(b); }, []) .filter(function(picture){ return !picture.deleted; });}
def getPictures(items: List[Item], id: String): List[Picture] = items .find(_.id == id) .map(_.actions).getOrElse(List()) .filter(_.name == "sendPicture") .flatMap(_.pictures) .filter(!_.deleted)
![Page 35: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/35.jpg)
![Page 36: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/36.jpg)
public List<Picture> getPictures(List<Item> items, String id) { List<Picture> pictures = new ArrayList<>(); for (Item item : items) { if (item.getId() == id) { for (Action action : item.getActions()) { if (action.getName() == "sendPicture") { for (Picture picture : action.getPictures()) { if (!picture.getDeleted()) { pictures.add(picture); } } } } } } return pictures;}
def getPictures(items: List[Item], id: String): List[Picture] = items .find(_.id == id) .map(_.actions).getOrElse(List()) .filter(_.name == "sendPicture") .flatMap(_.pictures) .filter(!_.deleted)
Manipuler des donnéesfunction getPictures(items, id){ var pictures = []; for(var i=0; i<items.length; i++){ var item = items[i]; if(item.id === id){ for(var j=0; j<item.actions.length; j++){ var action = item.actions[j]; if(action.name === 'sendPicture'){ for(var k=0; k<action.pictures.length; k++){ var picture = action.pictures[k]; if(!picture.deleted){ pictures.push(picture); } } } } } } return pictures;}
function getPictures(items, id){ return items .find(function(item){ return item.id === id; }).actions .filter(function(action){ return action.name === 'sendPicture'; }) .map(function(action){ return action.pictures; }) .reduce(function(a, b){ return a.concat(b); }, []) .filter(function(picture){ return !picture.deleted; });}
Safe ?
![Page 37: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/37.jpg)
public List<Picture> getPictures(List<Item> items, String id) { List<Picture> pictures = new ArrayList<>(); for (Item item : items) { if (item.getId() == id) { for (Action action : item.getActions()) { if (action.getName() == "sendPicture") { for (Picture picture : action.getPictures()) { if (!picture.getDeleted()) { pictures.add(picture); } } } } } } return pictures;}
def getPictures(items: List[Item], id: String): List[Picture] = items .find(_.id == id) .map(_.actions).getOrElse(List()) .filter(_.name == "sendPicture") .flatMap(_.pictures) .filter(!_.deleted)
Manipuler des donnéesfunction getPictures(items, id){ var pictures = []; for(var i=0; i<items.length; i++){ var item = items[i]; if(item.id === id){ for(var j=0; j<item.actions.length; j++){ var action = item.actions[j]; if(action.name === 'sendPicture'){ for(var k=0; k<action.pictures.length; k++){ var picture = action.pictures[k]; if(!picture.deleted){ pictures.push(picture); } } } } } } return pictures;}
function getPictures(items, id){ return items .find(function(item){ return item.id === id; }).actions .filter(function(action){ return action.name === 'sendPicture'; }) .map(function(action){ return action.pictures; }) .reduce(function(a, b){ return a.concat(b); }, []) .filter(function(picture){ return !picture.deleted; });}
Cannot read property 'xxx' of
undefined x 6 !!!
![Page 38: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/38.jpg)
public List<Picture> getPictures(List<Item> items, String id) { List<Picture> pictures = new ArrayList<>(); for (Item item : items) { if (item.getId() == id) { for (Action action : item.getActions()) { if (action.getName() == "sendPicture") { for (Picture picture : action.getPictures()) { if (!picture.getDeleted()) { pictures.add(picture); } } } } } } return pictures;}
def getPictures(items: List[Item], id: String): List[Picture] = items .find(_.id == id) .map(_.actions).getOrElse(List()) .filter(_.name == "sendPicture") .flatMap(_.pictures) .filter(!_.deleted)
Manipuler des donnéesfunction getPictures(items, id){ var pictures = []; for(var i=0; i<items.length; i++){ var item = items[i]; if(item.id === id){ for(var j=0; j<item.actions.length; j++){ var action = item.actions[j]; if(action.name === 'sendPicture'){ for(var k=0; k<action.pictures.length; k++){ var picture = action.pictures[k]; if(!picture.deleted){ pictures.push(picture); } } } } } } return pictures;}
function getPictures(items, id){ return items .find(function(item){ return item.id === id; }).actions .filter(function(action){ return action.name === 'sendPicture'; }) .map(function(action){ return action.pictures; }) .reduce(function(a, b){ return a.concat(b); }, []) .filter(function(picture){ return !picture.deleted; });}
Cannot read property 'xxx' of
undefined x 6 !!!
![Page 39: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/39.jpg)
public List<Picture> getPictures(List<Item> items, String id) { List<Picture> pictures = new ArrayList<>(); for (Item item : items) { if (item.getId() == id) { for (Action action : item.getActions()) { if (action.getName() == "sendPicture") { for (Picture picture : action.getPictures()) { if (!picture.getDeleted()) { pictures.add(picture); } } } } } } return pictures;}
def getPictures(items: List[Item], id: String): List[Picture] = items .find(_.id == id) .map(_.actions).getOrElse(List()) .filter(_.name == "sendPicture") .flatMap(_.pictures) .filter(!_.deleted)
Manipuler des donnéesfunction getPictures(items, id){ var pictures = []; for(var i=0; i<items.length; i++){ var item = items[i]; if(item.id === id){ for(var j=0; j<item.actions.length; j++){ var action = item.actions[j]; if(action.name === 'sendPicture'){ for(var k=0; k<action.pictures.length; k++){ var picture = action.pictures[k]; if(!picture.deleted){ pictures.push(picture); } } } } } } return pictures;}
function getPictures(items, id){ return items .find(function(item){ return item.id === id; }).actions .filter(function(action){ return action.name === 'sendPicture'; }) .map(function(action){ return action.pictures; }) .reduce(function(a, b){ return a.concat(b); }, []) .filter(function(picture){ return !picture.deleted; });}
Cannot read property 'xxx' of
undefined x 6 !!!java.lang.NullPointerException x 6 !!!
![Page 40: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/40.jpg)
public List<Picture> getPictures(List<Item> items, String id) { List<Picture> pictures = new ArrayList<>(); for (Item item : items) { if (item.getId() == id) { for (Action action : item.getActions()) { if (action.getName() == "sendPicture") { for (Picture picture : action.getPictures()) { if (!picture.getDeleted()) { pictures.add(picture); } } } } } } return pictures;}
def getPictures(items: List[Item], id: String): List[Picture] = items .find(_.id == id) .map(_.actions).getOrElse(List()) .filter(_.name == "sendPicture") .flatMap(_.pictures) .filter(!_.deleted)
Manipuler des donnéesfunction getPictures(items, id){ var pictures = []; for(var i=0; i<items.length; i++){ var item = items[i]; if(item.id === id){ for(var j=0; j<item.actions.length; j++){ var action = item.actions[j]; if(action.name === 'sendPicture'){ for(var k=0; k<action.pictures.length; k++){ var picture = action.pictures[k]; if(!picture.deleted){ pictures.push(picture); } } } } } } return pictures;}
function getPictures(items, id){ return items .find(function(item){ return item.id === id; }).actions .filter(function(action){ return action.name === 'sendPicture'; }) .map(function(action){ return action.pictures; }) .reduce(function(a, b){ return a.concat(b); }, []) .filter(function(picture){ return !picture.deleted; });}
Cannot read property 'xxx' of
undefined x 6 !!!java.lang.NullPointerException x 6 !!!
Safe code \o/
![Page 41: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/41.jpg)
Java “Safe”public List<Picture> getPictures(List<Item> items, String id) { List<Picture> pictures = new ArrayList<>(); if (items != null) { for (Item item : items) { if (item != null && item.getId() == id && item.getActions() != null) { for (Action action : item.getActions()) { if (action != null && action.getName() == "sendPicture" && action.getPictures() != null) { for (Picture picture : action.getPictures()) { if (picture != null && !picture.getDeleted()) { pictures.add(picture); } } } } } } } return pictures;}
def getPictures(items: List[Item], id: String): List[Picture] = items .find(_.id == id) .map(_.actions).getOrElse(List()) .filter(_.name == "sendPicture") .flatMap(_.pictures) .filter(!_.deleted)
![Page 42: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/42.jpg)
Option
![Page 43: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/43.jpg)
Le problèmefunction getName(user) { return user.name;}
![Page 44: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/44.jpg)
Le problèmefunction getName(user) { return user.name;}
public String getName(User user) { return user.getName();}
![Page 45: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/45.jpg)
Le problèmefunction getName(user) { return user.name;}
public String getName(User user) { return user.getName();}
def getUser(user: User): String = user.name
![Page 46: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/46.jpg)
Le problèmefunction getName(user) { return user.name;}
getName();// Cannot read property 'name' of undefined
public String getName(User user) { return user.getName();}
getName(null);// java.lang.NullPointerException
def getUser(user: User): String = user.name
// no null (used) in scala !
![Page 47: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/47.jpg)
Le problèmefunction getName(user) { return user.name;}
getName();// Cannot read property 'name' of undefined
getName(localStorage.getItem('user'));// ERROR ???
public String getName(User user) { return user.getName();}
getName(null);// java.lang.NullPointerException
getName(getUser());// ERROR ???
def getUser(user: User): String = user.name
// no null (used) in scala !
![Page 48: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/48.jpg)
Le problèmefunction getName(user) { return user.name;}
getName();// Cannot read property 'name' of undefined
getName(localStorage.getItem('user'));// ERROR ???
function getName(user) { return user ? user.name : '';}function getName(user) { return (user || {}).name;}
public String getName(User user) { return user.getName();}
getName(null);// java.lang.NullPointerException
getName(getUser());// ERROR ???
public String getName(User user) { if(user != null){ return user.getName(); } else { return ""; }}
def getUser(user: User): String = user.name
// no null (used) in scala !
![Page 49: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/49.jpg)
Option
![Page 50: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/50.jpg)
Le problèmefunction getName(user) { return user.name;}
getName();// Cannot read property 'name' of undefined
getName(localStorage.getItem('user'));// ERROR ???
function getName(user) { return user ? user.name : '';}
function getName(user) { return (user || {}).name;}
public String getName(User user) { return user.getName();}
getName(null);// java.lang.NullPointerException
getName(getUser());// ERROR ???
public String getName(User user) { if(user != null){ return user.getName(); } else { return ""; }}
def getUser(user: User): String = user.name
// no null (used) in scala !
def getUser(user: Option[User]): Option[String] = user.map(_.name)
def getUser(user: Option[User]): String = user.map(_.name).getOrElse("")
![Page 51: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/51.jpg)
List.map() vs Option.map()
![Page 52: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/52.jpg)
Monad
![Page 53: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/53.jpg)
Monad
● Wrapper (context) M[A]
● Fonction map def map[B](f: A => B): M[B]
● Fonction flatMap def flatMap[B](f: A => M[B]): M[B]
![Page 54: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/54.jpg)
Monad
● List
● Option
● Future
● Try
● ...
![Page 55: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/55.jpg)
Basics
![Page 56: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/56.jpg)
Typage fort
![Page 57: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/57.jpg)
Typage fort
● Filet de sécurité pour garantir la cohérence du programme
![Page 58: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/58.jpg)
Typage fort
● Filet de sécurité pour garantir la cohérence du programme
● Documentation pour le développeur
![Page 59: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/59.jpg)
Typage fort
● Filet de sécurité pour garantir la cohérence du programme
● Documentation pour le développeur
● Implémentent certains concepts
![Page 60: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/60.jpg)
Typage fort
● Filet de sécurité pour garantir la cohérence du programme
● Documentation pour le développeur
● Implémentent certains concepts
● null => Option
![Page 61: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/61.jpg)
Typage fort
● Filet de sécurité pour garantir la cohérence du programme
● Documentation pour le développeur
● Implémentent certains concepts
● null => Option● exception => Either / Try
![Page 62: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/62.jpg)
Typage fort
● Filet de sécurité pour garantir la cohérence du programme
● Documentation pour le développeur
● Implémentent certains concepts
● null => Option● exception => Either / Try● async => Future● ...
![Page 63: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/63.jpg)
Typage fort
● Filet de sécurité pour garantir la cohérence du programme
● Documentation pour le développeur
● Implémentent certains concepts
● Type Driven Development
![Page 64: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/64.jpg)
Type all the things !!!case class Contact(
firstName: String, middleInitial: String, lastName: String,
emailAddress: String, isEmailVerified: Boolean
)
![Page 65: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/65.jpg)
Type all the things !!!case class Contact(
firstName: String, middleInitial: String, lastName: String,
emailAddress: String, isEmailVerified: Boolean
)
Optionnel ?
![Page 66: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/66.jpg)
Type all the things !!!case class Contact(
firstName: String, middleInitial: String, lastName: String,
emailAddress: String, isEmailVerified: Boolean
)
Optionnel ?Contrainte ?
![Page 67: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/67.jpg)
Type all the things !!!case class Contact(
firstName: String, middleInitial: String, lastName: String,
emailAddress: String, isEmailVerified: Boolean
)
Optionnel ?Contrainte ?
Lien ?
![Page 68: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/68.jpg)
Type all the things !!!case class Contact(
firstName: String, middleInitial: String, lastName: String,
emailAddress: String, isEmailVerified: Boolean
)
Optionnel ?Contrainte ?
Lien ?
Logique métier ?
![Page 69: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/69.jpg)
Type all the things !!!case class Contact(
firstName: String, middleInitial: String, lastName: String,
emailAddress: String, isEmailVerified: Boolean
)
case class Contact( name: PersonalName, email: EmailAddress)
Optionnel ?Contrainte ?
Lien ?
Logique métier ?
![Page 70: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/70.jpg)
Type all the things !!!case class Contact(
firstName: String, middleInitial: String, lastName: String,
emailAddress: String, isEmailVerified: Boolean
)
case class Contact( name: PersonalName, email: EmailAddress)
case class PersonalName( firstName: String_50, middleInitial: Option[String_1], lastName: String_50)
sealed trait EmailAddresscase class VerifiedEmail(value: Email) extends EmailAddresscase class UnverifiedEmail(value: Email) extends EmailAddress
Optionnel ?Contrainte ?
Lien ?
Logique métier ?
![Page 71: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/71.jpg)
Type all the things !!!case class Contact(
firstName: String, middleInitial: String, lastName: String,
emailAddress: String, isEmailVerified: Boolean
)
case class Contact( name: PersonalName, email: EmailAddress)
case class PersonalName( firstName: String_50, middleInitial: Option[String_1], lastName: String_50)
sealed trait EmailAddresscase class VerifiedEmail(value: Email) extends EmailAddresscase class UnverifiedEmail(value: Email) extends EmailAddress
case class String_1(value: String) { require(value.length <= 1, s"String_1 should be <= 1 (actual: $value)") override def toString: String = value}case class String_50(value: String) { require(value.length <= 50, s"String_50 should be <= 50 (actual: $value)") override def toString: String = value}case class Email(value: String) { require(value.contains("@"), s"Email should contain '@' (actual: $value)") override def toString: String = value}
Optionnel ?Contrainte ?
Lien ?
Logique métier ?
![Page 72: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/72.jpg)
Stateless
![Page 73: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/73.jpg)
Stateless
Passer toute les données nécessaires à chaque fois
![Page 74: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/74.jpg)
Stateless
Passer toute les données nécessaires à chaque fois
● Testabilité
![Page 75: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/75.jpg)
Stateless
Passer toute les données nécessaires à chaque fois
● Testabilité
● Plus facile à comprendre
![Page 76: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/76.jpg)
Immutabilité
![Page 77: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/77.jpg)
Immutabilité
![Page 78: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/78.jpg)
Immutabilité
● Scalabilité / Multithreading
![Page 79: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/79.jpg)
Immutabilité
● Scalabilité / Multithreading
● Meilleur nommage
![Page 80: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/80.jpg)
Immutabilité
● Scalabilité / Multithreading
● Meilleur nommage
● Séparation données / calculs
Types et Fonctions plutôt que Classes :
● Entity● Value Object● Service
![Page 81: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/81.jpg)
Immutabilité
● Scalabilité / Multithreading
● Meilleur nommage
● Séparation données / calculs
Types et Fonctions plutôt que Classes :
● Entity● Value Object● Service
case class Person( firstName: String, lastName: String) { val fullName = Person.fullName(this)}object Person { def fullName(p: Person): String = p.firstName+" "+p.lastName}
![Page 82: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/82.jpg)
No side effectEffet de bord: lancer une exception, faire un appel (bdd, http, fichier…), récupérer la date actuelle,
modifier un paramètre, accéder à une variable “globale”, afficher un log...
![Page 83: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/83.jpg)
No side effect
![Page 84: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/84.jpg)
No side effect
● Fonctions plus faciles à comprendre et à composer
● Possibilité de construire des choses complexes à partir d’éléments simples
● Local reasoning
![Page 85: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/85.jpg)
● Lancer une exception ?
No side effect
![Page 86: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/86.jpg)
● Lancer une exception ?
No side effect
Renvoyer un Type d’erreur :
● Option[A] : un type ou pas● Try[A] : un type ou un Throwable● Either[A, B] : un type ou un autre● Validation[A, Seq[ValidationError]] : un type ou une liste d’erreur
![Page 87: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/87.jpg)
● Lancer une exception ?● Accès à une base de données ?
No side effect
![Page 88: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/88.jpg)
● Lancer une exception ?● Accès à une base de données ?
No side effect
Effet de bord fait :● en “bordure du système”● idéalement par une librairie● représenté par un type (Future, IO…)
Ex : def getDBUser(id: UserId): Future[Option[User]] = ???
![Page 89: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/89.jpg)
● Lancer une exception ?● Accès à une base de données ?● Afficher un log ?
No side effect
![Page 90: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/90.jpg)
● Lancer une exception ?● Accès à une base de données ?● Afficher un log ?
No side effect
On peut éventuellement se permettre un peu de liberté...
![Page 91: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/91.jpg)
Architecture Hexagonale
strict FPsoft FP
![Page 92: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/92.jpg)
“Easy to learn/write”vs
“Easy to maintain”
![Page 93: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/93.jpg)
![Page 94: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/94.jpg)
DDD
Hexagonal architecture
Event Storming
Property based testing
Event Sourcing
Clean code
TDDBDD
Craftsmanship
Living Documentation
CQRS
![Page 95: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/95.jpg)
Take away
● Paramètre de fonction plutôt que donnée globale (même de classe)
● Créer des objets plutôt que de les modifier (immutable)
● Option plutôt que ‘null’
● Either/Try plutôt qu’une exception
● Collection API / recursivité plutôt que boucles for/while
● Eviter les ‘if’ autant que possible
● Séparation métier / technique
![Page 96: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/96.jpg)
![Page 97: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/97.jpg)
RéférencesDoes the Language You Use Make a Difference ?
When DDD meets FP, good things happen
Ur Domain Haz Monoids (vidéo)
DDD: et si on reprenait l'histoire par le bon bout ?
DDD, en vrai pour le développeur
Functional programming Illustrated by Scala
Scala School!
![Page 98: FP is coming... le 19/05/2016](https://reader031.fdocuments.in/reader031/viewer/2022030315/58848f691a28ab6d1a8b6dc1/html5/thumbnails/98.jpg)
[email protected] @loicknuchel http://loic.knuchel.org/