1

我希望尽可能地改进我的 OOP 代码设计,但我被困在这个问题上。

例如,我想在社交网站中获取用户所有朋友的个人资料。所以我有桌子FriendshipsProfiles. 我有课FriendsProfile.

让我们Friends成为处理用户友谊的类,并Friends::getFriendsProfiles()成为获取和返回所有用户朋友的个人资料的函数。

所以在我的函数Friends::getFriendsProfiles()中,我可以做一个

  1. 表连接(例如SELECT * FROM Friends LEFT JOIN Profiles ON Friends.user2 = Profile.userId WHERE Friends.user1 = :userid),或

  2. Profile我可以只获取朋友的用户 ID,为每个朋友 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类的方法。

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,那么请阅读软件设计模式。您可以从 Martin Fowlers 的网站开始

于 2013-01-20T02:09:03.720 回答
1

选项 1 缺点:我的友谊班知道个人资料。当我需要更改配置文件的返回方式时(例如,我想为每个配置文件对象添加另一个属性),我需要在 2 个不同的地方进行更改。

领域对象自然会有一些耦合。这只是您正在建模的系统的现实。这与其说是友谊和个人资料之间的耦合问题,不如说是业务层和数据层之间的紧密耦合问题。如果您有一个数据映射器、查找器类等并且使您的业务对象持久性无知,那么像这样的更改应该不会太重要。

如果您使用第二个选项,您会遇到n+1 选择问题。在这种情况下,当有更重要的领域可以考虑解耦时,我不会牺牲性能。

于 2013-01-20T02:07:25.170 回答