sábado, 12 de enero de 2013

Lo que amo de Scala: su cercanía a Java

Estoy en el proceso de registrar lo indispensable de Scala para el día que mire seriamente a otros lenguajes  "Mirar seriamente" es hacer un poco más que leer un tutorial y programar un "hello world", o sea demanda algo de esfuerzo.  No tengo el tiempo de revisar todos los lenguajes que se inventan así que debo filtrar los potenciales candidatos.  Por el momento, son Kotlin, Ceylon e Xtend porque todos comparten la cercanía con Java.

Esta cercanía con Java es importante por varias razones.

Por la JVM, los servidores de aplicación y en general los middleware basados en la JVM

No todos tenemos la suerte de trabajar para una startup que puede escoger completamente su arquitectura y, por ende, debemos negociar con el cliente la tecnología que se usará.  Casi todos los clientes tienen una plataforma definida y resulta más o menos difícil alterarla según lo que esta definición cubre.

Casi siempre, la definición de plataforma incluye la arquitectura física (servidores, redes, sistemas operativos, estaciones clientes) y la arquitectura de ejecución, o sea los middleware como los servidores de aplicación, servidores de mensajería y las bases de datos.  Es muy frecuente poder usar un middleware basado en la JVM

Otras veces la definición de plataforma incluye la arquitectura de desarrollo o sea, los lenguajes, las API, los frameworks, patrones y hasta el IDE de desarrollo.  En este caso, si el cliente pide Java+Spring-*, hay que tratar de convencerlo.  En la practica, es más fácil negociar cambiar la arquitectura de desarrollo que las arquitecturas físicas y de ejecución.

En resumen, la JVM y sus middleware (Tomcat, Websphere, Weblogic) son importantes por un tema de oportunidad laboral   

He leído que otros destacan la robustez, el performance, la seguridad y en general, la madurez de la JVM.  Estoy de acuerdo con estos argumentos y son las razones por las cuales, hay middleware basados en la JVM en todas partes.

Por las toneladas de API's y framework para Java

La popularidad de Java permite que haya soluciones para todo y a menudo de bajo costo.  No recuerdo cuando fue la ultima vez que me preocupe de encontrar un driver JDBC compatible con la versión de mi base de datos: no quiero pasar por lo mismo si me salgo de la JVM.

Poco a poco, hay API y framework que son optimizados para Scala, pero siempre habrá necesidades de usar esta vieja API Java que saca de apuro.

Por la sintaxis

Java hereda muchas ideas archi probadas en distintos lenguajes y que son familiares para muchos programadores.  Scala sigue usando:
  • la sintaxis básica de C usando bracket y donde una llamada a una función "f" se escribe como en las matemáticas básicas: "y = f (x)"
  • strong typing.  Me gusta que el compilador y el IDE trabajen por mi y no al revés
  • orientación al objeto.  Definitivamente no es la solución para todo, pero es necesario tenerla.
  • programación genérica. Hace el código más legible.
  • estilo imperativo.  No siempre se puede programar al estilo funcional en forma elegante.  El estilo imperativo saca de apuros, lo tengo comprobado.

Por los entornos de programación

Es tiempo ganado si no tengo que cambiar mi IDE (Netbeans, Eclipse), mi build automation (ant, maven), etc.

Lista de lenguajes que descarte

Todos los criterios anteriores me hicieron descartar:
  • los derivados de Lisp como Scheme, Clojure.  No hay ninguna razón para mantener una sintaxis que va contra años de enseñanza de las matemáticas.  Yo creo que usar estos lenguajes para tutoriales de programación funcional crea una barrera completamente absurda.
  • Ruby, Python: son dinámicos, su entorno "natural" no es la JVM.
  • Haskell, Erlang: no corren sobre la JVM y su sintaxis me recuerda demasiado a Lisp.
  • fantom: no tiene programación genérica.





Lo que me agrada de Scala: de NPE a Option

Sigo poblando mi lista de lo que me gusta del lenguaje Scala.  La motivación es poder comparar con otros lenguajes parecidos que están llegando para la JVM como Ceylon/Kotlin/Xtend y tener claro lo que tienen que ofrecer estos lenguajes para que valga la pena mirarlos con un poco más de detalle.  En este contexto, cabe mencionar esta encuesta de Infoq donde hay una lista de lenguajes potenciales y donde Scala y Clojure están bien posicionados.

Los títulos anteriores de mis entradas sobre el mismo tema empezaban con "Lo que amo de Scala".  Ahora voy a hablar de algo que solamente me agrada.

Donde Scala se contagia de Java

NullPointerException o NPE existen porque cualquier objeto en la JVM puede tener el valor null.  No hay forma en Java garantizar que un objeto es distinto de null excepto validandolo antes de referenciarlo.  Si se valida en forma paranoica todos los parámetros de entrada  y retornos de los métodos, se agrega mucho código bastante inútil.  La otra solución es no validar nada y capturar la NPE lo más inteligentemente posible. Si se opta por no validar, en algún momento aparecerá el NPE en algún log y ojala antes de entrar en producción.

Scala corre sobre la JVM e necesita interoperar con código Java.  Sigue existiendo el valor null y la posibilidad de NPE incluso en código 100% Scala.


Valores opcionales

Java no permite hacer la distinción entre un objeto que es nulo por error o intencionalmente sin valor.  Un objeto puede estar sin valor:
  • porque es naturalmente opcional, como el calculo de un valor máximo sobre una colección vacía o el retorno de una consulta por una primary key que no existe.
  • porque no conocemos aun su valor:
    • hay que rescatarlo con algún proceso largo, 
    • es un valor externo que debemos rescatar de parámetros de ambiente, archivos de configuración o preguntar al usuario.
En Java se puede manejar estas situaciones con objetos nulos o lanzando excepciones.  En SQL se puede definir un campo como "NULL" o "NOT NULL".  Scala soluciona este caso con el tipo Option y los subtipos None y Some.

Ejemplo de un atributo que es opcional y cuyo valor se conoce al runtime.


Un caso frecuente en mis aplicaciones es durante la inicialización de actores con el framework Akka.  Generalmente, los actores se crean en unos pocos thread y si su inicialización es larga (por ejemplo, porque tienen que rescatar algo de una base de datos) el arranque de la aplicación akka es lenta.  Entonces, el arranque del actor se hace en 2 pasos: la creación del actor mismo y luego su inicialización procesando un mensaje de "arranque".  Entre estos 2 pasos hay atributos del actor que no están conocidos aun.


Algunos comentarios finales

Entonces, porque solamente me agradan los Option y no los adoro:
  • Habría sido espectacular eliminar el valor nulo y la NPE por completo.  Pero prefiero mil veces mantener la interoperabilidad con Java, la cual si adoro.
  • Ceylon y Kotlin tienen una sintaxis especial para manejar los nulos la cual permite código más corto y más legible.  Scala no usa sintaxis especial, sino la capacidad de su type system.  El mismo type system permite implementar tipos equivalentes como los Box/Full/Empty/Failure del framework Liftweb .
En resumen, Scala mejora Java sin erradicar por completo el problema.