2010-03-06 13 views
46

Soy nuevo en Clojure, y estoy empezando a experimentar con la construcción de una aplicación.Mejores prácticas en la construcción e implementación de aplicaciones Clojure: buenos tutoriales?

Hasta ahora, todo lo que he visto sobre los tutoriales sobre la compilación de programas Clojure implica interactividad. Por ejemplo, "cargue el REPL y escriba (archivo de carga" this-or-that ") para ejecutar. Esto está bien, pero no es suficiente.

Estoy tan acostumbrado a los modismos edit-compile-run de idiomas como C o Delphi, que instintivamente estoy obligado a hacer ediciones, luego presiono "Mx compilar".

El problema es que "lein uberjar", que entiendo es el equivalente a "hacer", es dolorosamente lento para ejecutar incluso para un mundo hello. Así que tendré que descubrir cómo funciona este "desarrollo interactivo", dejar de usar el uberjar como si fuera una marca rápida y guardarlo solo para el final del día.

Otra cosa que noté durante la construcción (usando lein uberjar) es que la s aplicación de interfaz gráfica de usuario comercial Estoy trabajando en marcos emergentes en el proceso de compilación, como si fueran ejecutando mientras compila. Simplemente parece un poco contradictorio para mí; no es tan análogo a "hacer" como yo había pensado.

Sé que la manera Lisp de desarrollar cosas está trabajando de manera interactiva en el REPL, y no estoy tratando de cambiar eso: me gustaría adaptarme a esta forma de vida. Lamentablemente, he visto poco en forma de documentación sobre cómo hacerlo. Por ejemplo, cómo restablecer el estado actual de la máquina. Simplemente parece un poco complicado seguir compilando fragmentos individuales sobre la marcha sin poder hacer algún tipo de reinicio.

La mayoría de los tutoriales que he visto en Clojure (y Lisp) en general parecen centrarse en piratear el REPL. Las mejores prácticas en el despliegue de aplicaciones siguen siendo un misterio para mí. Mis usuarios solo serán usuarios; no van a ser desarrolladores que van a cargar archivos en un REPL.

Así que aquí está mi pregunta: ¿algún recurso para obtener buena información o tutoriales sobre todo el proceso de creación de una aplicación Clojure, incluida la implementación?

(Nota: Tengo todos los requisitos previos instalados y en funcionamiento (por ejemplo, Emacs, Slime, Leiningen, etc.), así que no se trata de eso).

Respuesta

25

Un par de consejos rápidos, a continuación, algunos enlaces:

no uso lein uberjar durante el desarrollo; Prefiero lein jar. La diferencia es que lein uberjar pone todas sus dependencias en el jar generado (incluido Clojure sí mismo), de modo que su tarro individual es un paquete totalmente independiente con su aplicación dentro; lein jar solo crea tu propio código. El enfoque uberjar tiene beneficios obvios para la implementación, pero para el desarrollo, debería poder utilizar la ruta de clases apropiada al ejecutar su aplicación, ahorrándose el tiempo necesario para preparar un uberjar. Si no desea administrar manualmente el classpath para ejecuciones de prueba, consulte el lein run plugin.

Además, lo más probable es que la mayoría de su código no se compile realmente. AOT es necesario en algunos escenarios de interoperabilidad de Java, pero la mayoría de las veces trae un pequeño aumento en la velocidad de inicio y problemas molestos con la compatibilidad binaria con diferentes lanzamientos de Clojure. Supongo que este último problema no es relevante para un tipo de proyecto de aplicación independiente uberjar -ed, pero cualquier código de biblioteca, al menos, debería dejarse para ser JIT-ed, si es posible.Con Leiningen, puede poner una cláusula :namespaces en el formulario defproject en project.clj para determinar qué espacios de nombres se deben compilar; lo que sea que dejes afuera estará actualmente JIT-ed por defecto. Las versiones anteriores de Leiningen solían compilar todo de manera predeterminada, ¡lo que en realidad es una buena razón para actualizar!

