在web应用程序中oop巨型用户对象应该有动作或动作类接收用户吗?

时间:2017-08-13 03:23:06

标签: php oop architecture domain-driven-design

我的公司对象需要安全程序员搞砸关系,因此我们需要将用户名绑定到每个对象。我们仍然希望重构和清理遗留代码,并围绕此构建一个结构。我们正在进行的论证是有些人认为那些CRUD就像对象上的动作应该由用户在例子中调用

$user = new User('usernameExample');
$profileData = $user->getProfile(12313);
echo json_encode($profileData);
$ID = $user->createProfile($_POST);
$user->updateProfile($_POST);
$user->refreshProfile(12321394);
$user->deleteProfile(234242);

$user = new User('usernameExample');
$batches = $user->getGroupList();
$user->updateGroup($_POST);
$user->deleteGroup(23242);
$newBatchID = $user->createGroup();

$user = new User('usernameExample');
$user->addSubuser($_POST);
$user->deleteSubuser('usernameExample');
$user->updateSubuser($_POST);
$user->getSubusers();

$user new User('usernameExample');
$user->updateSetting($_POST);

为User对象投入50个左右的方法,或者每个基础上是否分解并传入用户名或不可变用户对象?以下示例

$userProfiles = new UserProfile('usernameExample');
$profileData = $userProfile->getProfile(12313);

1 个答案:

答案 0 :(得分:1)

将大量功能填充到业务对象中以处理与其他对象的交互可能会很快变得难看,尤其是在处理复杂的关系和逻辑时。

超越这种架构的第一步通常是实现服务类,以促进对象之间的交互。

请考虑以下事项:

<?php
/**
 * Class UserBasedServiceAbstract
 * Base class for our user based services. All services must be instantiated
 * with a valid user
 */
abstract class UserBasedServiceAbstract
{
    protected $user;

    /**
     * UserBasedServiceAbstract constructor.
     * @param User $user
     * @throws Exception
     */
    public function __construct(User $user)
    {
        if($user->isNew())
        {
            throw new Exception('User must be persisted before doing anything useful with it');
        }

        $this->user = $user;
    }

    /**
     * @param $message
     */
    protected function logAction($message)
    {
        $formattedMessage = (is_array($message)) ? json_encode($message):$message;
        echo 'User action for '.$this->user->getUsername().': '.$formattedMessage;
    }
}

class GroupService extends UserBasedServiceAbstract
{
    /**
     * Get a list of groups that the current user belongs to
     * @return array
     */
    public function getGroupList()
    {
        // We always have a reference to our user
        $userId = $this->user->getId();

        $this->logAction('Getting group list');

        //Fetch groups for user
        $groupList = [];

        return $groupList;
    }

    /**
     * Update the specified group if the current user has permission to do so
     * @param Group $group
     * @param array $params
     * @throws Exception
     */
    public function updateGroup(Group $group, array $params)
    {
        if(!$this->_userCanUpdateGroup())
        {
            throw new Exception('User does not have permission to update this group');
        }

        $this->logAction('Updating group');

        //update group
    }

    /**
     * Delete the specified group if the current user has permission to do so
     * @param Group $group
     * @throws Exception
     */
    public function deleteGroup(Group $group)
    {
        if(!$this->_userCanDeleteGroup($group))
        {
            throw new Exception('User does not have permission to delete this group');
        }

        $this->logAction('Deleting group');

        //delete group
    }

    /**
     * Determine whether or not the current user can delete the specified group
     * @param Group $group
     * @return bool
     * @throws Exception
     */
    private function _userCanDeleteGroup(Group $group)
    {
        //Maybe there is some logic we need to check on the group before we go further
        if(!$group->isDeletable())
        {
            throw new Exception('This group cannot be deleted');
        }

        // Implement some user-specific logic
        return ($this->user->hasPermission('group_admin') && $this->user->getKarma()>100);
    }

    /**
     * Determine whether or not the current user can update the specified group
     * @return bool
     */
    private function _userCanUpdateGroup()
    {
        // Implement some user-specific logic
        return ($this->user->hasPermission('group_moderator') && $this->user->getKarma()>50);
    }
}

您可以使用所需的常用功能创建一个抽象类,并验证并保留对用户的引用。所有需要基于用户实例的服务都会扩展此类,并促进用户对象与相关对象之间的交互。所有关于权限的逻辑都会进入这些服务类。这比将所有内容都填充到业务对象中要容易得多。

这种方法可以带你走远。 OO宇航员可能会告诉你去看看像这样的Mediator模式的设计模式,这肯定能很好地运作,但总是在复杂性和易用性之间进行权衡。对于大多数CRUD重型应用程序,我发现这种基于服务的方法是最佳选择。