“可能已经有你的答案”的问题下拉列表中的大多数问题只能解释“理论”,而不是回答我这个简单问题的具体例子。
我有一个名为GuestbookEntry的类,它映射到名为“guestbook”的数据库表中的属性。很简单!
最初,我有一个名为getActiveEntries()的静态方法,它检索数据库中包含条目的所有GuestbookEntry对象的数组。然后在学习如何正确设计php类时,我学到了两件事:
处理问题分离,如果GuestbookEntry类只负责管理单个留言簿条目,那么这个getActiveEntries()方法应该去哪里?我想学习绝对正确的方法来做到这一点。
答案 0 :(得分:1)
我猜这个问题实际上有两个项目:
正如@duskwuff指出的那样,静态方法本身没有任何问题;如果你知道他们的警告(例如“Late Static Binding”)和限制,他们只是另一种工具。但是,您对数据库交互建模的方式确实会影响关注点的分离,例如单元测试。
由于不同的原因,没有“绝对正确的方式”来做持久性。其中一个原因是每种解决方法都有不同的权衡;哪个更适合你的项目很难说。另一个重要原因是语言不断发展,因此新的语言功能可以改进框架处理事物的方式。因此,您可能需要考虑使用关系数据库的不同方法来考虑OO持久性,而不是寻找完美的方法:
作为一般经验法则,我尝试让我的域模型尽可能独立于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#,概念在任何语言中都有效)