高级PHP开发人员在哪里找到方法getActiveEntries()?

时间:2012-10-31 02:34:44

标签: php oop

分离关注或单一责任原则

“可能已经有你的答案”的问题下拉列表中的大多数问题只能解释“理论”,而不是回答我这个简单问题的具体例子。

我想要完成的事情

我有一个名为GuestbookEntry的类,它映射到名为“guestbook”的数据库表中的属性。很简单!

最初,我有一个名为getActiveEntries()的静态方法,它检索数据库中包含条目的所有GuestbookEntry对象的数组。然后在学习如何正确设计php类时,我学到了两件事:

  1. 不希望采用静态方法。
  2. 分离关注
  3. 我的问题:

    处理问题分离,如果GuestbookEntry类只负责管理单个留言簿条目,那么这个getActiveEntries()方法应该去哪里?我想学习绝对正确的方法来做到这一点。

3 个答案:

答案 0 :(得分:1)

我猜这个问题实际上有两个项目:

  1. 正如@duskwuff指出的那样,静态方法本身没有任何问题;如果你知道他们的警告(例如“Late Static Binding”)和限制,他们只是另一种工具。但是,您对数据库交互建模的方式确实会影响关注点的分离,例如单元测试。

  2. 由于不同的原因,没有“绝对正确的方式”来做持久性。其中一个原因是每种解决方法都有不同的权衡;哪个更适合你的项目很难说。另一个重要原因是语言不断发展,因此新的语言功能可以改进框架处理事物的方式。因此,您可能需要考虑使用关系数据库的不同方法来考虑OO持久性,而不是寻找完美的方法:

    • 使用Active Record模式。到目前为止你所做的事情看起来像是Active Record风格,所以你可能会发现它很自然。活动记录具有易于掌握的优点,但往往与DB紧密耦合(当然这取决于实现)。这从关注点分离视图中可能很糟糕,并且可能使测试复杂化。
    • 使用ORM(例如DoctrinePropel)。在这种情况下,大多数艰苦的工作都是由框架完成的(BD映射,外键,级联删除,一些标准查询等),但是你必须适应框架规则(例如我记得有很多问题。方式Doctrine 1处理项目中的层次结构.AFAIK这个问题在Doctrine 2中得到了解决。
    • 推出自己的框架,以满足您的项目需求和编程风格。这显然是一项耗时的任务,但你学到了很多东西。
  3. 作为一般经验法则,我尝试让我的域模型尽可能独立于DB之类的东西,主要是因为单元测试。在编程时,单元测试应该一直在运行,因此它们应该快速运行(我在编程时始终保持一个终端打开,并且在应用更改后我不断切换到它来运行整个套件)。如果您必须与数据库进行交互,那么您的测试将变得缓慢(任何中型系统都将具有100或200个测试方法,因此这些方法应该以毫秒的顺序运行才有用)。

    最后,有不同的技术可以处理与DB通信的对象(例如模拟对象),但一个好的建议是在域模型和数据库之间始终有一个层。这将使您的模型更灵活,更易于测试。

    编辑:我忘了提及DAO方法,也在@MikeSW回答中说明。

    HTH

答案 1 :(得分:0)

不要再猜测自己了。静态方法getActiveEntries()是解决此问题的完美合理方法。

您正在寻找的“企业级”解决方案可能涉及创建GuestbookEntryFactory对象,配置它以获取活动条目以及执行它的内容。这太傻了。静态方法是一种工具,对他们来说这是一个完全合适的工作。

答案 2 :(得分:0)

GetActiveEntries应该是存储库/ DAO的方法,它将返回一个GuestBookEntry数组。当然,该存储库可以实现一个接口,因此您可以轻松进行测试。

我不同意为此使用静态方法,因为它显然是持久性访问问题。 GuestBookEntry应该只关心'业务'功能,而不关心db。这就是使用存储库有用的原因,该对象将业务层桥接到数据库层。

编辑我的php生锈但你明白了。

public interface IRetrieveEntries
{
    function GetActiveEntries();
}

public class EntriesRepository implements IRetrieveEntries
{
    private $_db;
    function __constructor($db)
    {
       $this->_db=$db;
     }

    function GetActiveEntries()
    {
      /* use $db to retreive the actual entries
       You can use an ORM, PDO whatever you want 
         */
      //return entries;
    }

  }

您将在需要访问功能的所有位置传递接口,即不将代码耦合到实际存储库。您也将使用它进行单元测试。关键是你将实际数据访问封装在GetActiveEntries方法中,应用程序的其余部分将不知道数据库。

关于存储库模式,您可以阅读some tutorials我写过(忽略使用的C#,概念在任何语言中都有效)