我是clojure的新手,我正在尝试理解不同情况下可用的不同设计选择。在这种特殊情况下,我想将紧密耦合的功能组合在一起,并且可以将函数作为集合传递。
何时使用功能图分组紧密相关的功能以及何时使用协议(+实现)?
有哪些优点和缺点?
要么更惯用吗?
供参考,以下是我的意思的两个例子。使用fn贴图:
(defn do-this [x] ...)
(defn do-that [] ...)
(def some-do-context { :do-this (fn [x] (do-this x)
:do-that (fn [] (do-that) }
在第二种情况下,
(defprotocol SomeDoContext
(do-this[this x] "does this")
(do-that[this] "does that")
(deftype ParticularDoContext []
SomeDoContext
(do-this[this x] (do-this x))
(do-that[this] (do-that))
答案 0 :(得分:1)
这完全取决于“紧密相关的功能”的含义。可以有两种解释:
这些功能集实现了系统的特定组件/子系统。示例:日志记录,身份验证等。在这种情况下,您可能会使用clojure命名空间(AKA模块)对相关函数进行分组,而不是使用哈希映射。
这些函数集在一些数据结构或类型或对象等上协同工作。在这种情况下,您将使用基于协议的方法,该方法允许ad-hoc多态,以便新类型也可以提供这组功能。示例:任何接口类型:可排序,可打印等。
答案 1 :(得分:1)
协议就像Interfaces
,所以如果您要创建的是一个,请使用协议。
如果您只是尝试将某个地方related functions
分组使用namespace
,则可以将您的功能浮动到那里,而不是特定的Object
。
在我看来,你正在考虑对象并使用map
来模拟一个对象或一个结构,你将你的功能连接在一起。感觉不自然,除非它确实是一种类型或协议,在这些情况下你应该使用defrecord
,deftype
和defprotocol
。
关于使用defprotocol
和defrecord
:
(defprotocol IAnimal
"the animal protocol"
(inner-report [o] "a report"))
(defrecord Dog []
IAnimal
(inner-report [o]
(println "Woof Woof.\n")))
(defrecord Cat []
IAnimal
(inner-report [o]
(println "Meow Meow.\n")))
答案 2 :(得分:0)
我的第一印象是第一种方式是面向数据,第二种方式是面向类型。到目前为止,我更喜欢面向数据。 也许这个决定与Alan Perlis的引述有关:“在一个数据结构上运行100个函数比在10个数据结构上运行10个函数更好。”