Php 在web应用程序oop中,巨型用户对象是否应该具有接收用户的动作或动作类?

Php 在web应用程序oop中,巨型用户对象是否应该具有接收用户的动作或动作类?,php,oop,architecture,domain-driven-design,Php,Oop,Architecture,Domain Driven Design,我公司的对象需要程序员的安全保护,因为程序员破坏了关系,所以我们要求用户名绑定到每个对象。我们仍然希望重构和清理遗留代码,并有一个围绕这一点的结构。我们正在讨论的论点是,一些人认为,在示例中,对象上类似CRUD的操作应该由用户调用 $user = new User('usernameExample'); $profileData = $user->getProfile(12313); echo json_encode($profileData); $ID = $user->creat

我公司的对象需要程序员的安全保护,因为程序员破坏了关系,所以我们要求用户名绑定到每个对象。我们仍然希望重构和清理遗留代码,并有一个围绕这一点的结构。我们正在讨论的论点是,一些人认为,在示例中,对象上类似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);
是否为用户对象添加了50个左右的方法太多了,还是应该将每个方法分解,并传入一个用户名或不可变的用户对象?下面的例子

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

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

这种体系结构之外的第一步通常是实现服务类以促进对象之间的交互

考虑以下几点:

<?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宇航员可能会告诉你,对于这类事情,去看看设计模式,比如中介模式,这肯定可以很好地工作,但在复杂性和易用性之间总是有一个权衡。对于大多数CRUD严重的应用程序,我发现这种基于服务的方法是最佳选择。

使用实体和数据映射器模式。请看:【域驱动设计】与此有什么关系?我希望有ddd经验的人能给出他们的方法。我们最大的问题之一是,大型类有许多公共方法和2个公共变量,如果一个类以一种方式调用对象,另一个类以另一种方式调用对象,那么如何进行简单调用就会丢失。最近,我非常喜欢创建控制器的想法,这些控制器只需调用单个域函数或微服务函数即可返回某些对象并结束事务。DDD会告诉您需要某种数据访问层,例如datamapper抽象,然后调用存储库来连接该层。