Java zu Clojure umschreiben

97

Ich wurde gerade von meiner Firma gebeten, eine große Java-Anwendung (50.000 einzelne Codezeilen) (eine Web-App mit JSP und Servlets) in Clojure neu zu schreiben. Hat jemand andere Tipps, worauf ich achten sollte?

Bitte denken Sie daran, dass ich sowohl Java als auch Clojure recht gut kenne.

Aktualisieren

Ich habe das Rewrite gemacht und es ging in Produktion. Es ist ziemlich seltsam, da das Umschreiben so schnell ging, dass es in ungefähr 6 Wochen fertig war. Da noch nicht viele Funktionen benötigt wurden, wurden eher 3000 Zeilen Clojure verwendet.

Ich höre, dass sie mit dem System zufrieden sind und genau das tun, was sie wollten. Der einzige Nachteil ist, dass der Typ, der das System wartet, Clojure von Grund auf lernen musste, und er wurde mit Tritten und Schreien hineingezogen. Ich habe neulich einen Anruf von ihm bekommen, der besagt, dass er Lisp jetzt liebt .. lustig :)

Ich sollte auch Vaadin gut erwähnen. Die Verwendung von Vaadin hat wahrscheinlich genauso viel Zeit und Zeit gespart wie Clojure. Vaadin ist immer noch das beste Webframework, das ich jemals verwendet habe, obwohl ich jetzt ClojureScript im Zorn lerne! (Beachten Sie, dass sowohl Vaadin als auch ClojureScript die GUI-Frameworks von Google unter der Haube verwenden.)

appshare.co
quelle
55
Ich möchte für Ihr Unternehmen arbeiten.
Mtyaka
4
Nun, einige Verteidigungsunternehmen in Europa haben begonnen, Clojure zu verwenden (wie ich gehört habe). Aber
ich
1
@Zubair: 50 000 Java LOC ist nicht annähernd "groß". Dies ist ein sehr kleines Projekt. Ich habe hier ein 250KLOC bis 300KLOC Java-Projekt und es ist mittelgroß ... Bestenfalls.
SyntaxT3rr0r
5
Eigentlich habe ich vielleicht einen Fehler gemacht, indem ich die Größe der Codebasis erwähnt habe, um fair zu sein. Eine Reduzierung der Codegröße ist nicht das Ziel des Umschreibens. Das Ziel ist zweierlei: 1) Die Codebasis verständlicher und damit kostengünstiger zu pflegen. 2) Benutzern des Tools ermöglichen, das Produkt mithilfe eines Clojure-Editors im Webbrowser zu erweitern (unter Verwendung von eval und anderer dynamischer Clojure-Güte, die teurer ist tun in Java)
appshare.co
1
Hey ... habe gerade diese ältere Frage gesehen und mich gefragt, wie das Umschreiben läuft?
Levand

Antworten:

82

Das größte "Übersetzungsproblem" wird wahrscheinlich von einer Java / OOP-Methodik zu einem Clojure / funktionalen Programmierparadigma übergehen.

Anstatt einen veränderlichen Zustand innerhalb von Objekten zu haben, besteht der "Clojure-Weg" insbesondere darin, den veränderlichen Zustand klar zu trennen und reine (nebenwirkungsfreie) Funktionen zu entwickeln. Das alles weißt du wahrscheinlich schon :-)

