1

可能な限りOOPコードの設計を改善したいと思っていますが、この問題に悩まされています。

たとえば、ソーシャルネットワーキングサイトで、ユーザーのすべての友達のプロファイルを取得したいとします。だから私はテーブルFriendshipsとを持っていProfilesます。そして、私はクラスFriendsとを持っていますProfile

Friendsユーザーの友情を処理するクラスであり、Friends::getFriendsProfiles()すべてのユーザーの友達のプロファイルをフェッチして返す関数であるとします。

だから私の関数のFriends::getFriendsProfiles()中で私はどちらかを行うことができます

  1. テーブル結合(例SELECT * FROM Friends LEFT JOIN Profiles ON Friends.user2 = Profile.userId WHERE Friends.user1 = :userid)、または

  2. 友達のユーザーIDを取得し、Profile友達IDごとにオブジェクトを作成し$profile->getProfile($friendid)、クエリ(SELECT * FROM Profiles WHERE userId = $friendid)を実行して友達のプロファイルを取得する呼び出しを行うだけです。次に、すべての友達のProfileオブジェクトのセットを返します。

オプション1短所:私の友情クラスはプロファイルについて知っています。また、プロファイルが返される方法を変更する必要がある場合(たとえば、各プロファイルオブジェクトに別のプロパティを追加したい場合)、2つの異なる場所で変更する必要があります。

オプション2の短所: 1つのクエリ(O(1)で実行する必要があると思いますか?)を作成する代わりに、O(n)になります。ここで、nはユーザーの友達の数です。

しかし、オプション2は非常にクリーンで、緩く結合されています。どのオプションを選択する必要がありますか?

4

2 に答える 2

2

私は間違いなくオプション1を使用し、1つのクエリのみを使用します。クラスは、コンストラクターが配列を処理できるかどうかFriendsについてあまり知らないようにする必要があります。Profilesあなたは次のようなことをすることができます:

SELECT Profiles.*
FROM Friends
LEFT JOIN Profiles ON Friends.user2 = Profile.userId
WHERE Friends.user1 = :userid

次に、ループ内で:

$profiles = array()
while ($data = mysqli_fetch_assoc($result)){
    $profiles[] = new Profile($data);
}

Profileおそらくよりクリーンな解決策の1つは、それをクラスのメソッドにすることです。

Profile::getFriendsProfiles()

ループ:

$profiles = array()
while ($data = mysqli_fetch_assoc($result)){
    $profiles[] = new self($data);
}

からのコンストラクタは次のProfileようになります。

function __constructor(array $data = null)
{
    if (null !== $data) {
        // fill properties
        $this->id_profile = $data['id_profile']; // example
        ...
    }
}

SQLコードが別のオブジェクトにあるとよいでしょうTable Data Gateway。OOPを本当に改善したくない場合は、ソフトウェアデザインパターンについて読んでください。ここからMartinFowlersのサイトから始めることができます。

于 2013-01-20T02:09:03.720 に答える
1

オプション1短所:私の友情クラスはプロファイルについて知っています。また、プロファイルが返される方法を変更する必要がある場合(たとえば、各プロファイルオブジェクトに別のプロパティを追加したい場合)、2つの異なる場所で変更する必要があります。

ドメインオブジェクトには、当然、何らかの結合があります。これは、モデリングしているシステムの現実です。これは、友情とプロファイルの間の結合の問題ではなく、ビジネス層とデータ層の間の緊密な結合の問題です。データマッパー、ファインダークラスなどがあり、ビジネスオブジェクトの永続性を無視した場合、このような変更はそれほど重要ではありません。

2番目のオプションを使用すると、n+1選択の問題が発生します。この場合、デカップリングを検討できるより重要な領域がある場合、パフォーマンスを犠牲にすることはありません。

于 2013-01-20T02:07:25.170 に答える