Clojure中的DSL取代了面向对象的软件解决方案?

时间:2011-10-14 17:49:18

标签: java clojure domain-driven-design data-modeling

大家好:我想知道是否有人知道Clojure中DSL的具体示例,它取代了优秀OO程序的抽象和可读性(用Java编写)。

我一直在尝试将OO数据模型(基于“bean”,使用非常抽象的方法隐藏底层实现)变成一个clojure moeity ......

我知道存在“宏”和“高阶函数”,但是,我从未将它们应用于易于理解的真实世界数据集(例如,课程注册系统或汽车经销商,或计费系统,或某种类型的东西,回想起过去十年Hibernate和Ibatis推广的臭名昭着的“JPetStore”例子。)

无论如何......我的基本问题是:

是否存在任何特定于域的模板,用于学习如何使用协议和高阶函数对Clojure中的真实世界系统进行建模?

3 个答案:

答案 0 :(得分:3)

没有针对DSL的特殊模板 - 您只需使用语言中提供的工具,并尽量使其尽可能方便且靠近域。 Lisp只为您提供了比其他语言更多的工具。

有关DSL的详细示例,请查看ClojureQL。最初,SQL是为关系数据库创建的DSL。从控制台工作非常方便...但不是像Java或Clojure这样的编程语言。 Java带有像Hibernate这样的大型ORM框架,而Clojure提供了简单的DSL,它与原始SQL一样方便,但完全可以作为语言的一部分使用:

(select (table :users) (where (= :id 5)))

Lisp DSL中常见的事情是使用像defsomething这样的结构。例如,在一本书中(抱歉,我不记得它的名字),有一个文本模式匹配的例子。作者为一个单词创建了包含?匹配器的模块,一个或多个单词为+,零个或多个单词为*,依此类推。为此,他创建了宏defmatcher,它采用了一些语法,并将此语法的处理程序添加到中央注册表。这只是抽象 - 而不是几次重复操作,他引入单宏来告诉他实际想做什么 - 定义匹配器。此示例还使用 - 宏和高阶函数。

所以,再一次,在基于Lisp的DSL中没有什么特别之处 - 你只需用你的语言 描述域区域,无论是Java,Clojure还是其他任何东西。只需使用语言设施,您就会看到它的样子。

UPD。一些“真实世界”的例子,其中基于Lisp的DSL比OOP更方便:

域名:汽车驱逐舰

(defcar my-cool-car :wheels 4, :doors 2, :color red) ;; in Java you need Factory
(def car1 (make-car my-cool-car))                    ;; and lots of methods to 
                                                     ;; add features to cars and 
                                                     ;; cars to factory

域名:结算系统

(transaction                ;; in Java you cannot create wrapping constructs
  (withdraw account1 100)   ;; so you have to use inheritance, annotations, etc.
  (put account2 100))       ;; which is much more code

域:一些处理多种类型请求的Web服务

(defhandler :show-all (fn [params] ...))     ;; adds defined function to the
(defhandler :find-best (fn [params] ...))    ;; map of :message-type -> function
...
(defn handle [message]
   (let [msg-type (:type message), msg-params (:params message)]
     (if (contains? *handlers* msg-type) 
       ((*handlers* msg-type) msg-params)
       (throw (Exception. (concat "No handler for type" (:type message)))))))

这些示例没有什么特别之处 - 您可以用Java或任何其他语言实现它们。虽然,关键字(第一个示例),高阶函数(第二个示例),宏(所有3个示例)之类的东西使您的代码更简洁和描述性。

答案 1 :(得分:1)

我不知道这是不是你想要的,但我读过一本关于Clojure(编程Clojure;实用程序员)的书,其中包含了一个很好的小DSL的例子。您可以在https://github.com/stuarthalloway/lancet找到代码。基本上lancet就像 make ant ,但实现为Clojure-DSL。

答案 2 :(得分:1)

OOP很好,我们已经习惯了它,并且它映射到现实世界中的概念。

你可以在第9章的欢乐中看到如何使用地图和多种方法构建一个OOP系统(类似于JS中的原型继承)。

来自Paul Graham的lisp书籍展示了如何在lisp中创建对象系统。应该很容易使它适应clojure。

本书还广泛地解释了“自下而上”的编程,即构建小型基础砖并构建它们以构建更高级的构造。

另外,如果您在许多应用程序(如java宠物商店)中看到主要概念是程序/功能,并且不会广泛使用泛化或封装等对象概念。

Bean没有行为。没有封装的数据具有getter / setter允许公共访问它们。对于它给你的东西,你可以使用C结构(用类型语言)或动态语言中的地图,如clojure。

对它们起作用的服务基本上是功能。它们没有状态,并从参数(bean)或数据库中获取数据。如果你真的需要inteface,你有clojure协议。

那并不复杂。

在JAVA中命名你的bean ...但是在clojure map或作为记录实现它们

为您的服务命名并将其实现为功能。

需要工厂吗?该函数采用配置和返回函数。

需要依赖注射吗?那么你可以使用函数参数。