コーラブルはすべてユーザー(利用者)定義となるわけだが、このコーラブル群とHoareRules実行フレームワークは切り離そう。適当なインターフェースを仕切りにして、コーラブルの詳細は隠蔽する。
public interface CallableLibrary {
// 実行フレームワークから呼ぶ必要があるメソッド群
}
絶対に必要なのは:
// 名前をキーとしてコーラブルを取得、なければnullが返る。
// 僕はgetXxx()よりxxx()が好きpublic Callable callable(String name);
public Function function(String name); // 述語も関数に含まれることに注意
public Predicate predicate(String name);
public Command command(String name);
記事「HoareRulesの実行フレームワーク」の「フレームワークの仕事」のところを見れば、これだけでも仕事ができるはず(commandは不要とも言える)。
別な考え方としては、「コーラブル実体を取得する必要はない」点に注目するのもある。ほんとに欲しいのは:
- 名前からコーラブルの存在確認ができること(検証のとき)
- 名前と引数配列によりコーラブルを呼び出せること(評価・実行のとき)
// 存在確認
public boolean hasCallable(String name);
public boolean hasFunction(String name);
public boolean hasPredicate(String name);
public boolean hasCommand(String name);// 呼び出し
public Object call(String name, Object[] args) throws Exception;
こっちの方法だと、実行フレームワークはコーラブル実体に触れないので、CallableLibrary内部にコーラブルコードをインラインコーディング(埋め込み)で書き込んだりできて、安直さが増す。
public Object call(String name, Object[] args) throws Exception {
if (name.equals("foo")) {
// fooのコード
} else if (name.equals("bar")) {
// barのコード
} else {
throw new CallableNotFoundException(name);
}
}
絶対必須ではないのだけど、CallableLibraryはコレクション(モノの集まり)だから、メンバー列挙があるほうがいいかも。いまどきのメンバー列挙はイテレータでしょう。が、例えば、lib.allPredicates() で述語が列挙されてもうれしくない。なぜなら、コーラブル実体はメタデータを(名前さえも)持たないので正体不明。そもそも「実行フレームワークはコーラブル実体に触れない」方式とは相容れないし。
名前(文字列)を列挙する、Iterable<String> callableNames(), functionNames(), predicateNames(), commandNames() あたりが妥当かな。まー、実行時にメンバー列挙が必要な状況になるまでは入れなくていいけど(ミニマリスト発想、別名手抜き主義)。