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

RxJava + Java 8, Sortir de l'Enfer des Callbacks

RxJava + Java 8, Sortir de l'Enfer des Callbacks

[FR] Comment faire du code asynchrone, lisible et composable? RxJava couplé à Java8 pourrait être une bonne solution pour sortir de cet Enfer des Callbacks.

Simon Baslé

May 23, 2014
Tweet

More Decks by Simon Baslé

Other Decks in Programming

Transcript

  1. EXEMPLE : je veux mes 10 premiers docs marqués comme

    favoris sous forme de json complet
  2. 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()); // …
  3. // … 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); } });
  4. 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
  5. 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()); // …
  6. 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()); // …
  7. 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()); // …
  8. Wow Such Space! 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. ...

  10. 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) .flatMap(new Func1<Comment, Observable<JsonObject>>() { public Observable<JsonObject> call(Comment c) { return UserService.find(c.getUserId()) .first() .map(new Func1<User, JsonObject>() { public JsonObject call(User u) { 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); }});
  11. Observable<JsonObject> op = PictureService.findAllMetas(doc.getPictures()) .map(new Func1<PicMeta, JsonObject>() { public JsonObject

    call(PicMeta p) { return jsonify(p); }}); 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. 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) .flatMap(new Func1<Comment, Observable<JsonObject>>() { public Observable<JsonObject> call(Comment c) { return UserService.find(c.getUserId()) .first() .map(new Func1<User, JsonObject>() { public JsonObject call(User u) { 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); }});
  13. Observable<JsonObject> op = PictureService.findAllMetas(doc.getPictures()) .map(new Func1<PicMeta, JsonObject>() { public JsonObject

    call(PicMeta p) { return jsonify(p); }}); 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. Observable<JsonObject> fullDocumentJson = DocumentService.find("user") .filter(Document::isStarred) .take(10) .map(doc -> { Observable<JsonObject>

    oc = CommentService.findForDoc(doc) .flatMap(c -> UserService.find(c.getUserId()) .first() .map(u -> { 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. Observable<JsonObject> fullDocumentJson = DocumentService.find("user") .filter(Document::isStarred) .take(10) .map(doc -> { Observable<JsonObject>

    oc = CommentService.findForDoc(doc) .flatMap(c -> UserService.find(c.getUserId()) .first() .map(u -> { 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; }); Observable<JsonObject> fullDocumentJson = DocumentService.find("user") .filter(Document::isStarred) .take(10)
  16. Observable<JsonObject> fullDocumentJson = DocumentService.find("user") .filter(Document::isStarred) .take(10) .map(doc -> { Observable<JsonObject>

    oc = CommentService.findForDoc(doc) .flatMap(c -> UserService.find(c.getUserId()) .first() .map(u -> { 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; }); Observable<JsonObject> oc = CommentService.findForDoc(doc) .flatMap(c -> UserService.find(c.getUserId()) .first() .map(u -> { JsonObject result = jsonify(c) .append("author", u.getName()); .append("nickname", u.getLogin()) .append("email", u.getEmail()); return result; }) );
  17. Observable<JsonObject> fullDocumentJson = DocumentService.find("user") .filter(Document::isStarred) .take(10) .map(doc -> { Observable<JsonObject>

    oc = CommentService.findForDoc(doc) .flatMap(c -> UserService.find(c.getUserId()) .first() .map(u -> { 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; }); oc.reduce(c, (array, elem) -> array.addElement(elem));
  18. 2 1 slides en taille 10 58 23 lignes de

    code max 7 3 tabulations 3 0 imbrications
  19. Crédits ➔ The Door to Hell - By-Sa Flydime http://www.flickr.com/photos/flydime/4671890969

    ➔ Cat Attack - By-Nc Static416 http://www.flickr.com/photos/ehacke/4584255926/ ➔ Série Stormtroopers - By J.D. Hancock http://photos.jdhancock.com/series/stormtroopers.html ➔ Marbles Reflected - By ~Pawsitive~Candie_N http://www.flickr.com/photos/scjn/4274713988/ ➔ Marble Diagrams - Apache 2.0 Netflix OSS http://netflix.github.io/ (doc RxJava) ➔ Chien de près - By Rpavich http://www.flickr.com/photos/rpavich/11409595543/ ➔ Hyperspace - By Procsilas Moscas http://www.flickr.com/photos/procsilas/ 12821454664/ ➔ Takeaway - By Edimbhurg Blog http://www.flickr.com/photos/theedinburghblog/ 6493647769/ ➔ The End Sable - Cc0 Elektro-Plan http://pixabay.com/p-283407/