4

Clojureの学習演習として、私が作成したグラフデータベースライブラリであるBulbs(http://bulbflow.com)をPythonからClojureに移植しています。

私がまだやや曖昧なことの1つは、Clojureの慣用的な方法でライブラリを構造化する方法です。

複数のデータベースをサポートするために、Bulbsは依存性注入を使用します。さまざまなデータベースバックエンドは、インターフェイスを実装するカスタムClientクラスに抽象化され、クライアントは実行時に構成されます。

Graphオブジェクトとそのさまざまなプロキシオブジェクトは、低レベルのClientオブジェクトのインスタンスを保持します。

# bulbs/neo4jserver/graph.py

class Graph(object):

    default_uri = NEO4J_URI

    def __init__(self, config=None):
        self.config = config or Config(self.default_uri)
        self.client = Neo4jClient(self.config)

        self.vertices = VertexProxy(Vertex, self.client)
        self.edges = EdgeProxy(Edge, self.client)

Bulbsを使用するには、それぞれのグラフデータベースサーバーのGraphオブジェクトを作成します。

>>> from bulbs.neo4jserver import Graph
>>> g = Graph()

次に、プロキシオブジェクトを介してデータベースに頂点とエッジを作成できます。

>>> james = g.vertices.create(name="James")
>>> julie = g.vertices.create(name="Julie")
>>> g.edges.create(james, "knows", julie)

この設計により、REPLからBulbsを簡単に使用できるようになります。これは、Graphオブジェクトをインポートしてインスタンス化する(または必要に応じてカスタムConfigオブジェクトを渡す)だけで済むためです。

しかし、Graphオブジェクトとそのプロキシーは、実行時に構成されるClientオブジェクトを保持する必要があるため、Clojureでこの設計にアプローチする方法がわかりません。

Clojure-これを行う方法は何ですか?

更新:これは私がやったことです...

;; bulbs/neo4jserver/client.clj

(def ^:dynamic *config* default-config)

(defn set-config!
  [config]
  (alter-var-root #'*config* (fn [_] (merge default-config config))))

(defn neo4j-client
  [& [config]]
  (set-config! config))

(neo4j-client {:root_uri "http://localhost:7474/data/db/"})

(println *config*)

更新2:

Andrew Cookeは、グローバル変数を使用すると、Pythonバージョンでは使用できるのに対し、プログラムで複数の独立したグラフ「インスタンス」を使用できなくなると指摘しました。

そして、私はこれを思いついた:

(defn graph
  [& [config]]
  (let [config (get-config config)]
    (fn [func & args]
      (apply func config args))))

(defn create-vertex
  [config data]
  (let [path (build-path vertex-path)
        params (remove-null-values data)]
    (rest/post config path params)))

(defn gremlin
  [config script & [params]]
  (rest/post config gremlin-path {:script script :params params}))

そして、次のようなさまざまな関数を呼び出すことができます。

(def g (graph {:root_uri "http://localhost:7474/data/db/"}))

(g create-vertex {:name "James"})

(g gremlin "g.v(id)" {:id 178})

今はまだマクロを掘り下げていませんし、他の人と比べてこのアプローチのメリットがよくわからないので、フィードバックを歓迎します。

4

1 に答える 1

6

プロトコルはClojureでこれに非常に適しています。データベースとのインターフェースに必要なすべての関数を定義するプロトコル(インターフェースによく似ています)を定義し、実行時に、プロトコルのインスタンスで構築されるグラフプロトコルのコンストラクターを呼び出します。選択したDBに接続します。

基本的なフローは、Clojureプロトコルを使用することを除いてほとんど同じです。

于 2012-05-10T20:22:23.357 に答える