【发布时间】:2013-05-22 18:10:33
【问题描述】:
我正在编写这个程序,它就像一个用于在线论坛的网络爬虫。对于我抓取的每个论坛,我都需要做同样的事情:
- 登录
- 查找板
- 查找帖子
- 找到帖子的固定链接
- 查找发帖人的用户名
- 等
现在,虽然每个论坛都需要执行相同的逻辑,但每个论坛的实现是不同的。例如,每个论坛的每个登录表单的输入都不同。一个论坛可能有一个名为“用户名”的字段,另一个可能有一个名为“用户”的字段。其中一些步骤可能具有默认实现。例如,login 的默认实现是不做任何事情(因为您不必登录某些论坛来抓取它)。
我所做的是创建了一个函数,其中包含所有这些步骤,名为crawl-forum,但实现是抽象的并在其他地方实现。我的问题是,让crawl-forum 使用这些实现的最佳方式是什么?
我尝试过的
1) 配置图
这是我迄今为止尝试过的。我为crawl-forum 函数添加了一个新参数,称为configs。它是一个如下所示的地图数据结构:
{ :login login-function
:find-boards find-boards-function
...
}
调用crawl-forum 的代码负责填充该映射。我不喜欢的是 configs 需要在整个 crawl-forum 代码中传递。它到处添加一个新参数。此外,我还有一些用于处理默认实现的蹩脚的临时代码。
2) 多种方法
我在 irc 上谈到了这一点,有人给了我一个想法,我应该为此使用多方法,因为它确实是多态行为。它们看起来像这样:
(defn get-site-key [& args] (first args))
(defmulti login get-site-key)
(defmethod login :default [site-key cookie-store] nil)
那么客户端代码必须在外面定义自己的多方法:
(defmethod login :forum-1 [site-key cookie-store] (do-something cookie-store))
我不喜欢的是,就像config 一样,我必须将site-key 传递给crawl-forum 函数,而site-key 仍然必须在内部各处传递。此外,每个defmethod 都必须将其自己的site-key 作为参数传回,但它们都不会永远使用它。这只是进行调度的必要参数。不过,我真的很难找到一个完整的多方法教程,所以如果有更聪明的方法可以做到这一点,请告诉我。
有没有更好的第三个选项?有没有更好的方法来使用多方法?告诉我,谢谢。
【问题讨论】:
-
@nathanhayfield 那条评论对我来说没有意义。这是在 clojure 中。
-
使用配置映射似乎不是一种反模式。你可以使用
get的 not-found 选项、or宏和:or指令破坏来减轻你的“用于处理默认实现的蹩脚的临时代码”吗?如果使用多方法,你也有默认值。 -
@A.Webb 这正是我所做的。我认为这有点蹩脚,因为地图是到处传递的,但
:or是在使用之前为每个函数定义的。也许我应该在一个地方完成这一切。
标签: design-patterns clojure multimethod