¿Ceylon constituye una plataforma o eso no está en sus planes?

Hola, saludos cordiales a la comunidad.

Sigo con mis preguntas provocadoras.

Me queda claro que Ceylon es un lenguaje que busca hacerle la vida más sencilla a los desarrolladores prescindiendo de varios de los elementos negativos de Java y adoptando características valiosas de otros paradigmas (programación funcional, mixins, por ejemplo), ya en sí es una discusión si hace falta un nuevo lenguaje o si algún lenguaje existente resuelve las preocupaciones que Ceylon intenta resolver.

Haciendo el supuesto de que Ceylon en efecto resuelve problemas y preocupaciones que ningún otro lenguaje podía resolver, ahora quiero lanzar otra pregunta provocadora.

Antes un breve prólogo.

El lenguaje Java en su momento tuvo un enorme impacto porque contribuyó a extender a la amplia mayoría algo que antes era tema solo de iniciados: la programación orientada a objetos, además de que en su biblioteca estándar incorporó una serie de facilidades que ayudaron a crear fácilmente aplicaciones para Internet (que en esa época empezaron a brotar como hongos por todos lados). De esa manera, Java paso muy rápidamente de ser solo un lenguaje a constituirse en toda una plataforma para soportar múltiples tipos de aplicaciones y esto generó una amplia adopción por parte de la comunidad desarrolladora.

Con otros lenguajes, como Python o Ruby eventualmente ha ocurrido lo mismo (por ejemplo Python tiene una plataforma completa con Zope y BlueBream - o Django también, y algo similar ha sucedido con Ruby-Ruby on Rails - el caso de TorqueBox es interesante).

Inclusive PHP, pese a todas las deficiencias del lenguaje, tiene a su favor una biblioteca estándar muy amplia y un grado de adopción enorme que conforman una plataforma.

Mi pregunta es: ¿para dónde va Ceylon, cual es su visión al respecto? ¿buscan eventualmente crear una plataforma? ¿su plan es montarse sobre una plataforma existente (por ejemplo Java EE con JBoss)? ¿o más bien hacer algo como lo que están haciendo con Scala - Akka - Play? ¿o eso no es una preocupación en este momento y solo están enfocados en el lenguaje?.

Gracias de antemano por compartir sus puntos de vista.

Saludos

J. Reynaga

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

Plataforma

Definitivamente se busca tener una plataforma. Es por ello que desde el inicio Ceylon tiene su propio SDK; eso te permite un cierto grado de independencia y es la razón por la que ya desde hoy puedes compilar código Ceylon a bytecode y a JavaScript; el SDK lo tenemos implementado para la JVM y para JavaScript. Y ya hay alguien trabajando en poder compilar Ceylon a IL para que corra sobre el CLR (o sea .NET), aunque eso es (al menos por ahora) un proyecto externo en el que solamente estamos apoyando con resolver algunas dudas y cosas así).

Un aspecto importante de Ceylon, del que no he escrito al respecto aquí, es el sistema de módulos. Tengo pendiente escribir un buen post al respecto, pero pues en resumen es como una mezcla entre Ivy y Grape. Es parte integral del proceso de compilación y de la arquitectura de nuestra plataforma, para evitar el tener que depender de cosas como Maven o tener un SDK monolítico como tiene hoy Java.

Para el backend en Java, la intención inicialmente era un poco montarse sobre el sistema de módulos de JBoss 7, pero parece que no será necesario. Ya hoy existe Herd, que es un sistema de repositorios para módulos de Ceylon. Con Herd puedes administrar tu propio repositorio privado, entonces por ejemplo en una empresa podrías tener tu repo privado y poner ahí todos los módulos que son internos, y a la vez usar el repositorio público de Ceylon para jalar módulos externos. Lo interesante es que se vuelve parte del proyecto, no es algo externo que dependa puramente de archivos de configuración. Por ejemplo, imagínate que estás programando algo que requiere de una colección que ya no es parte del SDK básico:

import ceylon.collection { HashSet }

void run() {
  value s = HashSet();
}

Ese código por sí mismo no va a compilar, por que el compilador te va a decir que no sabe de dónde viene HashSet ni conoce el paquete ceylon.collection, no lo tiene a la mano. Pero agregas entonces la definición de tu módulo; suponte que el código anterior viene en un archivo prueba.ceylon entonces en el mismo directorio metes module.ceylon con lo siguiente:

doc "Modulo de prueba"
by "Enrique Zamudio"
license 'GPL v3'
module prueba '0.1' {
  import ceylon.collection '0.3.2';
}