En cuanto a las ventanas que aparecen durante la compilación, supongo que está ejecutando código de ventana emergente durante el tiempo de expansión de macro o fuera de cualquier definición de función o construcción similar. (Algo así como un (println "Foo!") en el nivel superior.) Eso es algo que no deberías hacer, supongo, a menos que planees ejecutar tu código como un script, de todos modos. Para evitar el problema, ajuste el código de efecto secundario en las definiciones de función y proporcione un punto de entrada a su aplicación utilizando la cláusula :main en project.clj. (Si dices :main foo, entonces la función -main del espacio de nombres foo se usará como punto de entrada a tu aplicación. De todos modos, esa es la predeterminada, y al menos el lein run mencionado anteriormente parece tener el nombre codificado, no estoy seguro de que sea en sí.)

En cuanto a restablecer el estado de REPL, puede simplemente reiniciarlo. Con SLIME, M-x slime-restart-inferior-lisp hará exactamente eso mientras mantiene todo el otro estado de su sesión de Emacs.

Véase también estas discusiones en el grupo Clojure Google:

  1. Clojure for system administration
  2. Prepping clojure for packaging (was: Re: Clojure for system administration)
  3. Leiningen, Clojure and libraries: what am I missing?
+0

¡Gracias por la información y los enlaces! El plugin lein run parece que me va a ayudar. Por supuesto, esto lleva a otra pregunta: http://stackoverflow.com/questions/2393705/how-to-install-a-leiningen-plugin – kes

+0

¡De nada! Solo respondí la nueva pregunta también. :-) –

13

No, no entre las funciones en el REPL.

Edite los archivos fuente, como siempre. La ventaja de Lisp es que tiene el sistema ejecutándose en segundo plano al mismo tiempo, por lo que puede compilar funciones individuales desde su archivo de origen y ponerlas en el sistema en ejecución, o incluso reemplazarlas allí.

Si usa Slime, presiona C-c C-c en el archivo fuente para compilar y cargar la función en el punto. Luego puede cambiar a REPL para probar y explorar, pero cualquier cosa que quiera persistir como fuente, la pondrá en sus archivos fuente.

Los tutoriales generalmente comienzan escribiendo cosas en el REPL, porque no hay mucho que tenga que configurar para esto, pero el desarrollo serio integra el sistema en ejecución y la gestión de archivos fuente.


Sólo para ilustrar, mi flujo de trabajo habitual (estoy usando Common Lisp, pero Clojure es similar) es la siguiente:

  • inicio Emacs
  • M-x slime para comenzar limo, el sistema Lisp, y conectar los dos a través de Swank
  • , (comandos) load-systemfoo para cargar el proyecto actual (compilar sólo si es necesario) en la imagen
  • C-x b cambio a un búfer de origen
  • C-c ~ hacer que el directorio de origen del directorio actual y el paquete fuente del paquete actual de la REPL

Ahora, que sea puesto al día con mi sistema funcionando en el fondo. Trabajo es entonces:

  • cambiar o añadir una definición de función o tipo
  • C-c C-c para compilar y cargarlo en la imagen del switch
  • a REPL, prueba
  • depuración

Hay no hay pausas de compilación significativas, porque nunca compilo todo de una vez, solo definiciones individuales.

+2

También hay 'C-c C-z' para cambiar al búfer REPL desde cualquier búfer fuente Lisp. En general, es una prioridad para aprender a aprovechar adecuadamente SLIME y Paredit, y luego hay una cantidad de cosas algo menos importantes, pero todavía * extremadamente * útiles, p. ido-mode (o algo para lograr un propósito similar - posiblemente carámbanos o cualquier cosa.el). (Gracias por la edición, ¡por cierto!) –

+0

Configuré el selector de baba en 'C-c s', lo que da más opciones de cambio de búfer. – Svante

Cuestiones relacionadas