Wie auch immer, diese Philosophie führt tendenziell zu einem "Bottom-up" -Entwicklungsstil, bei dem Sie die anfänglichen Bemühungen darauf konzentrieren, die richtigen Tools zur Lösung Ihres Problems zu entwickeln und diese schließlich am Ende zusammenzufügen. Das könnte ungefähr so ​​aussehen

  1. Identifizieren Sie wichtige Datenstrukturen und wandeln Sie sie in unveränderliche Clojure-Karten- oder Datensatzdefinitionen um. Haben Sie keine Angst, viele unveränderliche Karten zu verschachteln - sie sind dank der beständigen Datenstrukturen von Clojure sehr effizient. Sehen Sie sich dieses Video an, um mehr zu erfahren.

  2. Entwickeln Sie kleine Bibliotheken mit reinen, auf Geschäftslogik ausgerichteten Funktionen, die auf diesen unveränderlichen Strukturen basieren (z. B. "Artikel in den Warenkorb legen"). Sie müssen nicht alle auf einmal ausführen, da es später einfach ist, weitere hinzuzufügen. Es ist jedoch hilfreich, einige frühzeitig auszuführen, um das Testen zu erleichtern und zu beweisen, dass Ihre Datenstrukturen funktionieren An der REPL können Sie tatsächlich anfangen, nützliche Dinge interaktiv zu schreiben

  3. Entwickeln Sie separat Datenzugriffsroutinen, mit denen diese Strukturen nach Bedarf in / aus der Datenbank oder dem Netzwerk oder dem alten Java-Code beibehalten werden können. Der Grund, dies sehr getrennt zu halten, besteht darin, dass Sie keine Persistenzlogik mit Ihren "Geschäftslogik" -Funktionen verknüpfen möchten. Vielleicht möchten Sie sich dafür ClojureQL ansehen , obwohl es auch ziemlich einfach ist, jeden Java-Persistenzcode zu verpacken, den Sie mögen.

  4. Schreiben Sie Unit-Tests (z. B. mit clojure.test ), die alle oben genannten Punkte abdecken. Dies ist in einer dynamischen Sprache wie Clojure besonders wichtig, da a) Sie nicht so viel Sicherheitsnetz für die statische Typprüfung haben und b) es hilfreich ist, sicherzustellen, dass Ihre Konstrukte auf niedrigerer Ebene gut funktionieren, bevor Sie zu viel darauf aufbauen oben auf ihnen

  5. Entscheiden Sie, wie Sie die Referenztypen von Clojure (Vars, Refs, Agenten und Atome) verwenden möchten, um den Status jedes Teils auf Anwendungsebene zu ändern. Sie funktionieren alle auf ähnliche Weise, haben jedoch unterschiedliche Transaktions- / Parallelitätssemantiken, je nachdem, was Sie versuchen. Refs werden wahrscheinlich Ihre Standardauswahl sein - sie ermöglichen es Ihnen, "normales" STM-Transaktionsverhalten zu implementieren, indem Sie beliebigen Code in einen (dosync ...) Block einschließen.

  6. Wählen Sie das richtige allgemeine Webframework aus - Clojure hat bereits einige, aber ich würde Ring dringend empfehlen - sehen Sie sich dieses hervorragende Video " Ein Ring zum Binden " sowie entweder Fleet oder Enlive oder Hiccup an, je nach Ihrer Vorlagenphilosophie. Verwenden Sie diese Option, um Ihre Präsentationsebene zu schreiben (mit Funktionen wie "Diesen Einkaufswagen in ein geeignetes HTML-Fragment übersetzen").

  7. Zum Schluss schreiben Sie Ihre Bewerbung mit den oben genannten Tools. Wenn Sie die oben genannten Schritte ordnungsgemäß ausgeführt haben, ist dies tatsächlich ganz einfach, da Sie die gesamte Anwendung durch geeignete Zusammensetzung der verschiedenen Komponenten mit sehr wenig Boilerplate erstellen können.

Dies ist ungefähr die Reihenfolge, in der ich das Problem angreifen würde, da es weitgehend die Reihenfolge der Abhängigkeiten in Ihrem Code darstellt und daher für einen "Bottom-up" -Entwicklungsaufwand geeignet ist. Obwohl Sie sich natürlich in einem guten agilen / iterativen Stil befinden, werden Sie wahrscheinlich frühzeitig zu einem nachweisbaren Endprodukt vordringen und dann ziemlich häufig zu früheren Schritten zurückkehren, um die Funktionalität oder den Refactor nach Bedarf zu erweitern.

ps Wenn Sie dem obigen Ansatz folgen, wäre ich fasziniert zu hören, wie viele Clojure-Zeilen erforderlich sind, um die Funktionalität von 50.000 Java-Zeilen zu erreichen

Update : Seit dieser Beitrag ursprünglich geschrieben wurde, sind einige zusätzliche Tools / Bibliotheken entstanden, die sich in der Kategorie "Muss auschecken" befinden:

  • Noir - Webframework, das auf Ring aufbaut.
  • Korma - ein sehr schönes DSL für den Zugriff auf SQL-Datenbanken.
