2

我正在尝试为数据模型的存储提出一个好的设计。语言是 python,但我想这是相当不可知的。

目前我设想了三种可能的策略:

对象数据库

数据模型是一个对象网络。当我创建它们时,我将它们指定为持久性对象的后代。例子:

class Tyres(PersistentObject):
    def __init__(self,brand):
        self._brand = brand

class Car(PersistentObject):
    def __init__(self,model):
        self._model = model
        self._tyres = None
    def addTyres(self,tyres):
        self._tyres = tyres
    def model(self):
        return model

客户端代码不知道持久性,它像在内存中一样操作对象,并且持久性对象在客户端代码不知道的情况下处理所有事情。检索可以通过数据库对象的键控查找来完成。这是 Zope 对象数据库(以及许多其他方法)使用的方法。优点是惰性检索,并且仅对已更改的对象进行更改,而不检索未触及的对象。

搁置物件

上面给出的数据模型在内存中表示,但随后使用数据库将数据作为整体实体推送或拉取。例如:

 car = Car("BMW")
 tyres = Tyres("Bridgestone")
 car.setTyres(tyres)
 db.store(car)

这就是基于泡菜的解决方案所做的。在某种意义上,它与前面的解决方案类似,唯一的区别是将对象存储为单个包,然后将其作为单个包再次检索。

立面

具有便利方法的单个数据库类。客户端代码从不处理对象,只处理 id。例子

class Database:
     def __init__(self):
         # setup connection

     def createCar(self, model):
         # creates the car, returns a numeric key car_id

     def createTyresForCar(self, car_id, brand):
         # creates the tyres for car_id, returns a numeric id tyres_id

     def getCarModel(self, car_id):
         # returns the car model from the car identifier
     def getTyresBrand(self, car_id, tyre_id):
         # returns the tyre brand for tyres_id in car_id.
         # if tyres_id is not in car_id, raises an error.
         # apparently redundant but it's not guaranteed that
         # tyres_id identifies uniquely the tyres in the database.

这个解决方案颇有争议。数据库类可以有很多职责,但我有种感觉,这就是 SOAP 中使用的哲学:您不能直接操作对象,您可以查询远程服务器的对象属性。在没有 SQL 的情况下,这可能是关系数据库的接口:db.createTable()db.insert()db.select()。SQL 对此进行了简化以获得非常简单的数据库接口,db.query(sql_string)代价是语言 (SQL) 解析和执行。您仍然可以对您感兴趣的数据模型的子部分进行操作,而无需触及其他部分。

我想问问你对这三种设计的看法,尤其是第三种。什么时候是一个好的设计,如果有的话?

反转逻辑

这是我在 MediaWiki 代码上看到的。而不是有类似的东西

 db.store(obj)

他们有

 obj.storeOn(db)

编辑:我展示的示例数据模型有点简单。我的真正目标是创建一个基于图形的数据模型(如果有人想参与该项目,我将很荣幸)。第三种解决方案让我担心的是,它强烈地封装了写入的数据模型(与内存中的数据模型相反)并屏蔽了后端,但它有爆炸的风险,因为只有一个中心类暴露了所有方法。老实说,我不喜欢第三种情况,但我认为它是一种可能的解决方案,所以我想把它放在问题的盘子上。它可能有好处。

编辑 2:添加了反转的逻辑条目

4

2 回答 2

1

第一个设计与领域驱动设计最兼容。使实现持久性对对象完全私有意味着您可以使用该对象而无需考虑其关系表示。对象只公开与其特定领域行为相关的方法,而不是低级别的 CRUD 操作,这会很有帮助。高级方法是您要提供给该对象的消费者的唯一 API 协定(即,您不希望任何人都能够删除汽车)。您可以实现复杂的数据关系,并且只需在一处进行编码。

第二种设计可以与访问者模式一起使用。汽车对象知道它的哪些部分需要被持久化,但它没有与数据库的连接。因此,您将汽车对象传递给数据库连接实例。在内部,数据库知道如何调用它给定的对象。大概汽车实现了一些“db-callable”接口。

第三种设计有助于实现适配器模式。每个数据库品牌的 API 都不同,每种 SQL 风格也略有不同。如果你有一个用于普通数据库操作的通用 API,你可以封装这些差异,并换出一个知道如何与各自品牌的数据库通信的不同实现。

于 2009-08-23T05:57:46.497 回答
0

很难说,因为你的例子显然是人为的。

需要根据您的数据模型更改的频率来做出决定。恕我直言,汽车并不经常收集新零件。所以我会在数据库中使用您希望建模的所有项目的静态模型,然后将所有这些项目链接在一起,但这对于您实际所做的可能是错误的。

我建议您与我们讨论您需要建模的实际数据。

于 2009-08-23T05:52:55.773 回答