Loading…

Flash Player 9 (or above) is needed to view presentations.
We have detected that you do not have it on your computer. To install it, go here.

Like this presentation? Why not share!

Un tour por Java, Scala, Python, Ruby y Javascript

on

  • 1,270 views

 

Statistics

Views

Total Views
1,270
Views on SlideShare
1,255
Embed Views
15

Actions

Likes
1
Downloads
11
Comments
0

2 Embeds 15

https://twitter.com 14
http://blog.continuum.cl 1

Accessibility

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />

Un tour por Java, Scala, Python, Ruby y Javascript Un tour por Java, Scala, Python, Ruby y Javascript Presentation Transcript

  • Un tour por Java, Scala, Python, Ruby y JavaScript Leo Soto M. Developer @ Hashrocket Chile / Continuum Encuentro Linux 2010
  • Problema:
  • Un servicio penca...
  • Solución: ¡ser insistente!
  • def servicio_penca: print “servicio invocado” randomly raise SomeException print “servicio ejecutado” def solucion: retry servicio_penca 10 times when SomeException waiting 2 seconds
  • Java
  • import static java.lang.System.out; import static java.lang.Math.random; public class ... {      static class GuateoException extends Exception {};        static void servicioPenca() throws GuateoException { out.println("Servicio invocado"); if (random() < 0.8) { throw new GuateoException(); } out.println("Servicio ejecutado exitosamente");   } ... }
  • Intento Nº1: Solución obvia
  • public class RetryPenca { ... static void solucion() throws GuateoException { int times = 10; int wait = 2 * 1000; // 2 segundos GuateoException lastException = null; while (times-- > 0) { try { servicioPenca(); return; } catch (GuateoException e) { lastException = e; sleep(wait); } } static void sleep(int millis) { try { Thread.sleep(millis); } catch (InterruptedException e) {};   } }
  • public class RetryPenca { ... static void solucion() throws GuateoException { int times = 10; int wait = 2 * 1000; // 2 segundos GuateoException lastException = null; while (times-- > 0) { try { servicioPenca(); return; } catch (GuateoException e) { lastException = e; sleep(wait); } } static void sleep(int millis) { try { Thread.sleep(millis); } catch (InterruptedException e) {};   } }
  • public class RetryPenca { ... static void solucion() throws GuateoException { int times = 10; int wait = 2 * 1000; // 2 segundos GuateoException lastException = null; while (times-- > 0) { try { servicioPenca(); return; } catch (GuateoException e) { lastException = e; sleep(wait); } } static void sleep(int millis) { try { Thread.sleep(millis); } catch (InterruptedException e) {};   } }
  • public class RetryPenca { ... static void solucion() throws GuateoException { int times = 10; int wait = 2 * 1000; // 2 segundos GuateoException lastException = null; while (times-- > 0) { try { servicioPenca(); return; } catch (GuateoException e) { lastException = e; sleep(wait); } } static void sleep(int millis) { try { Thread.sleep(millis); } catch (InterruptedException e) {};   } }
  • public class RetryPenca { ... static void solucion() throws GuateoException { int times = 10; int wait = 2 * 1000; // 2 segundos GuateoException lastException = null; while (times-- > 0) { try { servicioPenca(); return; } catch (GuateoException e) { lastException = e; sleep(wait); } } static void sleep(int millis) { try { Thread.sleep(millis); } catch (InterruptedException e) {};   } }
  • Intento Nº2: Solución “funcional”
  • public class RetryDecente { ... static void solucion() { retry(10, GuateoException.class, 2000, new Runnable() { public void run() { servicioPenca(); } }); } ... }
  • public class RetryDecente { ... static void retry( int times, Class<? extends RuntimeException> exceptionClass, int sleepMillis, Runnable what) { RuntimeException lastException = null; while (times-- > 0) { try { what.run(); return; } catch (RuntimeException e) { if (exceptionClass.isAssignableFrom(e.getClass())) { sleep(sleepMillis); lastException = e; } else { throw e; } } } throw lastException; } }
  • public class RetryDecente { ... static void retry( int times, Class<? extends RuntimeException> exceptionClass, int sleepMillis, Runnable what) { RuntimeException lastException = null; while (times-- > 0) { try { what.run(); return; } catch (RuntimeException e) { if (exceptionClass.isAssignableFrom(e.getClass())) { sleep(sleepMillis); lastException = e; } else { throw e; } } } throw lastException; } }
  • public class RetryDecente { ... static void retry( int times, Class<? extends RuntimeException> exceptionClass, int sleepMillis, Runnable what) { RuntimeException lastException = null; while (times-- > 0) { try { what.run(); return; } catch (RuntimeException e) { if (exceptionClass.isAssignableFrom(e.getClass())) { sleep(sleepMillis); lastException = e; } else { throw e; } } } throw lastException; } }
  • import static java.lang.System.out; import static java.lang.Math.random; public class ... {      static class GuateoException extends Exception {};        static void servicioPenca() throws GuateoException { out.println("Servicio invocado"); if (random() < 0.8) { throw new GuateoException(); } out.println("Servicio ejecutado exitosamente");   } ... }
  • import static java.lang.System.out; import static java.lang.Math.random; public class ... {      static class GuateoException extends RuntimeException {};        static void servicioPenca() throws GuateoException { out.println("Servicio invocado"); if (random() < 0.8) { throw new GuateoException(); } out.println("Servicio ejecutado exitosamente");   } ... }
  • Intento Nº3: Solución “funcional” y genérica
  • public class RetryDecenteGenerico { ... static void solucion() throws Exception { Retry.retry(10, GuateoException.class, 2000, new Retry.Runnable() { public Object run() throws GuateoException { servicioPenca(); return null; } }); } ... }
  • public class RetryDecenteGenerico { ... static class Retry { static interface Runnable { Object run() throws Exception; } static Object retry(int times, Class<? extends Exception> exceptionClass, int sleepMillis, Runnable what) throws Exception { Exception lastException = null; while (times-- > 0) { try { return what.run(); } catch (Exception e) { if (exceptionClass.isAssignableFrom(e.getClass())) { sleep(sleepMillis); lastException = e; } else { throw e; } } } throw lastException; } } ... }
  • public class RetryDecenteGenerico { ... static void solucion() throws Exception { Retry.retry(10, GuateoException.class, 2000, new Retry.Runnable() { public Object run() throws GuateoException { servicioPenca(); return null; } }); } ... }
  • public class RetryDecenteGenerico { ... static void solucion() throws Exception { Retry.retry(10, GuateoException.class, 2000, new Retry.Runnable() { public Object run() throws GuateoException { servicioPenca(); return null; } }); } ... }
  • public class RetryDecenteGenerico { ... static void solucion() throws Exception { Retry.retry(10, GuateoException.class, 2000, new Retry.Runnable() { public Object run() throws GuateoException { servicioPenca(); return null; } }); } ... }
  • Intento Nº4: Solución “funcional” y genérica y con method chaining
  • public class RetryCool { ... static void solucion() throws Exception { Retry.times(10).when(GuateoException.class).wait(2000).execute( new Retry.Runnable() { public Object run() throws GuateoException{ servicioPenca(); return null; } } ) } ... }
  • public class RetryCool { ... static class Retry { static interface Runnable { Object run() throws Exception; } static Retry times(int times) { return new Retry(times); } int times; int wait; Class<? extends Exception> exceptionClass; Retry(int times) { this.times = times; } Retry wait(int wait) { this.wait = wait; return this; } Retry when(Class<? extends Exception> exceptionClass) { this.exceptionClass = exceptionClass; return this; } ...
  • public class RetryCool { ... static class Retry { ... Object execute(Retry.Runnable what) throws Exception { Exception lastException = null; while (times-- > 0) { try { return what.run(); } catch (Exception e) { if (exceptionClass.isAssignableFrom(e.getClass())) { sleep(wait); lastException = e; } else { throw e; } } } throw lastException; } } ... }
  • public class RetryCool { ... static void solucion() throws Exception { Retry.times(10).when(GuateoException.class).wait(2000).execute( new Retry.Runnable() { public Object run() throws GuateoException{ servicioPenca(); return null; } } ) } ... }
  • public class RetryCool { ... static void solucion() throws Exception { Retry.times(10).when(GuateoException.class).wait(2000).execute( new Retry.Runnable() { public Object run() throws GuateoException{ servicioPenca(); return null; } } ) } ... }
  • Resultado Java “funcional”: ~ 80 líneas Un montón de contorsiones en la implementación
  • Wait, pero en Java el martillo es la POO (¡y toooodo tiene pinta de clavo!)
  • Intento Nº5:
  • Intento Nº5: RetryFramework
  • public class RetryFramework { ... static class SolucionRetryable extends Retryable { protected Object run() throws GuateoException { servicioPenca(); return null; } } static void solucion() throws Exception { SolucionRetryable s = new SolucionRetryable(); s.times = 10; s.when = GuateoException.class; s.wait = 2000; s.start(); } ... }
  • public class RetryFramework { ... static abstract class Retryable { public int times; public Class<? extends Exception> when; public int wait; abstract protected Object run() throws Exception; public Object start() throws Exception { Exception lastException = null; while (times-- > 0) { try { return run(); } catch (Exception e) { if (when.isAssignableFrom(e.getClass())) { sleep(wait); lastException = e; } else { throw e; } } } throw lastException; }   } ... }
  • public class RetryFramework { ... static abstract class Retryable { public int times; public Class<? extends Exception> when; public int wait; abstract protected Object run() throws Exception; public Object start() throws Exception { Exception lastException = null; while (times-- > 0) { try { return run(); } catch (Exception e) { if (when.isAssignableFrom(e.getClass())) { sleep(wait); lastException = e; } else { throw e; } } } throw lastException; }   } ... }
  • public class RetryFramework { ... static class SolucionRetryable extends Retryable { protected Object run() throws GuateoException { servicioPenca(); return null; } } static void solucion() throws Exception { SolucionRetryable s = new SolucionRetryable(); s.times = 10; s.when = GuateoException.class; s.wait = 2000; s.start(); } ... }
  • public class RetryFramework { ... static class SolucionRetryable extends Retryable { protected Object run() throws GuateoException { servicioPenca(); return null; } } static void solucion() throws Exception { SolucionRetryable s = new SolucionRetryable(); s.times = 10; s.when = GuateoException.class; s.wait = 2000; s.start(); } ... }
  • public class RetryFramework { ... static class SolucionRetryable extends Retryable { String param; public SolucionRetryable(String param) { this.param = param; } protected Object run() throws GuateoException { servicioPenca(param); return null; } } static void solucion() throws Exception { SolucionRetryable s = new SolucionRetryable("Que horrible!”); s.times = 10; s.when = GuateoException.class; s.wait = 2000; s.start(); } ... }
  • public class RetryFramework { ... static class SolucionRetryable extends Retryable { String param; public SolucionRetryable(String param) { this.param = param; } protected Object run() throws GuateoException { servicioPenca(param); return null; } } static void solucion() throws Exception { SolucionRetryable s = new SolucionRetryable("Que horrible!”); s.times = 10; s.when = GuateoException.class; s.wait = 2000; s.start(); } ... }
  • Resultado Java “framework”: ~ 70 líneas Un montón de contorsiones en la interfaz.
  • Y también: http://steve-yegge.blogspot.com/2006/03/execution-in- kingdom-of-nouns.html
  • Scala
  • import java.lang.Math object Retry { class GuateoException extends Exception   def servicioPenca {     println("Servicio invocado")     if (Math.random < 0.8) {       throw new GuateoException     }     println("Servicio ejecutado exitosamente")   } ... }
  • object Retry { ... def solucion {     retry(times=10, when=classOf[GuateoException], wait=2000) {       servicioPenca     }   } ... }
  • object Retry { def solucion {     retry(times=10, when=classOf[GuateoException], wait=2000) {       servicioPenca     }   } def retry[R, E <: Exception](times: Int, when: Class[E], wait: Int) (body: => R): R = {     var lastException:Throwable = null     for (i <- 0 until times) { try { return body       } catch { case e => { if (when isAssignableFrom e.getClass()) { lastException = e Thread.sleep(wait) } else { throw e } }       }     }     throw lastException }
  • object Retry { def solucion {     retry(times=10, when=classOf[GuateoException], wait=2000) {       servicioPenca     }   } def retry[R, E <: Exception](times: Int, when: Class[E], wait: Int) (body: => R): R = {     var lastException:Throwable = null     for (i <- 0 until times) { try { return body       } catch { case e => { if (when isAssignableFrom e.getClass()) { lastException = e Thread.sleep(wait) } else { throw e } }       }     }     throw lastException }
  • object Retry { def solucion {     retry(times=10, when=classOf[GuateoException], wait=2000) {       servicioPenca     }   } def retry[R, E <: Exception](times: Int, when: Class[E], wait: Int) (body: => R): R = {     var lastException:Throwable = null     for (i <- 0 until times) { try { return body       } catch { case e => { if (when isAssignableFrom e.getClass()) { lastException = e Thread.sleep(wait) } else { throw e } }       }     }     throw lastException }
  • object Retry { ... def retry[R, E <: Exception](times: Int, when: Class[E], wait: Int) (body: => R): R = {     var lastException:Throwable = null     for (i <- 0 until times) { try { return body       } catch { case e => { if (when isAssignableFrom e.getClass()) { lastException = e Thread.sleep(wait) } else { throw e } }       }     }     throw lastException ... }
  • object Retry { ... def retry[R, E <: Exception](times: Int, when: Class[E], wait: Int) (body: => R): R = {     var lastException:Throwable = null     for (i <- 0 until times) { try { return body       } catch { case e => { if (when isAssignableFrom e.getClass()) { lastException = e Thread.sleep(wait) } else { throw e } }       }     }     throw lastException ... }
  • object Retry { ... def retry[R, E <: Exception](times: Int, when: Class[E], wait: Int) (body: => R): R = {     var lastException:Throwable = null     for (i <- 0 until times) { try { return body       } catch { case e => { if (when isAssignableFrom e.getClass()) { lastException = e Thread.sleep(wait) } else { throw e } }       }     }     throw lastException ... }
  • object Retry { ... def solucion {     retry(times=10, when=classOf[GuateoException], wait=2000) {       servicioPenca     }   } ... }
  • object Retry { ... def retry[R, E <: Exception](times: Int, when: Class[E], wait: Int) (body: => R): R = {     var lastException:Throwable = null     for (i <- 0 until times) { try { return body       } catch { case e => { if (when isAssignableFrom e.getClass()) { lastException = e Thread.sleep(wait) } else { throw e } }       }     }     throw lastException ... }
  • object Retry { ... def retry[R, E <: Exception](times: Int, when: Class[E], wait: Int) (body: => R): R = {     var lastException:Throwable = null     for (i <- 0 until times) { try { return body       } catch { case e => { if (when isAssignableFrom e.getClass()) { lastException = e Thread.sleep(wait) } else { throw e } }       }     }     throw lastException ... }
  • object Retry { ... def retry[R, E <: Exception](times: Int, when: Class[E], wait: Int) (body: => R): R = {     var lastException:Throwable = null     for (i <- 0 until times) { try { return body       } catch { case when => e { lastException = e Thread.sleep(wait) }       }     }     throw lastException ... }
  • object Retry { ... def retry[R, E <: Exception](times: Int, when: Class[E], wait: Int) (body: => R): R = {     var lastException:Throwable = null     for (i <- 0 until times) { try { return body       } catch { case when => e { lastException = e Thread.sleep(wait) }       }     }     throw lastException ... }
  • Resultado Scala: ~ 40 líneas Elegante. E incluye type-safety.* Pros: Contras: • Funciones 1º clase • Matching de excepciones • Funciones anónimas estático • + Syntactic Sugar • Parámetros con nombre * Honestamente me importa un pepino, pero sirve para despertar a los que juran de guata que quedarse en Java es buena idea porque es lo mas type-safe que hay
  • Python
  • import random class GuateoException(Exception): pass def servicio_penca():   print "Servicio invocado"   if random.random() < 0.8:       raise GuateoException()   print "Servicio ejecutado exitosamente"
  • def solucion():     retry(servicio_penca, when=GuateoException, times=10, wait=2) def retry(callable, when, times, wait):     last_exception = None     while times > 0:         times -= 1         try:             return callable()         except when, exception:             time.sleep(wait)             last_exception = exception     raise last_exception
  • def solucion():     retry(servicio_penca, when=GuateoException, times=10, wait=2) def retry(callable, when, times, wait):     last_exception = None     while times > 0:         times -= 1         try:             return callable()         except when, exception:             time.sleep(wait)             last_exception = exception     raise last_exception MEGA
  • def solucion():     retry(servicio_penca, when=GuateoException, times=10, wait=2) def retry(callable, when, times, wait):     last_exception = None     while times > 0:         times -= 1         try:             return callable()         except when, exception:             time.sleep(wait)             last_exception = exception     raise last_exception
  • def solucion():     retry(servicio_penca, when=GuateoException, times=10, wait=2) def retry(callable, when, times, wait):     last_exception = None     while times > 0:         times -= 1         try:             return callable()         except when, exception:             time.sleep(wait)             last_exception = exception     raise last_exception
  • def solucion():     retry(servicio_penca, when=GuateoException, times=10, wait=2) def retry(callable, when, times, wait):     last_exception = None     while times > 0:         times -= 1         try:             return callable()         except when, exception:             time.sleep(wait)             last_exception = exception     raise last_exception
  • Peero
  • def solucion():     retry(servicio_penca, when=GuateoException, times=10, wait=2) def retry(callable, when, times, wait):     last_exception = None     while times > 0:         times -= 1         try:             return callable()         except when, exception:             time.sleep(wait)             last_exception = exception     raise last_exception
  • def solucion():     retry(lambda: servicio_penca(args), when=GuateoException, times=10, wait=2) def retry(callable, when, times, wait):     last_exception = None     while times > 0:         times -= 1         try:             return callable()         except when, exception:             time.sleep(wait)             last_exception = exception     raise last_exception
  • def llamar_a_todos_los_servicios(): servicio_1() servicio_2() def solucion():     retry(llamar_a_todos_los_servicios, when=GuateoException, times=10, wait=2) def retry(callable, when, times, wait):     last_exception = None     while times > 0:         times -= 1         try:             return callable()         except when, exception:             time.sleep(wait)             last_exception = exception     raise last_exception
  • Resultado Python: ~ 30 líneas Shortest code ever. Pros: Contras: • Funciones 1º clase • No hay sintaxis para • Parámetros con nombre funciones anónimas multi- • Matching de excepciones línea ni “bloques” dinámico
  • Ruby
  • class GuateoException < Exception; end def servicio_penca   puts "Servicio invocado"   raise GuateoException if rand < 0.8   puts "Servicio ejecutado exitosamente" end
  • def solucion   retrying 10.times, :when => GuateoException, :wait => 2 do     servicio_penca   end end def retrying(n_times, options = {})   exception_class = options[:when] || Exception   wait_time = options[:wait] || 0   last_exception = nil   n_times.each do     begin       return yield     rescue exception_class => e       last_exception = e       sleep wait_time     end   end   raise last_exception end
  • def solucion   retrying 10.times, :when => GuateoException, :wait => 2 do     servicio_penca   end end def retrying(n_times, options = {})   exception_class = options[:when] || Exception   wait_time = options[:wait] || 0   last_exception = nil   n_times.each do     begin       return yield     rescue exception_class => e       last_exception = e       sleep wait_time     end   end   raise last_exception end
  • def solucion   retrying 10.times, :when => GuateoException, :wait => 2 do     servicio_penca   end end def retrying(n_times, options = {})   exception_class = options[:when] || Exception   wait_time = options[:wait] || 0   last_exception = nil   n_times.each do     begin       return yield     rescue exception_class => e       last_exception = e       sleep wait_time     end   end   raise last_exception end
  • def solucion   retrying 10.times, :when => GuateoException, :wait => 2 do     servicio_penca   end end def retrying(n_times, options = {})   exception_class = options[:when] || Exception   wait_time = options[:wait] || 0   last_exception = nil   n_times.each do     begin       return yield     rescue exception_class => e       last_exception = e       sleep wait_time     end   end   raise last_exception end
  • def solucion   retrying 10.times, :when => GuateoException, :wait => 2 do     servicio_penca   end end def retrying(n_times, options = {})   exception_class = options[:when] || Exception   wait_time = options[:wait] || 0   last_exception = nil   n_times.each do     begin       return yield     rescue exception_class => e       last_exception = e       sleep wait_time     end   end   raise last_exception end
  • def solucion   retrying 10.times, :when => GuateoException, :wait => 2 do     servicio_penca   end end def retrying(n_times, options = {})   exception_class = options[:when] || Exception   wait_time = options[:wait] || 0   last_exception = nil   n_times.each do     begin       return yield     rescue exception_class => e       last_exception = e       sleep wait_time     end   end   raise last_exception end
  • def solucion   retrying 10.times, :when => GuateoException, :wait => 2 do     servicio_penca   end end def retrying(n_times, options = {})   exception_class = options[:when] || Exception   wait_time = options[:wait] || 0   last_exception = nil   n_times.each do     begin       return yield     rescue exception_class => e       last_exception = e       sleep wait_time     end   end   raise last_exception end
  • def solucion   retrying 10.times, :when => GuateoException, :wait => 2 do     servicio_penca   end end def retrying(n_times, options = {})   exception_class = options[:when] || Exception   wait_time = options[:wait] || 0   last_exception = nil   n_times.each do     begin       return yield     rescue exception_class => e       last_exception = e       sleep wait_time     end   end   raise last_exception end
  • Resultado Ruby: ~ 35 líneas Aún mas elegante que en Scala Pros: Contras: • Sintaxis de Bloques • Sin soporte directo de • Syntactic Sugar built-in parámetros con nombre. • Matching de excepciones dinámico
  • Javascript
  • function servicioPenca() { print("Servicio invocado");   if (Math.random() < 0.8) { throw "GuateoException";   }   print("Servicio ejecutado exitosamente"); }
  • function solucion() { retry({times: 10, when: "GuateoException", wait: 2}, servicioPenca); } function retry(options, callback) { var lastException = null; var times = options.times || 10; var exception = options.when; var wait = options.wait; while (times-- > 0) { try { return callback(); } catch (e) { if (!exception || exception == e) { sleep(wait); lastException = e; } else { throw e; } } } throw lastException; }
  • function solucion() { retry({times: 10, when: "GuateoException", wait: 2}, servicioPenca); } function retry(options, callback) { var lastException = null; var times = options.times || 10; var exception = options.when; var wait = options.wait; while (times-- > 0) { try { return callback(); } catch (e) { if (!exception || exception == e) { sleep(wait); lastException = e; } else { throw e; } } } throw lastException; }
  • function solucion() { retry({times: 10, when: "GuateoException", wait: 2}, servicioPenca); } function retry(options, callback) { var lastException = null; var times = options.times || 10; var exception = options.when; var wait = options.wait; while (times-- > 0) { try { return callback(); } catch (e) { if (!exception || exception == e) { sleep(wait); lastException = e; } else { throw e; } } } throw lastException; }
  • function solucion() { retry({times: 10, when: "GuateoException", wait: 2}, servicioPenca); } function retry(options, callback) { var lastException = null; var times = options.times || 10; var exception = options.when; var wait = options.wait; while (times-- > 0) { try { return callback(); } catch (e) { if (!exception || exception == e) { sleep(wait); lastException = e; } else { throw e; } } } throw lastException; }
  • function solucion() { retry({times: 10, when: "GuateoException", wait: 2}, servicioPenca); } function retry(options, callback) { var lastException = null; var times = options.times || 10; var exception = options.when; var wait = options.wait; while (times-- > 0) { try { return callback(); } catch (e) { if (!exception || exception == e) { sleep(wait); lastException = e; } else { throw e; } } } throw lastException; }
  • function solucion() { retry({times: 10, when: "GuateoException", wait: 2}, servicioPenca); } function retry(options, callback) { var lastException = null; var times = options.times || 10; var exception = options.when; var wait = options.wait; while (times-- > 0) { try { return callback(); } catch (e) { if (!exception || exception == e) { sleep(wait); lastException = e; } else { throw e; } } } throw lastException; }
  • function solucion() { retry({times: 10, when: "GuateoException", wait: 2}, servicioPenca); } function retry(options, callback) { var lastException = null; var times = options.times || 10; var exception = options.when; var wait = options.wait; while (times-- > 0) { try { return callback(); } catch (e) { if (!exception || exception == e) { sleep(wait); lastException = e; } else { throw e; } } } throw lastException; }
  • Y si la estrategia se parece a Python, ¿Tendrá el mismo problema?
  • function solucion() { retry({times: 10, when: "GuateoException", wait: 2}, servicioPenca); } function retry(options, callback) { var lastException = null; var times = options.times || 10; var exception = options.when; var wait = options.wait; while (times-- > 0) { try { return callback(); } catch (e) { if (!exception || exception == e) { sleep(wait); lastException = e; } else { throw e; } } } throw lastException; }
  • function solucion() { retry({times: 10, when: "GuateoException", wait: 2}, function() { servicioPenca(arg); }); } function retry(options, callback) { var lastException = null; var times = options.times || 10; var exception = options.when; var wait = options.wait; while (times-- > 0) { try { return callback(); } catch (e) { if (!exception || exception == e) { sleep(wait); lastException = e; } else { throw e; } } } throw lastException; }
  • function solucion() { retry({times: 10, when: "GuateoException", wait: 2}, function() { servicio1(); servicio2(); }); } function retry(options, callback) { var lastException = null; var times = options.times || 10; var exception = options.when; var wait = options.wait; while (times-- > 0) { try { return callback(); } catch (e) { if (!exception || exception == e) { sleep(wait); lastException = e; } else { throw e; } } } throw lastException; }
  • Resultado Javascript: ~ 40 líneas ¿Quien diablos le puso JavaScript? Pros: Contras: • Funciones 1º clase • Sin soporte directo de • Funciones anónimas parámetros con nombre. • Sin matching de excepciones.
  • Entonces, ¿cual sería el lenguaje ideal?
  • Abstracciones útiles en un lenguaje para el problema visto:
  • Funciones 1º clase: Scala, Python, Javascript
  • Funciones anónimas multi-línea: Scala, JavaScript
  • Sintaxis especial para bloques: Ruby, Scala* * La de Scala no es específicamente para bloques, sino mas bien syntax sugar para funciones anónimas. Pero las mejora!
  • Matching de Excepciones Java, Scala, Python, Ruby
  • Matching de Excepciones Dinámico: Python, Ruby
  • Parámetros por nombre: Scala, Python
  • Extensión de objetos predefinidos Scala, Ruby
  • ¡Shit, no hay lenguaje ideal!
  • That’s life.
  • Aprendan varios, para que siempre...
  • ...de la lista que manejan, haya al menos uno...
  • ...que se adecúe al problema que tienen en frente.
  • ¡Sean políglotas!
  • ¡Gracias!