Переписать Java на Clojure

97

Моя компания только что попросила меня переписать большое (50 000 строк кода) Java-приложение (веб-приложение, использующее JSP и сервлеты) на Clojure. Есть ли у кого-нибудь еще советы о том, чего мне следует остерегаться?

Имейте в виду, что я достаточно хорошо знаю как Java, так и Clojure.

Обновить

Я переписал, и он пошел в производство. Это довольно странно, ведь переписывание закончилось так быстро, что на это ушло около 6 недель. Поскольку многие функциональные возможности не требовались, в итоге получилось больше 3000 строк Clojure.

Я слышал, что они довольны системой и делают именно то, что они хотели. Единственным недостатком является то, что парню, обслуживающему систему, пришлось изучать Clojure с нуля, и он был втянут в нее, пиная и крича. На днях мне действительно позвонил он и сказал, что теперь он любит Lisp ... смешно :)

Кроме того, я должен упомянуть Ваадина. Использование Vaadin, вероятно, привело к экономии времени и краткости кода, как и Clojure. Vaadin по-прежнему остается лучшим веб-фреймворком, который я когда-либо использовал, хотя теперь я изучаю ClojureScript в гневе! (Обратите внимание, что и Vaadin, и ClojureScript используют фреймворки графического интерфейса Google под капотом.)

appshare.co
источник
55
Я хочу работать в вашей компании.
mtyaka 08
4
Ну, некоторые оборонные компании в Европе начали использовать Clojure (я слышал). Но не могу вспомнить имена :)
appshare.co
1
@Zubair: 50 000 Java LOC далеко не «щедрый». Это очень маленький проект. У меня есть Java-проект от 250KLOC до 300KLOC, и он среднего размера ... В лучшем случае.
SyntaxT3rr0r 09
5
На самом деле, возможно, я ошибся, упомянув размер кодовой базы, поскольку, честно говоря, уменьшение размера кода не является целью переписывания. Цель двоякая: 1) сделать кодовую базу более понятной и, следовательно, дешевле поддерживать код 2) Разрешить пользователям инструмента расширять продукт с помощью редактора Clojure в веб-браузере (используя eval и другие динамические возможности Clojure, которые дороже делать на Java)
appshare.co
1
Эй ... только что увидел этот старый вопрос и задумался, как продвигается переписывание?
levand

Ответы:

82

Самая большая «проблема перевода», вероятно, будет связана с переходом от методологии Java / OOP к парадигме Clojure / функционального программирования.

В частности, вместо того, чтобы иметь изменяемое состояние внутри объектов, «способ Clojure» состоит в том, чтобы четко отделить изменяемое состояние и разработать чистые (без побочных эффектов) функции. Вы, наверное, уже все это знаете :-)

В любом случае, эта философия имеет тенденцию вести к чему-то вроде стиля разработки «снизу вверх», когда вы сосредотачиваете начальные усилия на создании правильного набора инструментов для решения вашей проблемы, а затем, наконец, соединяете их вместе в конце. Это может выглядеть примерно так

  1. Определите ключевые структуры данных и преобразуйте их в неизменяемые определения карты или записи Clojure. Не бойтесь вкладывать множество неизменяемых карт - они очень эффективны благодаря постоянным структурам данных Clojure. Чтобы узнать больше, стоит посмотреть это видео .

  2. Разработайте небольшие библиотеки функций, ориентированных на чистую бизнес-логику, которые работают с этими неизменяемыми структурами (например, «добавить товар в корзину»). Вам не нужно делать все это сразу, так как позже легко добавить больше, но это помогает сделать несколько на раннем этапе, чтобы облегчить тестирование и доказать, что ваши структуры данных работают ... в любом случае в этом момент, вы можете начать писать полезные вещи в интерактивном режиме в REPL

  3. Отдельно разрабатывайте процедуры доступа к данным, которые могут сохранять эти структуры в / из базы данных, сети или устаревшего кода Java по мере необходимости. Причина, по которой это нужно держать отдельно, заключается в том, что вы не хотите, чтобы логика сохраняемости была связана с вашими функциями «бизнес-логики». Возможно, вы захотите взглянуть на ClojureQL для этого, хотя также довольно легко обернуть любой код сохраняемости Java, который вам нравится.

  4. Напишите модульные тесты (например, с помощью clojure.test ), которые охватывают все вышеперечисленное. Это особенно важно для динамического языка, такого как Clojure, поскольку а) у вас нет такой защиты от статической проверки типов и б) это помогает убедиться, что ваши конструкции нижнего уровня работают хорошо, прежде чем вы будете слишком много строить на верх из них

  5. Решите, как вы хотите использовать ссылочные типы Clojure (переменные, ссылки, агенты и атомы) для управления каждой частью изменяемого состояния на уровне приложения. Все они работают одинаково, но имеют разную семантику транзакций / параллелизма в зависимости от того, что вы пытаетесь сделать. Ссылки, вероятно, будут вашим выбором по умолчанию - они позволяют реализовать «нормальное» транзакционное поведение STM, заключая любой код в блок (dosync ...).

  6. Выберите правильный общий веб - фреймворк - Clojure имеет довольно много уже , но я настоятельно рекомендую кольцо - посмотреть отличное видео « Одно Кольцо , чтобы связать их » плюс либо Fleet или Enlive или икота в зависимости от вашей философии шаблонной. Затем используйте это, чтобы написать свой уровень презентации (с такими функциями, как «преобразовать эту корзину в соответствующий фрагмент HTML»)

  7. Наконец, напишите свое приложение, используя указанные выше инструменты. Если вы выполнили описанные выше шаги правильно, то это действительно будет несложно, потому что вы сможете построить все приложение с помощью соответствующей композиции различных компонентов с очень небольшим количеством шаблонов.

