dongliuxia9495 2017-08-13 03:23
浏览 58
已采纳

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

My companys objects need security from programmers screwing up relationships so we require username be tied to each object. We would still like to refactor and clean up legacy code and have a structure around this. Our on going argument is some believe those CRUD like actions on a object should be called by a user in example

$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);

Is throwing in 50 methods or so for User object to much or should things be broke up per basis and pass in a username or immutable user object? Example below

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

1条回答 默认 最新

  • dou91736 2017-08-13 04:41
    关注

    Stuffing a lot of functionality into your business objects to handle interaction with other objects can get ugly fast, especially if you are dealing with complex relationships and logic.

    The first step beyond that kind of architecture is typically implementing service classes to facilitate the interaction between your objects.

    Consider the following:

    <?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);
        }
    }
    

    You create an abstract class with the common functions you need, and to verify and hold a reference to your user. All of your services that need to be based around a user instance extend this class and facilitate interaction between the user object and the related objects. All of your logic around permissions goes into these service classes. This is a lot more maintainable than stuffing all of that into the business objects.

    This approach can take you far. OO astronauts may tell you to go look at design patterns like the Mediator pattern for this kind of thing, and that can definitely work well, but there is always a trade off between complexity and ease of use. For most CRUD heavy applications, I find this service based approach to be the sweet spot.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 名为“Product”的列已属于此 DataTable
  • ¥15 安卓adb backup备份应用数据失败
  • ¥15 eclipse运行项目时遇到的问题
  • ¥15 关于#c##的问题:最近需要用CAT工具Trados进行一些开发
  • ¥15 南大pa1 小游戏没有界面,并且报了如下错误,尝试过换显卡驱动,但是好像不行
  • ¥15 没有证书,nginx怎么反向代理到只能接受https的公网网站
  • ¥50 成都蓉城足球俱乐部小程序抢票
  • ¥15 yolov7训练自己的数据集
  • ¥15 esp8266与51单片机连接问题(标签-单片机|关键词-串口)(相关搜索:51单片机|单片机|测试代码)
  • ¥15 电力市场出清matlab yalmip kkt 双层优化问题