Ответ 1
Самая большая "проблема перевода", вероятно, будет идти от методологии 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":