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

93

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

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

Update

Я переписал и пошел в производство. Это довольно странно, поскольку переписывание закончилось так быстро, что это было сделано примерно через 6 недель. Поскольку много функциональности не требовалось, все же это больше похоже на 3000 строк Clojure. Я слышал, что они довольны системой и делают именно то, что хотели. Единственным недостатком является то, что парень, поддерживающий систему, должен был научиться Clojure с нуля, и его затащили в него ногами и криками. Я получил звонок от него на днях, сказав, что он любил Lisp, хотя.. смешно:)

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

  • 53
    Я хочу работать в вашей компании.
  • 3
    Ну, некоторые оборонные компании в Европе начали использовать Clojure (я слышал). Но не могу вспомнить ни одного имени :)
Показать ещё 9 комментариев
Теги:
clojure
vaadin

3 ответа

79
Лучший ответ

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

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

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

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

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

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

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

  • Решите, как вы хотите использовать ссылочные типы Clojure (vars, refs, agents и atom) для управления каждой частью изменчивого состояния уровня приложения. Все они работают аналогично, но имеют разную транзакционную /concurrency семантику в зависимости от того, что вы пытаетесь сделать. Refs, вероятно, будет вашим выбором по умолчанию - они позволяют реализовать "нормальное" транзакционное поведение STM путем упаковки любого кода в блок (dosync...).

  • Выберите правильный общий веб-фреймворк - Clojure уже есть немало, но я настоятельно рекомендую Ring - см. это отличное видео " One Ring To Bind Them" плюс либо Fleet или Enlive или Hiccup в зависимости от вашей философии шаблонов. Затем используйте это, чтобы написать свой слой презентации (с такими функциями, как "перевести эту корзину покупок в соответствующий фрагмент HTML" )

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

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

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

Обновить. Поскольку этот пост был первоначально написан, появилось несколько дополнительных инструментов/библиотек, которые находятся в категории "must check out":

  • Noir - веб-фреймворк, который строится поверх Ring.
  • Korma - очень хороший DSL для доступа к базам данных SQL.
  • 4
    Nitpick re: «Решите, какой из эталонных типов STM Clojure вы хотите использовать для управления каждой изменяемой частью уровня приложения»: существует только один эталонный тип STM. Другие IRef не включают STM. В противном случае выглядит солидный совет.
  • 0
    хммм ... я думаю, я считаю, что ссылки, агенты и атомы являются частью системы Clojure STM / параллелизма. Например, все они поддерживают валидаторы, а агенты координируются с фиксацией транзакций. но я понимаю вашу точку зрения, ссылки являются «основной» транзакционной моделью. внесу быструю поправку.
Показать ещё 3 комментария
5

Какие аспекты Java включает ваш текущий проект? Logging, транзакции базы данных, декларативные транзакции /EJB, веб-уровень (вы упомянули JSP, сервлеты) и т.д. Я заметил, что экосистема Clojure имеет различные микро-рамки и библиотеки с целью сделать одну задачу и сделать это хорошо, Я бы предложил оценить библиотеки на основе ваших потребностей (и будет ли он масштабироваться в крупных проектах) и принять обоснованное решение. (Отказ от ответственности: я являюсь автором http://code.google.com/p/bitumenframework/) Еще одна вещь, которую следует отметить, это процесс сборки - если вам нужна сложная настройка (dev, testing, sting, prod), вам, возможно, придется разделить проект на модули и создать сценарий сборки для удобства.

  • 0
    Сервлеты, JSP, самодельная среда персистентности (10 лет) и pojos, но без EJB
  • 4
    Сервлеты можно легко заменить на Ring + Compojure IMHO, а JSP можно заменить, возможно, на StringTemplate (или шаблоны FreeMarker / Velocity). Постоянство в Clojure будет отличаться от Java. Если вам нужно реляционное отображение, вы можете взглянуть на Clj-Record и SQLRat (пока не очень зрелый). В настоящий момент ClojureQL поддерживает только MySQL и PostgreSQL AFAICT. Нынешнее ограничение в ccsql запретить подчеркивание в именах столбцов может стать неожиданностью. Я думаю, что обсуждение аспектов разработки в списке Clojure по мере необходимости будет полезным. Удачи в проекте!
Показать ещё 1 комментарий
4

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню