Question

Dites que je voulais factoriser un code commun entre mon côté client * .cljs et mon côté serveur * .clj, par exemple différents, je peux faire des structures de données et opérations courantes? Est-il logique de le faire?

Était-ce utile?

La solution

Mise à jour: à partir de clojure 1.7, consultez Clojure conditionals lecteur ou cljc. Je l'ai utilisé cljc avec succès pour partager beaucoup de code entre le serveur et le navigateur très facilement.

Bonne question! J'ai pensé beaucoup à ce sujet aussi bien ces derniers temps et ai écrit quelques applications à l'expérience.

Voici ma liste des types de choses que vous pouvez partager et avantages / inconvénients de chacun:

  • La plupart de mes fichiers cljs client contient du code qui manipule le Royaume. Ainsi, il ne serait pas logique de partager tout cela avec le serveur
  • La plupart des choses du côté serveur traite les appels de systèmes de fichiers et base de données. Je suppose que vous pouvez appeler la base de données du client (surtout si vous utilisez l'un des que les appels javascript soutien de la db no-SQL). Mais, même alors, je me sens comme vous devez choisir de db appel du client ou un appel db à partir du serveur et, par conséquent, il ne fait pas beaucoup de sens pour partager le code db soit.
  • Un domaine où le partage est sans aucun doute utile est d'être en mesure de partager et transmettre des structures de données de Clojure (combinaisons imbriquées des listes, des vecteurs, des jeux, etc.) entre le client et le serveur. Pas besoin de se convertir à JSON (ou xml) et le dos. Par exemple, être en mesure de transmettre des représentations hoquet style du dos dom-et-vient est très pratique. En GWT, je l'ai utilisé pour les modèles de gilead partager entre le client et le serveur. Mais, en Clojure, vous pouvez tout simplement passer des structures de données autour, donc il n'y a vraiment pas besoin de partager des définitions de classe comme dans GWT.
  • Un domaine que je sens que je besoin d'expérimenter plus est partage d'état entre le client et le serveur. Dans mon esprit, il y a quelques stratégies: l'état du magasin sur le client (applications de type ajax seule page) ou de l'état de stockage sur le serveur (comme les applications de legacy) ou un combo des deux. Peut-être le code responsable de l'état de mise à jour (les atomes, refs, agents ou autre) pourraient être partagées et l'état pourrait être passé en arrière sur demande et la réponse à maintenir les deux niveaux en phase? Jusqu'à présent, écrivant serveur en utilisant REST meilleures pratiques et ayant l'état stocké sur le client semble fonctionner assez bien. Mais je pouvais voir comment il pourrait y avoir des avantages à partager l'état entre le client et le serveur.
  • Je n'ai pas besoin de Constantes d'actions et / ou encore des propriétés, mais cela pourrait être quelque chose qui serait bon de les réutiliser. Si vous mettez toutes vos constantes globales de app dans un fichier CLJ puis écrit un script pour le copier sur cljs chaque fois que vous le compilez clojurescript, qui devrait fonctionner correctement, et pourrait sauver un peu de duplication de code.

En espérant que ces pensées sont utiles, je suis très intéressé par ce que les autres ont trouvé à ce jour!

Autres conseils

J'ai écrit cljx Leiningen plug-in spécifique pour gérer le partage de code Clojure / ClojureScript pour une bibliothèque de visualisation de données Clojure . 95% du code non-hôte Interop regarde la même chose, et cljx vous permet de réécrire automatiquement cette dernière 5% en spécifiant les règles de réécriture en utilisant core.logic. La plupart du temps, cependant, il est des substitutions simples de symboles; clojure.lang.IFn dans Clojure est juste IFn dans ClojureScript, par exemple.

Vous pouvez également utiliser des métadonnées à des formes annoter à inclure ou à exclure lorsque le code est généré pour une plate-forme spécifique.

Le nouveau lein-cljsbuild plugin Leiningen a intégré support pour le partage pur code Clojure

A écrit un peu rapide de code pour copier un sous-ensemble de mon code clojure serveur vers mon code clojurescript, renommer comme .cljs avant de construire:

(ns clj-cljs.build
  (use
    [clojure.java.io]
  )
  (require
    [cljs.closure :as cljsc]
  )
)

(defn list-files [path]
 (.listFiles (as-file path))
)

(defn copy-file* [from to]
 ;(println " coping " from " to " to)
 (make-parents to)
 (copy from to)
)    

(defn rename [to-path common-path f]
 (str to-path common-path (.replaceAll (.getName f) ".clj" ".cljs"))
)

(defn clj-cljs* [files common-path to-path]
  (doseq [i (filter #(.endsWith (.getName %) ".clj") files)]
    (copy-file* i (file (rename to-path common-path i)))
  )
  (doseq [i (filter #(.isDirectory %) files)]
    (clj-cljs* (list-files i) (str common-path (.getName i) "/") to-path)
  )
)

(defn build [{:keys [common-path clj-path cljs-path js-path module-name]}]
  (clj-cljs* (list-files (str clj-path common-path)) common-path cljs-path)
  (cljsc/build
    cljs-path
    {
     :output-dir js-path
     :output-to (str js-path module-name ".js")
    }
  )
)

(defn build-default []
  (build
   {
    :clj-path "/home/user/projects/example/code/src/main/clojure/"
    :cljs-path "/home/user/projects/example/code/src/main/cljs/"
    :js-path "/home/user/projects/example/code/public/js/cljs/"
    :common-path "example/common/" ; the root of your common server-client code
    :module-name "example"
   }
  )
)

Cette question est antérieure à cljc, mais depuis que je suis tombé sur elle, je pensais que je voudrais mentionner Clojure lecteur conditionals .

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