PoEAA ch18 Registry
- Registry
- How It Works
- When to Use It
- Example: A Singleton Registry (Java)
- Example: Thread-Safe Registry
- 英語
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メソッド
- データのスコープ
- プロセス内グローバル
- スレッド内グローバル
- セッション内グローバル
- スコープが異なれば、実装も異なってくる
- が、staticメソッドを叩く人は、得られるデータのスコープを知っている必要はない
- シングルスレッドならSingleton Pattern使え
- プロセススコープ
- データをmutableなstaticフィールドで持っても実現できる
- が、置換不可能だからよしたほうがいい
- テストしたいとき困る
private static Registry soleInstance;
を1つ持つ感じRegistry::soleInstance->getFoo()
Registry::getFoo()
と書けるとなおよい
- プロセススコープ
- マルチスレッドならSingletonはやめておけ
- スレッド横断的にmutableなグローバル領域にアクセスするのは無謀
- 同期制御すれば不可能ではないが難しい
- immutableだったり、めったに変更されないデータならこの限りではない
- 合衆国の州のリストとか
- スレッド横断的にmutableなグローバル領域にアクセスするのは無謀
- 一般的なRegistryはスレッドスコープ
- 例: DBコネクション
- スレッドスコープの実装例
- 環境がスレッド別ストレージを提供している
- Javaの
ThreadLocal
(後述)
- Javaの
- スレッドをキーとする辞書で自前管理する
- 環境がスレッド別ストレージを提供している
- スコープによらず、Registryのインタフェースは変わらないことに注意
Registry::getDbConnection()
- プロセススコープだろうがスレッドスコープだろうが変わらない
- セッションスコープでも同じ
- セッションIDをキーとする辞書で管理
- …をスレッドスコープの辞書に入れることも
- スレッドスコープのデータにstaticメソッドでアクセスするとパフォーマンス問題あるかも
- その場合はスレッド別インスタンスに直接アクセスしてボトルネックを解消せよ
- Registryが複数あるケース
- システムのレイヤーや実行コンテキストで区切られるのが普通
- 著者としては、どう使われるかで分けるのが好み
When to Use It
- 濫用するな
- 基本はあくまでオブジェクト間相互作用
- Registryを使わない方法
- Registryの問題
- 管理するデータが追加されるたびに、Registryクラスを変更しないといけない
- これを嫌って、グローバルデータの保持には汎用の辞書クラスを使う人もいる
- 管理するデータが追加されるたびに、Registryクラスを変更しないといけない
- 著者見解としては、汎用辞書ではなく、明示的なRegistryクラスを作るほうが良い
- グローバルはグローバル。無実を証明しない限りは罪であることを忘れぬよう
Example: A Singleton Registry (Java)
Example: Thread-Safe Registry
class ThreadLocalRegistry ... private static ThreadLocal instances = new ThreadLocal(); public static ThreadLocalRegistry getInstance() { return (ThreadLocalRegistry) instances.get(); }
- こんな感じにスレッドローカル変数を作れる
英語
- asylum
- 亡命