================== Paquetes y módulos ================== Esta es la décima entrega de el tour de Ceylon. Si en la parte anterior sobre los tipos genéricos te sentiste un poco abrumado, no te preocupes; esta parte cubrirá algo de material que deberá ser mas fácil llevar acabo. Vamos a poner atención en tema muy distinto. Aprenderemos acerca de paquetes y módulos. ------------------------ Paquetes e importaciones ------------------------ No existe una declaración ``packages`` en los archivos fuente de Ceylon. El compilador determina el paquete y el módulo en el que un programa permanecerá mediante la ubicación de archivo fuente en que es declarado. Una clase llamada ``Hello`` en el paquete ``org.jboss.hello`` deberá ser definida en el archivo ``org/jboss/hello/Hello.Ceylon``. Cuando un archivo fuente en un paquete refiere a elemento de un programa ``toplevel`` en otro paquete, deberá explícitamente importar el elemento del programa. Ceylon, a diferencia de Java, no soporta el uso de nombres calificativos dentro del código fuente. Así es que no podemos escribir ``org.jboss.hello.Hello`` en Ceylon. La sintaxis de la declaración ``import`` es un poco diferente a la de Java. Para importar un elemento de un programa, escribimos: .. code-block:: ceylon import com.redhat.polar.core { Polar } Para importar varios elementos de un programa de un paquete, escribimos: .. code-block:: ceylon import com.redhat.polar.core { Polar, pi } Para importar todos los elementos de un programa ``toplevel`` en un paquete, escribimos: .. code-block:: ceylon import com.redhat.polar.core { ... } Para resolver un conflicto de nombres, podemos renombrar una declaración importada: .. code-block:: ceylon import com.redhat.polar.core { PolarCoord=Polar } Pensamos que renombrar es mucho mas limpio que usar nombres calificativos, podemos incluso renombrar miembros de un tipo: .. code-block:: ceylon import com.redhat.polar.core { Polar { r=radius, theta=angle } } ------- Módulos ------- El soporte integrado para modularidad es uno de los mayores logros del proyecto Ceylon, pero ¿Qué significa modularidad? Hay varias definiciones para esto: - Soporte para una unidad de visibilidad que es mas grande que un paquete, pero mas pequeño que todos los paquetes. - Un formato descriptor de un módulo que expresa dependencias entre versiones especificas de módulos. - Un integrado formato de módulo y un repositorio de módulos disponible que es entendido por todas las herramientas escritas para el lenguaje, desde el compilador hasta el IDE. - Un ``runtime`` que cuenta con un cargador de clases (un cargador por módulo) y la habilidad para manejar múltiples versiones de el mismo módulo. - Un ecosistema repositorios de módulos remotos donde desarrolladores pueden compartir sus códigos con otros desarrolladores. ################################# Nivel de visibilidad de un módulo ################################# Un paquete en Ceylon puede ser compartido o no compartido. Un módulo no compartido (Por defecto) es visible únicamente a el módulo que contiene el paquete. Podemos crear un paquete compartido proveiendo un descriptor del paquete. .. code-block:: ceylon "The typesafe query API." shared package org.hibernate.query; Un paquete ``shared`` define parte de la API ``public`` de el módulo. Así otros módulos pueden acceder a las declaraciones compartidas en un paquete ``shared``. En tiempo de ejecucuón el paquete es representado por un atributo ``Package`` ``top level`` llamado ``package``. #################### Descriptor de módulo #################### Un módulo deberá especificar explícitamente los módulos de los que depende. Esto es logrado a través de un descriptor de módulo. .. code-block:: ceylon "The best-ever ORM solution" license "http://www.gnu.org/licenses/lgpl.html" module org.hibernate '3.0.0.beta' { shared import ceylon.language '1.0.1'; import java.sql '4.0'; } En tiempo de ejecución un módulo es representado por un atributo ``Module`` ``top level`` llamado ``module``. ######################################## Archivos módulo y repositorio de módulos ######################################## Un paquete de archivos compilan a archivos ``.class``, los descriptores de paquetes y módulos en un estilo ``Java`` a un archivo ``jar`` con la extensión ``.car``. El compilador de Ceylon usualmente no produce archivos ``.class`` individuales en un directorio. En vez de ello, produce archivos módulo. Archivos módulo se encuentran en un repositorio de módulos. Un repositorio de módulos es una estructura de directorio bien definida con un bien definido lugar para cada módulo. Un repositorio de módulos puede ser local(en un sistema de archivos) o remoto (en internet). Dada una lista de repositorios de módulos, el compilador de Ceylon puede localizar las dependencias mencionada en el descriptor del módulo cuando se compila. Y cuando termina la compilación del módulo, el coloca al archivo del módulo resultante en un lugar correcto en el repositorio local. La arquitectura también incluye soporte para directorios fuente, archivos de código, directorios de documentación del módulo. ######################################### Desarrollando módulos en la IDE de Ceylon ######################################### Para empezar con los módulos en la ide de Ceylon, ve a ``Help > Cheat Sheets...``, abre el objeto ``Ceylon`` y corre el cheat sheet ``Introduction to Ceylon Modules``, que te guiara paso a paso a través del proceso de crear un módulo, definiendo sus dependencias y exportando su repositorio de módulos. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Ejemplo: Compilando a un repositorio local o remoto ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Supongamos que estas escribiendo ``net.example.foo``. Tu directorio de proyecto puede lucir como este: :: README source/ net/ example/ foo/ Foo.ceylon FooService.ceylon module.ceylon documentation/ manual.html Aquí el código fuente esta en un directorio llamado source (que es utilizado por defecto y nos salva de tener que pasarle la opción ``--src`` a ``ceylon compile``). Desde el directorio del proyecto(el directorio que contiene el directorio ``source``) tu puedes compilar usando el comando: .. code-block:: console $ ceylon compile net.example.foo Este comando deberá compilar los archivos de código fuente (Foo.ceylon y FooService.ceylon) en archivo módulo y publicarlos en el directorio de repositorios por defecto de salida, ``modules`` (puedes usar la opción ``--our build`` para publicarlos a ``build``). Ahora tu directorio de proyecto lucirá como esto: :: README source/ net/ example/ foo/ Foo.ceylon FooService.ceylon module.ceylon modules/ net/ example/ foo/ 1.0/ net.example.foo-1.0.car net.example.foo-1.0.car.sha1 net.example.foo-1.0.src net.example.foo-1.0.src.sha1 documentation/ manual.html El archivo ``.src`` es el archivo de código que puede ser usado por herramientas tales como el ``IDE``, para búsqueda de código. El archivo ``sha1`` contiene la suma de verificación del archivo sin la extensión ``sha1`` y puede ser usado para detectar archivos corruptos. Puedes generar la documentación del ``API`` usando ``ceylon doc``` como en el siguiente ejemplo: .. code-block:: console $ ceylon doc net.example.foo Esto deberá crear un modules/net/example/foo/1.0/module-doc directorio que contiene la documentación. Ahora vamos a suponer que tu proyecto obtiene una dependencia en ``com.example.bar`` versión 3.1.4. Tienes que declarar el módulo y la versión de la que depende en tu descriptor ``module.ceylon`` , no necesitaras decirle a ``ceylon compile`` en que repositorio buscar para encontrar la dependencia. Una posibilidad es que tu tengas un repositorio local llamado ``com.example.bar/3.1.4`` si este se encuentra en tu repositorio por defecto (``~/.ceylon/repo``) entonces no necesitas hacer nada, el mismo comando hará el trabajo: .. code-block:: console $ ceylon compile net.example.foo Alternativamente, si tienes otro repositorio local puede especificarlo usando la opción ``--rep``. El `Ceylon Herd`_ en un repositorio de módulos online que contiene módulos de Ceylon open source. Como suele pasar, el Herd es uno de los repositorios por defecto que conoce ``ceylon compile``. Asi si ``com.example.bar/3.1.4/`` esta en Herd entonces el comando a compilar deberá de permanecer agradablemente corto. .. code-block:: console $ ceylon compile net.example.foo (Esto es correcto, igual que como vimos anteriormente). Por cierto, puedes deshabilitar los repositorios por defecto con la opción ``--d`` si así lo deseas. Si ``com.example.bar/3.1.4`` se encuentra en otro repositorio, por decir algo en ``http://repo.example.com``, entonces el comando deberá ser: .. code-block:: console $ ceylon compile --rep \ http://repo.example.com \ net.example.foo Puedes especificar múltiples opciones ``--rep`` como sea necesario si tu tienes dependencias en múltiples repositorios. Cuando estés listo para publicar el módulo en algún lugar, para que cualquier otra persona pueda usarlo. Vamos a decir que lo quieres publicar en ``http://ceylon.example.net/repo``. Solo tienes que compilarlo otra vez, pero esta vez especificando la opción ``-out``. .. code-block:: console $ ceylon compile \ --rep http://repo.example.com \ --out http://ceylon.example.net/repo \ net.example.foo Es de valor señalar que tomando ventaja de las acertadas cosas como el directorio de código fuente y el directorio de salida, como el que hemos hecho aquí, te salvan de teclear mucho. -------------------- Ejecutando un módulo -------------------- La ejecución de un módulo de Ceylon es basado en módulos JBoss, una tecnología que también existe el core de JBoss AS 7. Dada una lista de repositorios de módulos, la ejecución automáticamente localiza un archivo módulo y sus dependencias versionada en los repositorios, incluso descargando archivos desde repositorios remotos si es necesario. Normalmente , la ejecución de Ceylon es invocada especificando el nombre de un módulo ejecutable en la linea de comandos. ################################################ Ejemplo: Corriendo un repositorio local o remoto ################################################ Vamos a continuar el ejemplo que teníamos donde ``net.example.foo`` versión 1.0 fue publicado to http://ceylon.example.net/repo. Ahora, supongamos que quieres correr el módulo(posiblemente desde otra computadora). Si la dependencias (com.example.bar/3.1.4) pueden ser encontrada en los repositorios por defecto el comando para ``ceylon run`` es: .. code-block:: console $ ceylon run \ --rep http://ceylon.example.net/repo \ net.example.foo/1.0 Puedes pasar opciones también (que son disponibles al programa a través del objeto top level ``process``): .. code-block:: console $ ceylon run \ --rep http://ceylon.example.net/repo \ net.example.foo/1.0 \ my options Si una de las dependencias no esta disponible desde los repositorios, deberás de especificar un repositorio que las contenga usando otro ``rep``: .. code-block:: console $ ceylon run \ --rep http://ceylon.example.net/repo \ --rep http://repo.example.com \ net.example.foo/1.0 \ my options El caso mas simple, es donde el módulo y sus dependencias están todos en uno (o mas) de los repositorios por defecto (tales como Herd o ``~/.ceylon.repo``). .. code-block:: console $ ceylon run net.example.foo/1.0 ##################################### Ecosistema del repositorio de módulos ##################################### Una de las ventajas mas agradables de esta arquitectura es que es posible corren un módulo "directamente desde internet", solo tecleando, por ejemplo: .. code-block:: console $ ceylon run --rep http://jboss.org/ceylon/modules org.jboss.ceylon.demo/1.0 Y todas las dependencias requeridas son automáticamente descargada como se necesiten. `Ceylon Herd`_ es una es una comunidad de repositorios de módulos donde cualquiera puede contribuir reusando módulos. Por supuesto, el formato de repositorio de módulos es un standard abierto, así cualquier organización puede mantener su repositorio de módulos publico. ########### Aun hay mas ########### En la siguiente estación veremos el soporte de Ceylon para funciones de orden superior. .. _Ceylon Herd: http://modules.ceylon-lang.org/