Les meilleures pratiques dans la construction et le déploiement d'applications Clojure: bons tutoriels?

StackOverflow https://stackoverflow.com/questions/2391711

Question

Je suis nouveau à Clojure, et je commence à expérimenter avec la construction d'une application.

Jusqu'à présent, tout ce que je l'ai vu au sujet des tutoriels sur la compilation des programmes Clojure implique l'interactivité. Par exemple, « charger le REPL et le type (charge-fichier « ou ce qui ») à courir. Cela est bien, mais il ne suffit pas.

Je suis tellement habitué à la modifier décompiler-exécuter idiomes de langages comme C ou Delphi, que je suis instinctivement amené à apporter des modifications, puis cliquez sur « M-x la compilation ».

Le problème est que « lein uberjar », que je comprends est l'équivalent de « faire », est douloureusement lent à exécuter même pour un monde bonjour. Je vais donc devoir comprendre comment ce genre de choses « de développement interactif » fonctionne, cesser d'utiliser la uberjar comme il est rapide make, et enregistrez-seulement pour la fin de la journée.

Une autre chose que j'ai remarqué lors de la construction (à l'aide uberjar lein) est que la petite application GUI Je travaille sur Déroule cadres dans le processus de compilation, comme si elles sont exécuter lors de la compilation. Il semble un peu contre-intuitif pour moi; il est pas tout à fait analogue à « faire » comme je l'avais pensé.

Je sais que la façon de développer les choses Lisp travaille de manière interactive dans le REPL, et je ne suis pas en train de changer: je voudrais adapter à ce mode de vie. Malheureusement, je l'ai vu peu sous la forme de la documentation sur la façon de le faire. Par exemple, comment réinitialiser l'état actuel de la machine. Il semble juste un peu en désordre juste garder la compilation des extraits individuels à la volée sans être en mesure de faire une sorte de remise à zéro.

La plupart des tutoriels que j'ai vu sur Clojure (et Lisp) en général semblent se concentrer sur le piratage dans le REPL. Les meilleures pratiques sur le déploiement d'applications reste un mystère pour moi. Mes utilisateurs vont juste être des utilisateurs; ils ne vont pas être les développeurs qui vont charger les fichiers dans un REPL.

Alors, voici ma question: toutes les ressources pour une bonne information ou des tutoriels sur l'ensemble du processus de création d'une application Clojure, y compris le déploiement?

(Note: J'ai toutes les conditions préalables installés et de travail (par exemple Emacs, Slime, Leiningen, etc.), donc ce n'est pas une question à ce sujet)

.
Était-ce utile?

La solution

Quelques conseils rapides, puis quelques liens:

Ne pas utiliser lein uberjar au cours du développement; préfèrent lein jar. La différence est que lein uberjar met toutes vos dépendances dans le jar généré (y compris Clojure lui-même), de sorte que votre unique pot est un ensemble entièrement autonome avec votre application à l'intérieur; lein jar bocaux seulement votre propre code. L'approche uberjar a des avantages évidents pour le déploiement, mais pour le développement, vous devriez être en mesure d'utiliser simplement le classpath approprié lors de l'exécution de votre application, vous sauver le temps nécessaire pour préparer un uberjar. Si vous ne voulez pas la main pour gérer les classpath séries de tests, consultez le lein run plug-in .

En outre, très probablement la majorité de votre code ne doit pas être fait AOT compilé. AOT est nécessaire dans certains scénarios Java Interop, mais la plupart du temps on apporte une légère augmentation de la vitesse de démarrage et les problèmes gênants avec la compatibilité binaire avec les différentes versions de Clojure. Je suppose que cette dernière question ne concerne pas une application autonome uberjar-ed genre de projet, mais tout code de bibliothèque au moins doit être laissée à être JIT-ed si possible. Avec Leiningen, vous pouvez mettre une clause de :namespaces sous la forme de defproject en project.clj pour déterminer quels espaces de noms sont élaborées; tout ce que vous excluez sera en être JIT-ed par défaut. Les anciennes versions de Leiningen utilisées pour compiler tout par défaut, qui est en fait une bonne raison de passer!

En ce qui concerne les fenêtres exorbités lors de la compilation, je suppose que vous êtes soit code popping fenêtre en cours d'exécution au cours du temps d'expansion macro ou en dehors de toute définition de la fonction ou de construction similaire. (. Quelque chose comme un (println "Foo!") au niveau supérieur) C'est juste quelque chose que vous ne devriez pas faire, je suppose - à moins que vous prévoyez d'exécuter votre code comme un script, de toute façon. Pour éviter le problème, enveloppez code côté en effectuant des définitions de fonctions et de fournir un point d'entrée à votre application à l'aide de la clause :main dans project.clj. (Si vous dites :main foo, la fonction de -main de l'espace de noms foo sera utilisé comme point d'entrée à votre application qui est la valeur par défaut, de toute façon, et au moins le lein run mentionné ci-dessus semble avoir le nom hardcoded -. Pas sûr lein lui-même.)

En ce qui concerne la réinitialisation de l'état de la REPL - vous pouvez simplement le redémarrer. Avec BOUE, M-x boue-restart-inférieure-Lisp exactement ce que fera tout en maintenant tout autre état de votre session Emacs.

Voir aussi ces discussions sur le groupe Google Clojure:

  1. Clojure pour l'administration système
  2. Prepping clojure pour l'emballage (était: Re: Clojure pour l'administration du système)
  3. Leiningen, Clojure et bibliothèques: ce que je manque

Autres conseils

Non, vous ne saisissez pas de fonctions sur le REPL.

Vous modifiez vos fichiers source, comme d'habitude. L'avantage Lisp est que vous avez le système en cours d'exécution en arrière-plan en même temps, de sorte que vous pouvez compiler les différentes fonctions de votre fichier source et les mettre dans le système en cours d'exécution, ou même les remplacer là.

Si vous utilisez Slime, vous appuyez sur C-c C-c dans votre fichier source pour compiler et charger la fonction au point. Vous pouvez ensuite passer à l'REPL pour tester et explorer, mais tout ce que vous voulez persister en tant que source, vous mettez dans vos fichiers source.

Tutoriels commencent généralement en tapant les choses sur le REPL, parce qu'il n'y a pas grand-chose que vous devez mettre en place pour cela, mais le développement sérieux intègre le système de fonctionnement et la gestion fichier source.


Pour illustrer, mon flux de travail habituelle (j'utilise Common Lisp, mais Clojure est similaire) est comme ceci:

  • Démarrer Emacs
  • M-x slime pour commencer Slime, le système Lisp et connecter les deux via Swank
  • , (commande) load-system foo pour charger le projet en cours (compilation seulement si nécessaire) dans l'image
  • commutateur C-x b à un tampon de source
  • C-c ~ rendre le répertoire source du répertoire courant et le paquet source du package actuel du REPL

Maintenant, je suis mis en place avec mon système en cours d'exécution en arrière-plan. Travail est alors:

  • changer ou ajouter une définition de fonction ou de classe
  • C-c C-c pour compiler et charger dans l'image
  • sur REPL, test
  • debug

Il n'y a pas de pauses de compilation importantes, parce que je ne compilez jamais la chose à la fois, à des définitions individuelles.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top