我正在写这个程序,就像在线论坛的网络爬虫一样。对于我爬网的每个论坛,我都需要做同样的事情:
现在,虽然每个论坛都需要执行相同的逻辑,但是每个论坛的实现都不同。例如,每个论坛的每个登录表单的输入都是不同的。一个论坛可能有一个名为“用户名”的字段,另一个论坛可能有一个名为“用户”的字段。其中一些步骤可能具有默认实现。例如,
login
的默认实现是不执行任何操作(因为您不必登录某些论坛即可对其进行爬网)。我所做的是创建了一个包含所有这些步骤的函数
crawl-forum
,但是实现是抽象的,并在其他地方实现。我的问题是,是使crawl-forum
使用这些实现的最佳方法是什么? 我尝试过的
1)配置图
到目前为止,这是我尝试过的。我在
crawl-forum
函数中添加了一个名为configs
的新参数。这是一个 map 数据结构,如下所示:{ :login login-function
:find-boards find-boards-function
...
}
调用
crawl-forum
的代码负责填充该 map 。我不喜欢的是configs
需要在整个crawl-forum
代码中传递。它随处添加新参数。此外,我还有一些la脚的临时代码用于处理默认实现。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
,但是没有人会使用它。这只是进行分派(dispatch)的必要参数。但是,对于我来说,很难找到详尽的多方法教程,因此,如果有更聪明的方法可以做到这一点,请告诉我。有没有第三种更好的选择?有没有更好的方法来使用多方法?让我知道,谢谢。
最佳答案
我会选择选项1。如果使 map 困扰,您始终可以使用动态var。对于默认值,我建议使用合并:
(def defaults { ... })
(def site-specific (merge defaults { ...}))