Réécriture de Java vers Clojure

97

Mon entreprise vient de me demander de réécrire une application Java de grande taille (50 000 lignes de code) (une application Web utilisant JSP et servlets) dans Clojure. Quelqu'un d'autre a-t-il des conseils sur ce à quoi je dois faire attention?

Veuillez garder à l'esprit que je connais assez bien Java ET Clojure.

Mettre à jour

J'ai fait la réécriture et elle est entrée en production. C'est assez étrange car la réécriture a fini par aller si vite qu'elle a été faite en environ 6 semaines. Parce que beaucoup de fonctionnalités n'étaient pas encore nécessaires, cela ressemblait plus à 3000 lignes de Clojure.

J'entends qu'ils sont satisfaits du système et qu'il fait exactement ce qu'ils voulaient. Le seul inconvénient est que le gars qui entretient le système a dû apprendre Clojure à partir de zéro, et il a été entraîné à coups de pied et de cris. J'ai reçu un appel de lui l'autre jour en disant qu'il aimait Lisp maintenant ... drôle :)

Aussi, je devrais mentionner Vaadin. Utiliser Vaadin représentait probablement autant de gain de temps et de brièveté du code que Clojure. Vaadin est toujours le meilleur framework Web que j'ai jamais utilisé, même si maintenant j'apprends ClojureScript dans la colère! (Notez que Vaadin et ClojureScript utilisent tous deux les frameworks d'interface graphique de Google sous le capot.)

appshare.co
la source
55
Je veux travailler pour votre entreprise.
mtyaka
4
Eh bien, certaines entreprises de défense en Europe ont commencé à utiliser Clojure (j'ai entendu dire). Mais
je
1
@Zubair: 50 000 LOC Java sont loin d'être "largish". C'est un tout petit projet. J'ai un projet Java 250KLOC à 300KLOC ici et il est de taille moyenne ... Au mieux.
SyntaxeT3rr0r
5
En fait, j'ai peut-être commis une erreur en mentionnant la taille de la base de code car pour être juste, une réduction de la taille du code n'est pas le but de la réécriture. L'objectif est double: 1) rendre la base de code plus compréhensible et donc moins chère à maintenir le code 2) Permettre aux utilisateurs de l'outil d'étendre le produit à l'aide d'un éditeur Clojure dans le navigateur Web (en utilisant eval et d'autres avantages dynamiques de Clojure qui sont plus coûteux à faire en Java)
appshare.co
1
Hé ... je viens de voir cette question plus ancienne et je me demande comment se passe la réécriture?
levand

Réponses:

82

Le plus gros "problème de traduction" sera probablement de passer d'une méthodologie Java / POO à un paradigme de programmation Clojure / fonctionnel.

En particulier, au lieu d'avoir un état mutable dans les objets, la "méthode Clojure" consiste à séparer clairement l'état mutable et à développer des fonctions pures (sans effet secondaire). Vous savez probablement déjà tout cela :-)

Quoi qu'il en soit, cette philosophie a tendance à conduire vers un style de développement «ascendant» où vous concentrez les efforts initiaux sur la construction du bon ensemble d'outils pour résoudre votre problème, puis les branchez ensemble à la fin. Cela pourrait ressembler à quelque chose comme ça

  1. Identifiez les structures de données clés et transformez-les en définitions immuables de carte ou d'enregistrement Clojure. N'ayez pas peur d'imbriquer de nombreuses cartes immuables - elles sont très efficaces grâce aux structures de données persistantes de Clojure. Cela vaut la peine de regarder cette vidéo pour en savoir plus.

  2. Développez de petites bibliothèques de fonctions pures orientées vers la logique métier qui opèrent sur ces structures immuables (par exemple «ajouter un article au panier»). Vous n'avez pas besoin de faire tout cela en même temps car il est facile d'en ajouter plus tard, mais cela aide à en faire quelques-uns tôt pour faciliter les tests et prouver que vos structures de données fonctionnent ... point que vous pouvez réellement commencer à écrire des éléments utiles de manière interactive à la REPL

  3. Développez séparément des routines d'accès aux données qui peuvent conserver ces structures vers / depuis la base de données ou le réseau ou le code Java hérité selon les besoins. La raison de garder cela très distinct est que vous ne voulez pas que la logique de persistance soit liée à vos fonctions de «logique métier». Vous voudrez peut-être consulter ClojureQL pour cela, bien qu'il soit également assez facile d'encapsuler tout code de persistance Java que vous aimez.

  4. Écrivez des tests unitaires (par exemple avec clojure.test ) qui couvrent tout ce qui précède. Ceci est particulièrement important dans un langage dynamique comme Clojure car a) vous n'avez pas autant de filet de sécurité contre la vérification de type statique et b) cela aide à être sûr que vos constructions de niveau inférieur fonctionnent bien avant de trop construire sur en haut d'eux

  5. Décidez de la manière dont vous souhaitez utiliser les types de référence de Clojure (vars, refs, agents et atomes) pour gérer l'état de chaque partie mutable au niveau de l'application. Ils fonctionnent tous de la même manière mais ont une sémantique transactionnelle / simultanée différente en fonction de ce que vous essayez de faire. Les références seront probablement votre choix par défaut - elles vous permettent d'implémenter un comportement transactionnel STM "normal" en enveloppant n'importe quel code dans un bloc (dosync ...).

  6. Sélectionnez le bon framework web global - Clojure en a déjà quelques-uns, mais je recommande fortement Ring - regardez cette excellente vidéo " One Ring To Bind Them " plus Fleet ou Enlive ou Hiccup en fonction de votre philosophie de création de modèles. Ensuite, utilisez ceci pour écrire votre couche de présentation (avec des fonctions telles que "traduire ce panier en un fragment HTML approprié")

  7. Enfin, écrivez votre application en utilisant les outils ci-dessus. Si vous avez correctement suivi les étapes ci-dessus, ce sera en fait la solution la plus simple, car vous serez en mesure de créer l'ensemble de l'application par une composition appropriée des différents composants avec très peu de passe-partout.