Это примерно та последовательность, в которой я хотел бы атаковать проблему, поскольку она широко представляет порядок зависимостей в вашем коде и, следовательно, подходит для разработки «снизу вверх». Хотя, конечно, в хорошем гибком / итеративном стиле вы, вероятно, рано или поздно будете продвигаться вперед к демонстрационному конечному продукту, а затем довольно часто возвращаться к предыдущим шагам, чтобы расширить функциональность или рефакторинг по мере необходимости.

ps. Если вы последуете описанному выше подходу, я был бы очень рад услышать, сколько строк Clojure нужно, чтобы соответствовать функциональности 50 000 строк Java.

Обновление : поскольку этот пост был изначально написан, появилось несколько дополнительных инструментов / библиотек, которые находятся в категории «обязательно проверить»:

  • Noir - веб-фреймворк, который строится поверх Ring.
  • Korma - очень хороший DSL для доступа к базам данных SQL.
Микера
источник
4
Nitpick re: «Решите, какой из ссылочных типов STM Clojure вы хотите использовать для управления каждым изменяемым состоянием на уровне приложения»: существует только один ссылочный тип STM. Другие IRef не используют STM. В противном случае выглядит солидным советом.
хммм ... Я считаю, что ссылки, агенты и атомы являются частью системы Clojure STM / concurrency. Например, все они поддерживают валидаторы, а агенты координируют транзакции. но я понимаю вашу точку зрения, ссылки являются «основной» транзакционной моделью. сделаю быструю поправку.
mikera 08
2
Если бы я только мог поставить больше +1. Я посмотрел оба видео, на которые вы ссылались, и они были великолепны. Спасибо.
jdl 09
1
Теперь нуар устарел. Полагаю, вам следует упомянуть о самообладании вместо нуара.
hsestupin
Ссылка One Ring To Bind Them не работает!
Адам Арольд
5

Какие аспекты Java включены в ваш текущий проект? Ведение журнала, транзакции базы данных, декларативные транзакции / EJB, веб-уровень (вы упомянули JSP, сервлеты) и т. Д. Я заметил, что экосистема Clojure имеет различные микро-фреймворки и библиотеки с целью выполнить одну задачу и сделать это хорошо. Я бы посоветовал оценить библиотеки в зависимости от ваших потребностей (и от того, будут ли они масштабироваться в крупных проектах) и принять обоснованное решение. (Отказ от ответственности: я являюсь автором bitumenframework ) Еще одна вещь, на которую следует обратить внимание, это процесс сборки - если вам нужна сложная настройка (разработка, тестирование, постановка, производство), вам, возможно, придется разбить проект на модули и создать сценарий для процесса сборки. легкость.

Шантану Кумар
источник
Сервлеты, JSP, самодельный фреймворк персистентности (10 лет) и pojos, но без EJB
appshare.co 08
4
Сервлеты можно легко заменить на Ring + Compojure IMHO, а JSP можно заменить, возможно, StringTemplate (или шаблонами FreeMarker / Velocity). Постоянство в Clojure будет отличаться от Java. Если вам нужно реляционное сопоставление, вы можете посмотреть Clj-Record и SQLRat (пока не очень развиты). ClojureQL поддерживает только MySQL и PostgreSQL на данный момент AFAICT. Текущее ограничение ccsql на запрет подчеркивания в именах столбцов может стать неожиданностью. Я думаю, что обсуждение аспектов разработки в списке Clojure по мере необходимости будет полезно. Удачи в проекте!
Шантану Кумар
После этого проекта я сделал еще одно приложение с Clojure и Clojurescript (nemcv.com), и сейчас я использую Ring, попробовал ClojureQL, но переключился на Korma для доступа к базе данных. Вы можете увидеть последние работы на github.com/zubairq/coils
appshare.co
4

Я обнаружил, что самое сложное - думать о базе данных. Проведите несколько тестов, чтобы найти нужные инструменты, которые вы хотите использовать.

LenW
источник
1
Я пробовал clojureql для доступа к данным, но он полностью отличается от стиля доступа к базе данных Java, который полностью основан на объектах. Просто ради интереса, какой доступ к базе данных вы использовали для Java и что вы использовали с Clojure?
appshare.co
1
В итоге мы переосмыслили многие вещи и перешли на mongodb, так как постоянство структур данных clojure было очень естественным
LenW