Я разрабатываю JAX-RS REST-сервер с использованием Clojure и RESTEasy.
Насколько я понимаю, приложения, написанные на языках семейства Lisp, в большей степени, чем приложения на "традиционных" императивных языках, строятся как "языки, специфичные для конкретного домена". Приложение разрабатывается снизу вверх как все более и более "утонченные" функции, пока на "верхнем" уровне приложение не превращается в серию вызовов функций очень высокого уровня.
Я пытаюсь сделать это для своего REST-сервера, начиная с классов ресурсов, которые обслуживают URL-запросы (GET, POST, PUT, DELETE).
Вот мой первый ресурс:
(ns com.example.server.resources.buildtime
(:import [javax.ws.rs CookieParam GET Produces Path]
[javax.ws.rs.core Context Cookie NewCookie Response UriInfo]
[org.jboss.resteasy.annotations.providers.jaxb Formatted]))
(definterface BuildTime
(getBuildTime [^javax.ws.rs.core.UriInfo info
^javax.ws.rs.core.Cookie security-cookie]))
(deftype
^{Formatted true}
BuildTimeResource []
BuildTime
(^{GET true
Path "/buildtime"
Produces ["application/json"]}
getBuildTime
[this info security-cookie]
(.. (Response/ok "20111009") build)))
Этот ресурс возвращает время сборки сервера в виде строки (заключенной в пакет JSON) при вызове по URL "/buildtime" с помощью метода GET http.
Я буду писать еще много таких классов ресурсов и вложенных методов (у большинства классов будет более одного метода), каждый из которых будет иметь definterface
и deftype
. Это кажется идеальным использованием макросов.
Я прошу предложений о том, как это можно сделать в виде DSL. Как нужно мыслить в терминах DSL?