Con lo anterior, estás indicando un montón de cosas:

  • Tu módulo se llama prueba
  • Es la versión 0.1
  • Depende del módulo ceylon.collection, versión 0.3.2
  • Incluye metadatos como la descripción del módulo y sus autores, licencia, etc

Cuando compilas entonces estos dos archivos prueba.ceylon y module.ceylon, ahora el compilador ya sabe que debe buscar ese módulo externo; lo obtiene ya sea de tu cache local o lo baja del repositorio default (le puedes indicar repositorios al compilador en la línea de comando) y con eso ya compila tu código.

Como resultado de la compilación te queda un archivo prueba-0.1.car (car es de Ceylon ARchive), un prueba-0.1.src (con el código fuente, si es que quieres distribuirlo) y sus respectivas firmas SHA-1. El car incluye los datos de la dependencia con ceylon.collection, eso es importante más adelante. Lo interesante es dónde quedan todos estos archivos... si no le dices nada al compilador, por default te lo pone dentro de un directorio modules, pero si le indicaste en la línea de comando un repositorio de salida, lo pone ahí; lo más interesante es que dicho repositorio de salida puede ser un URL a tu repo privado, y si le indicas además usuario y password, entonces con un simple comando compilaste tu código, que descargó un módulo externo para poder compilar, creaste tu módulo, y lo pusiste en un repositorio.

Si luego creas otro proyecto y requieres usar tu módulo prueba, cuando compiles dicho código se descargará prueba pero como ahí viene indicado que requiere ceylon.collection pues también se va a descargar ese módulo. Pero eso no es todo; si le pasas a alguien tu módulo de prueba y simplemente lo ejecuta (con el comando

ceylon</code), al ejecutarlo si no se tiene disponible ceylon.collection se descargará del repo global (o si indicaste repos privados pues se busca ahí también) para poder ejecutarlo. Es decir, la dependencia se resuelve tanto en tiempo de compilación como en tiempo de ejecución. Eso facilita mucho la distribución de software porque cada módulo trae la info de los módulos que requiere.

Aún hay algunos detalles que faltan de definir por completo pero esta es una característica muy interesante de Ceylon, ya que vas a tener algo que hoy día no existe en Java (esto se supone que es básicamente lo que ofrece Jigsaw pero pues ya lo quitaron de Java 8). Y es algo que yo creo que nos va a permitir prescindir de la arquitectura de contenedores y todo eso, porque la realidad es que actualmente gran parte de la razón por la que existen los contenedores es para manejar todas esas dependencias en tiempo de ejecución.

Pues muy buena explicación

Muchas gracias por compartir.

Ciertamente eso de la modularización es uno de los grandes defectos de Java y que ha tenido que ser atendido de manera externa (ya sea dentro de la misma plataforma - caso OSGi - o de plano extendiéndola hasta salirse - caso Scala-).

Seguiré echándole un ojo a Ceylon para determinar como se integraría en el futuro como plataforma de aplicaciones empresariales.

Saludos cordiales

J. Reynaga

Imagen de ezamudio

Scala?

Scala hace algo respecto a la modularidad? no sabía... entonces por qué no la usan para su mismo SDK?

Imagen de bferro

arquitectura de contenedores?

¿qué tiene que ver la arquitectura de contenedores con la modularidad?¿Por qué dices Enrique que la razón por la que existen los contenedores es para manejar todas esas dependencias en tiempo de ejecución?
Quizá este pensando yo en algo diferente del término contenedor y por eso me entra esa duda.

Imagen de bferro

Otra duda

Dices que: "Lo interesante es que se vuelve parte del proyecto, no es algo externo que dependa puramente de archivos de configuración."
¿No es un archivo de configuración lo que escribes?

doc "Modulo de prueba"
by "Enrique Zamudio"
license 'GPL v3'
module prueba '0.1' {
  import ceylon.collection '0.3.2';
}

Modularidad en Scala

Hola.

Yo tampoco sabía que Scala soportara modularidad (al estilo OSGi) :-p

Me refiero a que en Scala de plano se salieron por la tangente y usan traits y dynamic linking para lograr el objetivo. No sé si eso sea bueno o sea malo comparado con cosas como Jigsaw u OSGi (creo que es inferior pero no tengo el conocimiento para concluir algo).

Por lo demás será interesante ver que tanta aceptación tiene Ceylon entre la comunidad de desarrolladores.

Creo que el reto (como sucede con cualquier lenguaje) es que tenga la capacidad de expresar poderosas abstracciones de una manera simple de entender y que quien lo use realmente le encuentre el valor de usarlo en relación a lo que usa actualmente.

