Я только что попросил мою компанию переписать довольно большое (50 000 отдельных строк кода) приложение Java (веб-приложение с использованием JSP и сервлетов) в Clojure. Кто-нибудь еще получил советы о том, что я должен соблюдать?
Пожалуйста, имейте в виду, что я хорошо знаю как Java, так и Clojure.
Я переписал и пошел в производство. Это довольно странно, поскольку переписывание закончилось так быстро, что это было сделано примерно через 6 недель. Поскольку много функциональности не требовалось, все же это больше похоже на 3000 строк Clojure. Я слышал, что они довольны системой и делают именно то, что хотели. Единственным недостатком является то, что парень, поддерживающий систему, должен был научиться Clojure с нуля, и его затащили в него ногами и криками. Я получил звонок от него на днях, сказав, что он любил Lisp, хотя.. смешно:)
Кроме того, я должен упомянуть Ваадина. Использование Vaadin, вероятно, учитывало столько времени, сколько было сохранено и коротко сжато кода, поскольку Clojure сделал.. Vaadin по-прежнему является верхней веб-картой, которую я когда-либо использовал, хотя теперь я изучаю ClojureScript в гневе! (Обратите внимание, что как Vaadin, так и ClojureScript используют рамки графического интерфейса Google под капотом)
Самая большая "проблема перевода", вероятно, будет идти от методологии 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":
Какие аспекты Java включает ваш текущий проект? Logging, транзакции базы данных, декларативные транзакции /EJB, веб-уровень (вы упомянули JSP, сервлеты) и т.д. Я заметил, что экосистема Clojure имеет различные микро-рамки и библиотеки с целью сделать одну задачу и сделать это хорошо, Я бы предложил оценить библиотеки на основе ваших потребностей (и будет ли он масштабироваться в крупных проектах) и принять обоснованное решение. (Отказ от ответственности: я являюсь автором http://code.google.com/p/bitumenframework/) Еще одна вещь, которую следует отметить, это процесс сборки - если вам нужна сложная настройка (dev, testing, sting, prod), вам, возможно, придется разделить проект на модули и создать сценарий сборки для удобства.
Я обнаружил, что самая сложная часть была связана с базой данных. Сделайте несколько тестов, чтобы найти нужные инструменты, которые вы хотите использовать там.