Facebook PHP-sdk ( https://github.com/facebook/php-sdk/ )をラップして拡張するモジュール (フレームワーク固有) を作成したいと考えています。私の問題は、クラスをうまく編成する方法です。
詳細に入ると、Facebook PHP-sdk は 2 つのクラスで構成されます。
- BaseFacebook - sdk が行うすべてのものを含む抽象クラス
- Facebook - BaseFacebook を拡張し、デフォルトのセッション使用法で親抽象永続性関連メソッドを実装します
ここで、追加する機能がいくつかあります。
- フレームワーク セッション クラスと統合された Facebook クラスの置換
- API 呼び出しを実行する短縮メソッド、私は主に (BaseFacebook::api() を介して) 使用します。
- 承認方法なので、毎回このロジックを書き直す必要はありません。
- パラメータとして渡される代わりに、フレームワーククラスから吸い上げられた構成
- キャッシング、フレームワーク キャッシュ モジュールと統合
非常に正常に見えない継承が多すぎるため、何かが非常に間違っていることはわかっています。すべてを 1 つの「複雑な拡張」クラスにラップすることも、多すぎるように思えます。一緒に動作するクラスはほとんどないはずだと思いますが、次のような問題が発生します。キャッシュクラスが実際に BaseFacebook::api() メソッドを拡張してオーバーライドしない場合、短縮形と認証クラスはキャッシュを使用できません。
たぶん、ある種のパターンがここにあるでしょうか?これらのクラスとその依存関係をどのように整理しますか?
編集 04.07.2012
トピックに関連するコードのビット:
これは、Facebook PHP-sdk の基本クラスの方法です。
abstract class BaseFacebook {
// ... some methods
public function api(/* polymorphic */)
{
// ... method, that makes api calls
}
public function getUser()
{
// ... tries to get user id from session
}
// ... other methods
abstract protected function setPersistentData($key, $value);
abstract protected function getPersistentData($key, $default = false);
// ... few more abstract methods
}
通常、Facebook クラスはそれを拡張し、それらの抽象メソッドを実装します。私はそれを私のsubtitudeに置き換えました - Facebook_Session クラス:
class Facebook_Session extends BaseFacebook {
protected function setPersistentData($key, $value)
{
// ... method body
}
protected function getPersistentData($key, $default = false)
{
// ... method body
}
// ... implementation of other abstract functions from BaseFacebook
}
わかりました、次に、省略形のメソッドと構成変数を使用してこれをさらに拡張します。
class Facebook_Custom extends Facebook_Session {
public function __construct()
{
// ... call parent's constructor with parameters from framework config
}
public function api_batch()
{
// ... a wrapper for parent's api() method
return $this->api('/?batch=' . json_encode($calls), 'POST');
}
public function redirect_to_auth_dialog()
{
// method body
}
// ... more methods like this, for common queries / authorization
}
これが単一のクラス(承認/短縮メソッド/構成)にとって多すぎないかどうかはわかりません。次に、別の拡張レイヤー - キャッシュがあります。
class Facebook_Cache extends Facebook_Custom {
public function api()
{
$cache_file_identifier = $this->getUser();
if(/* cache_file_identifier is not null
and found a valid file with cached query result */)
{
// return the result
}
else
{
try {
// call Facebook_Custom::api, cache and return the result
} catch(FacebookApiException $e) {
// if Access Token is expired force refreshing it
parent::redirect_to_auth_dialog();
}
}
}
// .. some other stuff related to caching
}
これでかなりうまくいきます。Facebook_Cache の新しいインスタンスにより、すべての機能が提供されます。Facebook_Cache は api() メソッドを上書きするため、Facebook_Custom の簡易メソッドはキャッシュを使用します。しかし、ここに私を悩ませているものがあります:
- 継承しすぎだと思います。
- Facebook_Cache クラスの拡張で api() メソッド ループを回避するために、'parent:api' の代わりに 'Facebook_Custom::api' を指定しなければならなかった方法を見てください。
- 全体的に雑で醜い。
繰り返しますが、これは機能しますが、これをよりクリーンでスマートな方法で行うパターン/方法について尋ねているだけです。