class Bookmark { |
class ActiveRecordTestCase extends UnitTestCase { // ... function testSave() { $link = Bookmark::add( ‘http://blog.casey-sweat.us/’, ‘My Blog’, ‘Where I write about stuff’, ‘php’); $link->description = ‘Where I write about PHP, Linux and other stuff’; $link->save(); $link2 = Bookmark($link->getId()); $this->assertEqual($link->getId(), $link2->getId()); $this->assertEqual($link->created, $link2->updated); } } |
现在,让我们转向如何处理删除操作。在16章――数据地图模式中有一个例子,但是你可以方便的从insert()和update()方法中推导出来。
总结
正如大多数初次尝试由面向过程到面向对象编程所表现的那样,动态记录模式在概念与执行上都较为简单。将你所有的SQL代码都组织在一起是非常好的,并且动态记录模式给了你一个非常好的将业务逻辑与数据库操作相结合来持续保存对象的方法。
本章的例子用了一个真实的数据库来开发测试代码。另一个测试简单数据库代码的方法是使用模拟对象(参见第6章)来模拟数据库连接。不幸的是,这个方法并是广泛有效。SQL是一个复杂的语言,模拟的每个语句都与数据库的细节实验密切相关。而用新建的,实际的表进行实验则令人觉得舒服得多,没有模拟SQL时的副作用了。
如果动态记录模式还有不利的方面,则是其复杂性了。一个动态记录类可能迅速的变大,就像一个块磁铁。例如,书签类现在只有一个findById()方法,但你很有可能想要findByDescription()方法,或是findByGroup(),findRecentlyCreated()等方法。
另一个问题是对象会变得“重复”,这在save()方法中可能会看到。例如,$link与$link2在实验用例表示的是不同的对象,但事实上它们都是指同一个书签ID。你可以用下面的实验来证明。
class ActiveRecordTestCase extends UnitTestCase { // ... function testSave() { // ... $this->assertNotIdentical($link, $link2); } } |
如果认为解决这个问题是重要的,你有可能要增加一个内部的注册机制(参见第五章)确保Bookmark(1)返回的所有对象的实例应是同一个对象。因为你实际上用的是new操作来建立一个对象而不是用工厂方法,作为一种实际的Active Record类,你应该将Bookmark修改为代理(参见11章)来真正解决这个问题。
另一个方面,Active Record模式被设计成一次处理一行记录的方式。这种模式是典型的”管理”式应用的界面,如编辑一篇文章,一个链接,一个注释等。但是大数的网页要处理的是多数据集或是多行数据,这正是我们下一章要讨论的主要内容――表数据网关模式。