C'est à peu près la séquence dans laquelle j'attaquerais le problème car il représente globalement l'ordre des dépendances dans votre code et convient donc à un effort de développement "ascendant". Bien sûr, dans un bon style agile / itératif, vous vous retrouverez probablement à pousser tôt vers un produit final démontrable, puis à revenir assez fréquemment aux étapes précédentes pour étendre la fonctionnalité ou le refactoriser au besoin.

ps Si vous suivez l'approche ci-dessus, je serais fasciné d'entendre combien de lignes de Clojure il faut pour correspondre à la fonctionnalité de 50000 lignes de Java

Mise à jour : depuis la rédaction de cet article, quelques outils / bibliothèques supplémentaires sont apparus dans la catégorie "à vérifier":

  • Noir - cadre Web qui s'appuie sur Ring.
  • Korma - un très bon DSL pour accéder aux bases de données SQL.
Mikera
la source
4
Nitpick re: "Décidez lequel des types de référence STM de Clojure que vous souhaitez utiliser pour gérer chaque état au niveau de l'application modifiable de partie": Il n'y a qu'un seul type de référence STM. Les autres IRef n'impliquent pas la STM. Sinon, cela ressemble à un conseil solide.
hmmm ... Je suppose que je compte les références, les agents et les atomes comme faisant tous partie du système Clojure STM / concurrence. Par exemple, ils prennent tous en charge les validateurs et les agents sont coordonnés avec les validations de transactions. mais je comprends votre point, les refs sont le modèle transactionnel «primaire». fera un amendement rapide.
mikera
2
Si seulement je pouvais donner plus de +1. J'ai regardé les deux vidéos auxquelles vous avez fait référence, et elles étaient super. Merci.
jdl
1
Maintenant, le noir est obsolète. Je suppose que vous devez parler de compojure au lieu de noir.
hsestupin le
Le lien One Ring To Lind Them est rompu!
Adam Arold
5

Quels aspects de Java votre projet actuel inclut-il? Journalisation, transactions de base de données, transactions déclaratives / EJB, couche Web (vous avez mentionné JSP, servlets) etc. J'ai remarqué que l'éco-système Clojure a divers micro-frameworks et bibliothèques dans le but de faire une tâche et de bien le faire. Je suggérerais d'évaluer les bibliothèques en fonction de vos besoins (et si cela pourrait être mis à l'échelle dans de grands projets) et de prendre une décision éclairée. (Clause de non-responsabilité: je suis l'auteur de bitumenframework ) Une autre chose à noter est le processus de construction - si vous avez besoin d'une configuration complexe (développement, test, mise en scène, production), vous devrez peut-être diviser le projet en modules et avoir le processus de construction scripté pour facilité.

Shantanu Kumar
la source
Servlets, JSP, framework de persistance construit à la maison (10 ans) et pojos, mais pas d'EJB
appshare.co
4
Les servlets peuvent être facilement remplacés par Ring + Compojure IMHO, et les JSP peuvent être remplacés par des modèles StringTemplate (ou FreeMarker / Velocity.) La persistance dans Clojure sera différente de Java. Si vous avez besoin d'un mappage relationnel, vous pouvez regarder Clj-Record et SQLRat (pas encore très mûrs). ClojureQL prend en charge uniquement MySQL et PostgreSQL pour le moment AFAICT. La limitation actuelle de ccsql pour interdire les traits de soulignement dans les noms de colonnes peut surprendre. Je pense que discuter des aspects de développement de la liste Clojure au fur et à mesure des besoins sera utile. Bonne chance pour le projet!
Shantanu Kumar
Depuis ce projet, j'ai fait une autre application avec Clojure et Clojurescript (nemcv.com) et j'utilise Ring maintenant, j'ai essayé ClojureQL, mais je suis passé à Korma pour accéder à la base de données. Vous pouvez voir les derniers travaux sur github.com/zubairq/coils
appshare.co
4

J'ai trouvé que la partie la plus difficile était de penser à la base de données. Faites quelques tests pour trouver les bons outils que vous souhaitez utiliser.

LenW
la source
1
Eh bien, j'ai essayé clojureql pour l'accès aux données, mais il est totalement différent du style Java d'accès à la base de données qui est entièrement basé sur des objets. Juste par intérêt, quel accès à la base de données avez-vous utilisé pour Java et qu'avez-vous utilisé avec Clojure?
appshare.co
1
Nous avons fini par repenser beaucoup de choses et aller avec mongodb car la persistance des sturctures de données clojure était très naturelle
LenW