[Gauche-devel-jp] Re: module名を文字列で指定してロードしたい

アーカイブの一覧に戻る

Shiro Kawai shiro****@lava*****
2003年 11月 25日 (火) 16:25:59 JST


From: yasuy****@javao*****
Subject: [Gauche-devel-jp] Re: module名を文字列で指定してロードしたい
Date: Tue, 25 Nov 2003 15:40:03 +0900

> > このコードだとdbi-make-driverが定義されているモジュール(dbi)に
> > どんどん新しいモジュールがインポートされてしまうのがちょっと気持ち
> > 悪いので、requireだけしておいて、直接dbd.*内の定義を覗く方法もあります。
> 
> dbiを利用する側からみたとき、dbi-make-driver で作られた
> <pg-driver> を使ってコネクションオブジェクトを作る際に、
> dbi-make-connection が
> 基底クラスである <connection> 型ではなく、
> 引数のドライバーの型でディスパッチして <pg-connection> 型のオブジェクトを
> 作って欲しいのですが、requireだけする方法だと、
> このディスパッチを dbi-make-connection の中に記述することになる気がしています。

いや、ジェネリックファンクションdbi-make-connectionが共通の
dbdモジュールに定義されてさえいれば、dbd.pg等の各dbd実装
モジュールがdefine-methodしたメソッドはそのジェネリックファンクションに
くっつくので、dbiモジュールの中で明示的にディスパッチを書く
必要はないです。importするというのは単なる名前の可視性だけの
問題ですから。

モジュールdbi ----------------------

(define-method dbi-make-connection (top)
  .. デフォルトの動作 (エラーとか) ...)

モジュールdbd.pg -------------------

(use dbi)

(define-method dbi-make-connection ((driver <pg-driver>))
  ...
  (make <pg-connection> ....))

ユーザ -----------------------------

(use dbi) ;; dbd.pg が見える必要はない。

(let* ((driver (dbi-make-driver ...))
       (connection (dbi-make-connection driver))) ;; ちゃんとディスパッチされる
  ...)

> RDBからRDBへテーブルをコピーする簡易GUIツールを作るとします。
> 例えば PostgreSQLとMySQLのドライバーが組み込まれていて、
> コピー元とコピー先のドライバーは自由に選べるとしたら、
> どのRDBMSからどのRDBMSへコピーするかは実行時でないと分かりません。
> 
> このような応用を考えると、静的に追跡不可能な状況は避けられない気がしています。

ええ、ですから、どこかのレベルで実行時ロードは必要なのです。
が、それをアプリケーションレベルで行えば、少なくともライブラリに
関しては静的解析が可能になります。
ライブラリレベルで行ってしまうと、そのライブラリを使う全ての
ライブラリが静的解析不可能になります。
(それに、この例ですとGUIツールのメニューか何かでドライバーを
選ばせるかなんかするんですよね? そしたらどっちにせよアプリケーション
レベルでドライバのリストを作っておく必要がありますね)

まあ、どこまで静的解析にこだわる必要があるか、なんですが。
直観でしかないんですが、(eval '(require ...)) は
「スジが悪く」見えるんですね。

ただ、Perl方式の文字列指定も捨て難くはあるので、例えばこんな
低レベルAPIを用意しておいて:

  [function] dbd-search-driver-modules

    システムにインストールされているドライバモジュールを
    検索し、(ドライバ名 . モジュール名) のリストを返す。
    (("pg" . dbd.pg) ("mysql" . dbd.mysql) ...) みたいな。
    library-foldあたりを使えばできそう。

  [function] dbd-search-driver-module driver-name

    システムにインストールされているドライバモジュールの
    うち、ドライバ名driver-nameを実装しているものを
    見付けてそのモジュール名を返す。無ければ#f。

  [function] dbd-load-driver-class driver-name

    ドライバ名 ("pg" 等) を受けて、そのモジュールを
    ロードし、ドライバクラスを返す。
    (ここでevalが必要)

dbi-make-driverはこの上に構築すると。
これだと、動的ロードの基本機能はdbd-load-driver-classに
集中しているので、後でこういう動的ロードAPIをシステムでサポート
した時にはそこだけ置き換えれば済みます。

--shiro

    



Gauche-devel-jp メーリングリストの案内
アーカイブの一覧に戻る