Saludos

Imagen de ezamudio

contenedores

Contenedores: desde los muy simples de servlets (tipo jetty) hasta los más sofisticados de JEE (tipo weblogic). Sé perfectamente que también tienen muchas otras monerías, pero no se puede negar que mucho de lo que ofrecen se debe a que incluyen un montón de bibliotecas disponibles para que las apps contenidas ahí las puedan usar.

Que si una app necesita abc-1.0.jar y otra necesita abc-2.0.jar entonces cada quien que la tenga dentro de su war/ear pero si ambas usan xyz-1.0.jar y esa viene dentro del contenedor pues ya no necesitan incluirla, etc.

En cuanto a la definición del módulo: en Java por ejemplo se tiene la estructura de paquetes, y es muy engorroso y redundante que si ya se tiene una estructura a/b/c dentro del directorio de fuentes, en cada clase dentro del directorio c haya que indicar package a.b.c;. En Ceylon los archivos no llevan eso; simplemente hay un package.ceylon que dice shared packaged a.b.c; (shared solamente si es un paquete público; si es interno al módulo pues no lleva shared).

Pero hasta ahí llega Java. En Ceylon tenemos además el archivo module.ceylon con la descripción del módulo, que indica su nombre, versión, y qué otros módulos se requieren (por ahora es tanto para compilar como para tiempo de ejecución). El compilador lee ese archivo y utiliza el resolucionador de módulos para obtener los módulos requeridos si es que no se tienen disponibles ya; de ese modo no hay que estar agregando cosas al classpath manualmente, como en Java. A eso me refiero con que no es algo externo; en Java para compilar esto es un verdadero problema:

import org.apache.commons.dbcp.BasicDataSource;

public class MiClase {
  private final BasicDataSource pool;
}

Hay que tener a la mano commons-dbcp.jar pero pues es mi bronca obtenerlo, tengo que bajarlo de algún lado y tenerlo a la mano, tengo que indicarle a javac que necesita ese jar para compilar mi clase. Ese es un problema común para novatos en Java, tanto así que seguido vemos preguntas de tipo "no compila este código" o "no corre mi aplicación" y es un por class not found. Porque para correrlo también le tengo que indicar a Java que necesita ese jar, agregándolo al classpath. Es algo externo a la aplicación que quiero correr, o al código que quiero compilar. Ah y ni hablar de poner mi clase compilada en un jar; para eso hay otro programa separado que también es un rollo utilizar para crear mi jar.

Para resolver eso, han nacido cosas como Ivy y Maven, que son temas aparte. La cosa es que no hay algo que sea parte de Java para solucionar esto.

En Ceylon todo eso es parte del proceso de compilación: el manejo de las dependencias, el empaquetamiento de los artefactos resultantes de la compilación, etc. Pero no es un problema cuya solución se deja totalmente en manos de quien compila el código, porque quien hizo el código también indica cómo se llama su módulo y de qué otros módulos depende.

En resumen: sí, module.ceylon es un archivo de configuración, pero va incluido dentro de los fuentes, como parte integral del módulo que se va a compilar. En Java ni siquiera existe en realidad el concepto de módulo; javac se limita a generar archivos .class y luego hay otra herramienta separada que los empaqueta como se le indique; la manera de hacerlo queda totalmente en manos de alguien más.

Imagen de bferro

Los contenedores no incluyen bibliotecas

Los contenedores no incluyen bibliotecas. Las bibliotecas que usan son parte del SDK de la plataforma en que se basan, y los servidores de aplicaciones que entre otras cosas tienen varios contenedores, te dan la facilidad que no tengas que ocuparte de incluir esas bibliotecas como parte del proyecto, porque una vez que dices que ese será tu run time, ellos la incluyen.

Imagen de bferro

La manera de empaquetar siempre queda en manos de otro

Es muy buena la idea de que algunos archivos de configuración "queden en manos" del propio lenguaje en el que programas, y lo que comentas de Ceylon es interesante, pero la manera de empaquetar otros recursos que son parte de un proyecto y que son ajenos al lenguaje de programación, siempre queda en manos de otro.

Imagen de bferro

Desconozco las razones

Desconozco las razones por las cuales Java no ha incluido un sistema de módulos, aunque es algo que hace varios años se ha estado trabajando y hay un par de JSR´s que han tenido que ver con eso. Es un asunto que inclusive en el ambiente académico ha llamado la atención. Si les interesa "la parte académica" vale la pena leer la tesis doctoral de Rok Strnisa que aquí encuentran: http://rok.strnisa.com/phd/thesis.pdf.