Registry
A well-known object that other objects can use to find common objects and services.
- OOPでオブジェクトを検索するとき、通常は関連(association)しているオブジェクトを起点に行う
-
ある顧客
customer
の注文をすべて取得したいcustomer
と関連していれば、customer.getOrdersAll()
で手に入る
-
customer
オブジェクトが無い場合は?custmer
オブジェクトは、customerFinder.findById(customerId)
で手に入る
customerFinder
オブジェクトが無い場合は?-
Registryの出番
-
グローバルオブジェクトのようにふるまう
- 実際にそうかは別問題(後述)
-
How It Works
-
インタフェースと実装とは異なるよ、という話
-
インタフェースはstaticメソッド
- グローバルアクセス可能
-
メソッドがstaticだからといって、データまでもがstaticである必要性はない
- むしろ定数以外でstaticなデータは持たない
-
-
データのスコープ
- プロセス内グローバル
- スレッド内グローバル
- セッション内グローバル
- スコープが異なれば、実装も異なってくる
- が、staticメソッドを叩く人は、得られるデータのスコープを知っている必要はない
-
シングルスレッドならSingleton Pattern使え
-
プロセススコープ
- データをmutableなstaticフィールドで持っても実現できる
-
が、置換不可能だからよしたほうがいい
- テストしたいとき困る
private static Registry soleInstance;
を1つ持つ感じRegistry::soleInstance->getFoo()
Registry::getFoo()
と書けるとなおよい
-
-
マルチスレッドならSingletonはやめておけ
-
スレッド横断的にmutableなグローバル領域にアクセスするのは無謀
- 同期制御すれば不可能ではないが難しい
-
immutableだったり、めったに変更されないデータならこの限りではない
- 合衆国の州のリストとか
-
-
一般的なRegistryはスレッドスコープ
- 例: DBコネクション
-
スレッドスコープの実装例
-
環境がスレッド別ストレージを提供している
- Javaの
ThreadLocal
(後述)
- Javaの
- スレッドをキーとする辞書で自前管理する
-
-
スコープによらず、Registryのインタフェースは変わらないことに注意
Registry::getDbConnection()
- プロセススコープだろうがスレッドスコープだろうが変わらない
-
セッションスコープでも同じ
- セッションIDをキーとする辞書で管理
- …をスレッドスコープの辞書に入れることも
- スレッドスコープのデータにstaticメソッドでアクセスするとパフォーマンス問題あるかも
- その場合はスレッド別インスタンスに直接アクセスしてボトルネックを解消せよ
-
Registryが複数あるケース
- システムのレイヤーや実行コンテキストで区切られるのが普通
- 著者としては、どう使われるかで分けるのが好み
When to Use It
-
濫用するな
- 基本はあくまでオブジェクト間相互作用
-
Registryを使わない方法
-
広く使われるオブジェクトは明示的にメソッドの引数で渡す
-
デメリット: 自分が使わなくても下の層で使うから受け取らないといけない、というオブジェクトが現れる
- 【補】デメテルの法則違反
- 渡ってきたパラメータが9割がた使われないならRegistryを検討せよ
-
-
コンストラクタの引数で渡し、参照を保持する
- 使わなくても、コンストラクタの引数しか汚れない
-
-
Registryの問題
-
管理するデータが追加されるたびに、Registryクラスを変更しないといけない
- これを嫌って、グローバルデータの保持には汎用の辞書クラスを使う人もいる
-
-
著者見解としては、汎用辞書ではなく、明示的なRegistryクラスを作るほうが良い
-
識別子のあるメソッドを生やせる
- 何が使えるかソースコードを見ればわかる
- ドキュメント自動生成もできる
- 辞書を使うとありがちな「何のキーで何が得られるんだっけ」という混乱がない
- 型安全
-
静的なインタフェースで実装をカプセル化できる
- スコープ
-
- グローバルはグローバル。無実を証明しない限りは罪であることを忘れぬよう
Example: A Singleton Registry (Java)
- どうってことのないSingleton Pattern。略
- privateなインスタンスフィールドにstubインスタンスをセットするためのメソッドを生やしておく(テスト用)
Example: Thread-Safe Registry
class ThreadLocalRegistry ...
private static ThreadLocal instances = new ThreadLocal();
public static ThreadLocalRegistry getInstance() {
return (ThreadLocalRegistry) instances.get();
}
-
こんな感じにスレッドローカル変数を作れる
instances
自体はプロセススコープ。辞書みたいなヤツinstances.get()
すると、処理中のスレッドをキーに、スレッド固有のインスタンスを取り出してくれるinstances.set(何か)
すると、処理中のスレッドをキーに、スレッド固有のインスタンスに何かをセットしてくれる
英語
-
asylum
- 亡命