实体(如用户)是否应该存储自己的数据?

时间:2014-11-23 02:08:55

标签: php oop

我最近在Java中学习了OOP,并且我正在尝试实现我在PHP用户系统中学到的知识。

这是我目前的用户类

class User {
    public $id;
    public $session;
    public $email;
    public $lastVisit;

    public function __construct($id) {
        $conn = new Conn();
        $array = $conn->ExecuteCmdArray("SELECT * FROM user WHERE id = '".$id."'");
        $this->session = $array['session'];
        $this->email = $array['email'];
        $this->id = $array['id'];
        $this->lastVisit = $array['last_visit'];
    }
}

^哦,我应该执行一个SQL来检索数据吗?

然而,在看了一些在线示例之后,我查看了他们的User课程,但意识到其中只有登录等功能存在。类中的属性也只是用户名和密码。

它不应该包含所有其他变量,例如gender,real_name吗?在我看来,用户类不存储userdata,但它仅用于登录和填充。

这是PHP中的User类通常如何工作 - 这意味着我的User类错误地完成了吗?

2 个答案:

答案 0 :(得分:1)

设计User类没有正确方法。这取决于程序员的喜好,需求,技能以及他对OOP和软件设计的理解。


关注点分离

  

哦,我应该执行一个SQL来检索数据吗?

不推荐。良好的软件设计是关于创建分离的自包含组件。

在设计软件时,开箱即用并将自己置于另一个开发人员的角色中是一种很好的做法。所以如果你有一个User对象而不知道幕后会发生什么。 您是否希望它能够触发数据库查询?不,用户不负责查询数据库。

OOP也是关于可重用性。如果我们举个例子:如果我将你的User课程投入到我自己的项目中。它可能会破裂。您正在类中直接实例化数据库连接。如果我有其他处理数据库访问的方法怎么办?一切都会破坏。

Seperation of Concerns是此处的关键字。只要有可能,你就应该坚持下去。

  

然而,在看了一些在线示例之后,我查看了他们的User类,但意识到其中只存在登录等功能。

问自己这些问题:

  1. User是否应该知道如何登录?他的会话是如何管理的,或者这可能是另一项服务的任务?
  2. 如果你不了解课程,你会期望User可以登录吗?
  3. 你知道吗通过考虑课程的关注点,您可以在设计出现之前消除设计中的问题

    我不希望我的用户知道如何登录。我宁愿期望我的应用程序的服务明确专用于该任务,以处理它。

    <?php
    
    $authentication = new UserAuthenticationService();
    $authentication->attemptLogin('username', 'password');
    
    if( $authentication->check() )
    {
        $user = $authentication->getUser();
        echo $user->username();
    }
    

    构建应用程序,以便您的类尽可能自包含,并且只具有它们真正需要的依赖项。它是成功软件设计的关键之一。


    关于您的域名

      

    类中的属性也只是用户名和密码。

         

    它不应该包含所有其他变量,例如gender,real_name吗?在我看来,用户类不存储用户数据,但它只用于登录和填充。

    这取决于您的用例。如果您正在创建一个用户可以匿名发布上次宿醉故事的应用程序,那么为什么还需要真名?

    如果您正在创建一些企业商务应用程序,您可能希望存储该数据。 您的对象所持有的数据是由您定义的,仅由您定义

    让我们的宿醉网站更进一步。我只想从我的用户那里得到最少的信息,所以它看起来像这样。

    <?php 
    
    class User {
    
        private $username;
        private $email;
        private $gender;
    
        public function __construct( $username )
        {
            $this->username = $username;
        }
    
        public function username()
        {
            return $this->username;
        }
    
        //[...]
    
        public function setUsername( $username )
        {
            $this->username = $username;
        }
    
        //[...]
    
    }
    

    我甚至不会将密码存储在我的用户类中,因为我不想这样做。我决定我会有一些持久性管理器和一个处理这些管理器的身份验证管理器。

    <?php
    
    $authentication     = new UserAuthenticationService();
    $persistanceMapper  = new UserPersistanceMapper();
    
    $authentication->attemptLogin('username', 'password');
    
    if( $authentication->check() )
    {
        // Let's rename the User just for fun
        $user = $authentication->getUser();
        $user ->setName('Thomas');
        $persistanceMapper->persist( $user );
    }
    

    这真的取决于你的喜好。但我首先想要表明的是,我的对象只做负责应该做 p>

    • User能够改变它自己的状态,并能够向我提供它的数据。但他对数据库一无所知。
    • UserPersistanceMapper知道如何持久保存用户(在数据库中或任何地方)
    • UserAuthenticationService知道如何处理用户会话

    我没有处理所有内容的 。相反,我们在这里有自包含的对象,它们在一起处理我们的东西。


    这一切都取决于你的喜欢

      

    这是PHP中的User类通常如何工作 - 这意味着我的User类错误地完成了吗?

    最终没有权利也没有错。如果你想这样滚动,那就去吧!如果你不考虑设计,你可能会获得初始时间提升。对于不难维护的简单项目,这可能没问题。

    当您构建更大的应用程序时,反思自己的代码总是好的。

    请记住:

    • 在设计应用程序时尝试将自己置于其他开发人员的位置
    • 开始编码
    • 之前,可视化对象如何相互连接
    • 尝试尽可能保持您的课程自包含(从外部传递最终的依赖关系)
    • 完成任务!如果你无法想出一个干净的方法来做某件事:让它运作稍后重构一下。但请确保您有定期重构周期。不要把东西放在一边思考&#34;是的......不管我以后做什么&#34;。你会以这种方式结束很多Code Smells

    进一步阅读

答案 1 :(得分:0)

您创建用户类的方式的缺点是,当您管理用户列表或处理大量用户的事情时,您必须移动所有这些额外的用户数据,而有时您只需要它的id和电子邮件。

我们可以使用两个或更多课程!在你的例子中,将有一个最小的User类,具有非常小的属性和函数,以及一个Full_User类,扩展第一个类。

class User {
    public $id;
    public $email;
    public function __construct($array) {
        $this->email = $array['email'];
        $this->id = $array['id'];
    }
}

class Full_User {
    public $session;
    public $lastVisit;
    public function __construct($array) {
        $this->session = $array['session'];
        $this->lastVisit = $array['last_visit'];
        parent::__construct($array);
    }
}

我建议将属性数组传递给构造函数而不是执行语句。它允许从一些其他数据创建对象,然后创建数据库。

$id = 12;
$conn = new Conn();
$minimal_array = $conn->ExecuteCmdArray("SELECT id,mail FROM user WHERE id = '".$id."'");
$full_array = $conn->ExecuteCmdArray("SELECT id,mail,session,lastVisit FROM user WHERE id = '".$id."'");
$user_for_listing = new User($minimal_array);
$full_user = new Full_User($full_array);