オンライン フォーラムの Web クローラーのようなプログラムを書いています。クロールするフォーラムごとに、同じことを行う必要があります。
- ログインする
- ボードを見つける
- 投稿を見つける
- 投稿へのパーマリンクを見つける
- 投稿者のユーザー名を見つける
- 等
これと同じロジックが各フォーラムで発生する必要がありますが、各フォーラムの実装は異なります。たとえば、各ログイン フォームの入力はフォーラムごとに異なります。1 つのフォーラムには「username」という名前のフィールドがあり、もう 1 つのフォーラムには「user」という名前のフィールドがある場合があります。これらのステップの一部には、デフォルトの実装がある場合があります。たとえば、 のデフォルトの実装で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
に渡す必要があり、それを内部のあらゆる場所に渡さなければならないことです。また、everyはパラメーターとして独自に戻す必要がありますが、いずれもそれを使用することはありません。これは単にディスパッチを行うために必要な引数です。ただし、完全なマルチメソッドのチュートリアルを見つけるのは非常に難しいので、これを行うよりスマートな方法があれば教えてください.site-key
crawl-forum
site-key
defmethod
site-key
さらに優れた3番目のオプションはありますか?マルチメソッドを使用するより良い方法はありますか? 教えてください、ありがとう。