mikera
quelle
4
Nitpick re: "Entscheiden Sie, welchen der STM-Referenztypen von Clojure Sie verwenden möchten, um den Status jedes veränderlichen Teils auf Anwendungsebene zu verwalten": Es gibt nur einen STM-Referenztyp. Die anderen IRefs beinhalten kein STM. Ansonsten sieht es nach soliden Ratschlägen aus.
hmmm ... Ich schätze, ich zähle Refs, Agenten und Atome als Teil des Clojure STM / Concurrency-Systems. Zum Beispiel unterstützen sie alle Validatoren, und Agenten werden mit Commits von Transaktionen koordiniert. Aber ich verstehe, Refs sind das "primäre" Transaktionsmodell. wird eine schnelle Änderung vornehmen.
Mikera
2
Wenn ich nur mehr +1 geben könnte. Ich habe mir beide Videos angesehen, auf die Sie verwiesen haben, und sie waren großartig. Vielen Dank.
JDL
1
Jetzt ist noir veraltet. Ich nehme an, Sie müssen über Compojure statt Noir sprechen.
Hsestupin
Ein Link zum Binden ist unterbrochen!
Adam Arold
5

Welche Aspekte von Java beinhaltet Ihr aktuelles Projekt? Protokollierung, Datenbanktransaktionen, deklarative Transaktionen / EJB, Web-Layer (Sie haben JSP, Servlets erwähnt) usw. Ich habe festgestellt, dass das Clojure-Ökosystem verschiedene Mikro-Frameworks und Bibliotheken mit dem Ziel hat, eine Aufgabe zu erledigen und es gut zu machen. Ich würde vorschlagen, Bibliotheken basierend auf Ihrem Bedarf (und ob sie in großen Projekten skaliert werden) zu bewerten und eine fundierte Entscheidung zu treffen. (Haftungsausschluss: Ich bin der Autor von bitumenframework ) Eine weitere zu beachtende Sache ist der Erstellungsprozess. Wenn Sie ein komplexes Setup (Entwicklung, Testen, Staging, Prod) benötigen, müssen Sie das Projekt möglicherweise in Module aufteilen und den Erstellungsprozess für Skripte erstellen lassen Leichtigkeit.

Shantanu Kumar
quelle
Servlets, JSP, selbstgebautes Persistenz-Framework (10 Jahre alt) und Pojos, aber kein EJB
appshare.co
4
Servlets können einfach durch Ring + Compojure IMHO ersetzt werden, und JSPs können möglicherweise durch StringTemplate (oder FreeMarker / Velocity-Vorlagen) ersetzt werden. Die Persistenz in Clojure unterscheidet sich von Java. Wenn Sie eine relationale Zuordnung benötigen, können Sie sich Clj-Record und SQLRat ansehen (noch nicht sehr ausgereift). ClojureQL unterstützt derzeit nur MySQL und PostgreSQL AFAICT. Die derzeitige Einschränkung in ccsql, Unterstriche in Spaltennamen nicht zuzulassen, kann überraschend sein. Ich denke, dass es nützlich sein wird, die Entwicklungsaspekte auf der Clojure-Liste nach Bedarf zu diskutieren. Viel Glück beim Projekt!
Shantanu Kumar
Seit diesem Projekt habe ich eine weitere Anwendung mit Clojure und Clojurescript (nemcv.com) erstellt und verwende jetzt Ring, habe ClojureQL ausprobiert, aber für den Datenbankzugriff zu Korma gewechselt. Sie können die neuesten Arbeiten unter github.com/zubairq/coils
appshare.co
4

Ich fand es am schwierigsten, über die Datenbank nachzudenken. Führen Sie einige Tests durch, um die richtigen Tools zu finden, die Sie dort verwenden möchten.

LenW
quelle
1
Nun, ich habe Clojureql für den Datenzugriff ausprobiert, aber es unterscheidet sich grundlegend vom Java-Stil des Datenbankzugriffs, der allesamt objektbasiert ist. Nur aus Interesse, welchen Datenbankzugriff haben Sie für Java verwendet und was haben Sie mit Clojure verwendet?
appshare.co
1
Am Ende haben wir eine Menge Dinge überdacht und uns für Mongodb entschieden, da das Fortbestehen von Clojure-Datenstrukturen sehr natürlich war
LenW