Upgrade to Pro — share decks privately, control downloads, hide ads and more …

RxJava et Java 8 Pour Sortir de l'Enfer des Callbacks [quickie]

RxJava et Java 8 Pour Sortir de l'Enfer des Callbacks [quickie]

Comment la combinaison de la librairie RxJava (programmation réactive) et des lambdas de Java 8 peuvent idéalement nous sortir de l'Enfer des Callbacks. Quickie donné à DevoxxFR 2014

Simon Baslé

April 18, 2014
Tweet

More Decks by Simon Baslé

Other Decks in Programming

Transcript

  1. #CallBackHell @simonbasle EXEMPLE : je veux mes 10 premiers docs

    marqués comme favoris sous forme de json complet
  2. #CallBackHell @simonbasle Pour ça je dois agréger en asynchrone :

    méta commentaires & auteurs description d’images
  3. #CallBackHell @simonbasle DocumentService.find("userId", new Callback<List<Document>>() { public void onSuccess(List<Document> result)

    { final List<String> jsonList = new ArrayList<String>(10); int taken = 0; for (Document doc : result) { if (taken >= 10) break; if (!doc.isStarred()) continue; taken++; final CountDownLatch rendezVous = new CountDownLatch(3); final JsonObject jsonBuffer = new JsonObject(); jsonBuffer.appendInt("id", doc.getId()); jsonBuffer.append("text", doc.getText()); CommentService.findForDoc(doc, new Callback<List<Comment>>() { public void onSuccess(List<Comment> comments) { final JsonObject commentArray = JsonObject.createArray(); CountDownLatch userLatch = new CountDownLatch(comments.size()); for (Comment c : comments) { JsonObject cj = new JsonObject(); cj.append("content", c.getText()); cj.append("date", c.getDate()); UserService.find(c.getUserId(), new Callback<User>() { public void onSuccess(User user) { cj.append("author", user.getName()); cj.append("nickname", user.getLogin()); cj.append("email", user.getEmail()); // …
  4. #CallBackHell @simonbasle // … continued commentArray.add(cj); userLatch.countDown(); } }); }

    userLatch.await(); jsonBuffer.addArray("comments", commentArray); rendezVous.countDown(); } }); MetaService.findForDoc(doc, new Callback<List<Meta>>() { public void onSuccess(List<Meta> metas) { jsonBuffer.addArray("meta", jsonify(metas)); rendezVous.countDown(); } }); PictureService.findAllMetas(doc.getPictures(), new Callback<List<PicMeta>>() { public void onSuccess(List<PicMeta> picMetas) { jsonBuffer.addArray("pictures", jsonify(picMetas)); rendezVous.countDown(); } }); rendezVous.await(); jsonList.add(jsonBuffer.toString()); } somethingToDo.onSuccess(jsonList); } });
  5. #CallBackHell @simonbasle DocumentService.find("userId", new Callback<List<Document>>() { public void onSuccess(List<Document> result)

    { final List<String> jsonList = new ArrayList<String>(10); int taken = 0; for (Document doc : result) { if (taken >= 10) break; if (!doc.isStarred()) continue; taken++; final CountDownLatch rendezVous = new CountDownLatch(3); final JsonObject jsonBuffer = new JsonObject(); jsonBuffer.appendInt("id", doc.getId()); jsonBuffer.append("text", doc.getText()); CommentService.findForDoc(doc, new Callback<List<Comment>>() { public void onSuccess(List<Comment> comments) { final JsonObject commentArray = JsonObject.createArray(); CountDownLatch userLatch = new CountDownLatch(comments.size()); for (Comment c : comments) { JsonObject cj = new JsonObject(); cj.append("content", c.getText()); cj.append("date", c.getDate()); UserService.find(c.getUserId(), new Callback<User>() { public void onSuccess(User user) { cj.append("author", user.getName()); cj.append("nickname", user.getLogin()); cj.append("email", user.getEmail()); // … THIS
  6. #CallBackHell @simonbasle IS DocumentService.find("userId", new Callback<List<Document>>() { public void onSuccess(List<Document>

    result) { final List<String> jsonList = new ArrayList<String>(10); int taken = 0; for (Document doc : result) { if (taken >= 10) break; if (!doc.isStarred()) continue; taken++; final CountDownLatch rendezVous = new CountDownLatch(3); final JsonObject jsonBuffer = new JsonObject(); jsonBuffer.appendInt("id", doc.getId()); jsonBuffer.append("text", doc.getText()); CommentService.findForDoc(doc, new Callback<List<Comment>>() { public void onSuccess(List<Comment> comments) { final JsonObject commentArray = JsonObject.createArray(); CountDownLatch userLatch = new CountDownLatch(comments.size()); for (Comment c : comments) { JsonObject cj = new JsonObject(); cj.append("content", c.getText()); cj.append("date", c.getDate()); UserService.find(c.getUserId(), new Callback<User>() { public void onSuccess(User user) { cj.append("author", user.getName()); cj.append("nickname", user.getLogin()); cj.append("email", user.getEmail()); // …
  7. #CallBackHell @simonbasle callback DocumentService.find("userId", new Callback<List<Document>>() { public void onSuccess(List<Document>

    result) { final List<String> jsonList = new ArrayList<String>(10); int taken = 0; for (Document doc : result) { if (taken >= 10) break; if (!doc.isStarred()) continue; taken++; final CountDownLatch rendezVous = new CountDownLatch(3); final JsonObject jsonBuffer = new JsonObject(); jsonBuffer.appendInt("id", doc.getId()); jsonBuffer.append("text", doc.getText()); CommentService.findForDoc(doc, new Callback<List<Comment>>() { public void onSuccess(List<Comment> comments) { final JsonObject commentArray = JsonObject.createArray(); CountDownLatch userLatch = new CountDownLatch(comments.size()); for (Comment c : comments) { JsonObject cj = new JsonObject(); cj.append("content", c.getText()); cj.append("date", c.getDate()); UserService.find(c.getUserId(), new Callback<User>() { public void onSuccess(User user) { cj.append("author", user.getName()); cj.append("nickname", user.getLogin()); cj.append("email", user.getEmail()); // …
  8. #CallBackHell @simonbasle HEEEELL! DocumentService.find("userId", new Callback<List<Document>>() { public void onSuccess(List<Document>

    result) { final List<String> jsonList = new ArrayList<String>(10); int taken = 0; for (Document doc : result) { if (taken >= 10) break; if (!doc.isStarred()) continue; taken++; final CountDownLatch rendezVous = new CountDownLatch(3); final JsonObject jsonBuffer = new JsonObject(); jsonBuffer.appendInt("id", doc.getId()); jsonBuffer.append("text", doc.getText()); CommentService.findForDoc(doc, new Callback<List<Comment>>() { public void onSuccess(List<Comment> comments) { final JsonObject commentArray = JsonObject.createArray(); CountDownLatch userLatch = new CountDownLatch(comments.size()); for (Comment c : comments) { JsonObject cj = new JsonObject(); cj.append("content", c.getText()); cj.append("date", c.getDate()); UserService.find(c.getUserId(), new Callback<User>() { public void onSuccess(User user) { cj.append("author", user.getName()); cj.append("nickname", user.getLogin()); cj.append("email", user.getEmail()); // …
  9. #CallBackHell @simonbasle Wow Such Space! #CallBackHell @simonbasle DocumentService.find("userId", new Callback<List<Document>>()

    { public void onSuccess(List<Document> result) { final List<String> jsonList = new ArrayList<String>(10); int taken = 0; for (Document doc : result) { if (taken >= 10) break; if (!doc.isStarred()) continue; taken++; final CountDownLatch rendezVous = new CountDownLatch(3); final JsonObject jsonBuffer = new JsonObject(); jsonBuffer.appendInt("id", doc.getId()); jsonBuffer.append("text", doc.getText()); CommentService.findForDoc(doc, new Callback<List<Comment>>() { public void onSuccess(List<Comment> comments) { final JsonObject commentArray = JsonObject.createArray(); CountDownLatch userLatch = new CountDownLatch(comments.size()); for (Comment c : comments) { JsonObject cj = new JsonObject(); cj.append("content", c.getText()); cj.append("date", c.getDate()); UserService.find(c.getUserId(), new Callback<User>() { public void onSuccess(User user) { cj.append("author", user.getName()); cj.append("nickname", user.getLogin()); cj.append("email", user.getEmail()); // …
  10. #CallBackHell @simonbasle Observable<JsonObject> fullDocumentJson = DocumentService.find("user") .filter(new Func1<Document, Boolean>() {

    public Boolean call(Document doc) { return doc.isStarred(); }}) .take(10) .map(new Func1<Document, JsonObject>() { public JsonObject call(Document doc) { Observable<JsonObject> oc = CommentService.findForDoc(doc) .map(new Func1<Comment, JsonObject>() { public JsonObject call(Comment c) { User u = UserService.find(c.getUserId()) .toBlockingObservable().first(); JsonObject result = jsonify(c).append("author", u.getName()); return result.append("nickname", u.getLogin()).append("email", u.getEmail()); }}); Observable<JsonObject> om = MetaService.findForDoc(doc) .map(new Func1<Meta, JsonObject>() { public JsonObject call(Meta m) { return jsonify(m); }}); Observable<JsonObject> op = PictureService.findAllMetas(doc.getPictures()) .map(new Func1<PicMeta, JsonObject>() { public JsonObject call(PicMeta p) { return jsonify(p); }});
  11. #CallBackHell @simonbasle Func2<JsonArray, JsonObject, JsonArray> arrayAggregator = new Func2<JsonArray, JsonObject,

    JsonArray>() { public JsonArray call(JsonArray t1, JsonObject t2) { return t1.addElement(t2); }}; JsonObject docJson = new JsonObject().appendInt("id", doc.getId()).append("text", doc.getText()); JsonArray c = new JsonArray(); docJson.addArray("comments", c); oc.reduce(c, arrayAggregator); JsonArray m = new JsonArray(); docJson.addArray("meta", m); om.reduce(m, arrayAggregator); JsonArray p = new JsonArray(); docJson.addArray("pictures", p); op.reduce(p, arrayAggregator); return docJson; } });
  12. #CallBackHell @simonbasle Observable<JsonObject> fullDocumentJson = DocumentService.find("user") .filter(new Func1<Document, Boolean>() {

    public Boolean call(Document doc) { return doc.isStarred(); }}) .take(10) .map(new Func1<Document, JsonObject>() { public JsonObject call(Document doc) { Observable<JsonObject> oc = CommentService.findForDoc(doc) .map(new Func1<Comment, JsonObject>() { public JsonObject call(Comment c) { User u = UserService.find(c.getUserId()) .toBlockingObservable().first(); JsonObject result = jsonify(c).append("author", u.getName()); return result.append("nickname", u.getLogin()).append("email", u.getEmail()); }}); Observable<JsonObject> om = MetaService.findForDoc(doc) .map(new Func1<Meta, JsonObject>() { public JsonObject call(Meta m) { return jsonify(m); }}); Observable<JsonObject> op = PictureService.findAllMetas(doc.getPictures()) .map(new Func1<PicMeta, JsonObject>() { public JsonObject call(PicMeta p) { return jsonify(p); }});
  13. #CallBackHell @simonbasle Func2<JsonArray, JsonObject, JsonArray> arrayAggregator = new Func2<JsonArray, JsonObject,

    JsonArray>() { public JsonArray call(JsonArray t1, JsonObject t2) { return t1.addElement(t2); }}; JsonObject docJson = new JsonObject().appendInt("id", doc.getId()).append("text", doc.getText()); JsonArray c = new JsonArray(); docJson.addArray("comments", c); oc.reduce(c, arrayAggregator); JsonArray m = new JsonArray(); docJson.addArray("meta", m); om.reduce(m, arrayAggregator); JsonArray p = new JsonArray(); docJson.addArray("pictures", p); op.reduce(p, arrayAggregator); return docJson; } });
  14. #CallBackHell @simonbasle Observable<JsonObject> fullDocumentJson = DocumentService.find("user") .filter(doc -> doc.isStarred()) .take(10)

    .map(doc -> { Observable<JsonObject> oc = CommentService.findForDoc(doc) .map(c -> { User u = UserService.find(c.getUserId()).toBlockingObservable().first(); JsonObject result = jsonify(c).append("author", u.getName()); return result.append("nickname", u.getLogin()).append("email", u.getEmail());}); Observable<JsonObject> om = MetaService.findForDoc(doc).map(m -> jsonify(m)); Observable<JsonObject> op = PictureService.findAllMetas(doc.getPictures()).map(p -> jsonify(p)); JsonObject docJson = new JsonObject().appendInt("id", doc.getId()).append("text", doc.getText()); JsonArray c = new JsonArray(); docJson.addArray("comments", c); oc.reduce(c, (array, elem) -> array.addElement(elem)); JsonArray m = new JsonArray(); docJson.addArray("meta", m); om.reduce(m, (array, elem) -> array.addElement(elem)); JsonArray p = new JsonArray(); docJson.addArray("pictures", p); op.reduce(p, (array, elem) -> array.addElement(elem)); return docJson; });
  15. #CallBackHell @simonbasle 2 1 slides en taille 10 58 28

    lignes de code max 7 4 tabulations 3 1 imbrication exceptionnelle
  16. #CallBackHell @simonbasle Crédits ➔ The Door to Hell - Flydime

    http://www.flickr.com/photos/flydime/4671890969/ ➔ Cat Attack - Static416 http://www.flickr.com/photos/ehacke/4584255926/ ➔ Série Stormtroopers - J.D. Hancock http://photos.jdhancock.com/series/stormtroopers.html ➔ Chien de près - RPavich http://www.flickr.com/photos/rpavich/11409595543/ ➔ Hyperspace - Procsilas Moscas http://www.flickr.com/photos/procsilas/12821454664/ ➔ Takeaway - Edimbhurg Blog http://www.flickr.com/photos/theedinburghblog/6493647769/ ➔ The End Sable - Elektro-Plan http://pixabay.com/p-283407/ By-Sa By-Nc By By By By Cc0