【问题标题】:which data model storage strategy? [closed]哪种数据模型存储策略? [关闭]
【发布时间】:2009-08-23 21:15:23
【问题描述】:

我正在尝试为数据模型的存储提出一个好的设计。语言是 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)

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

立面

具有便利方法的单个数据库类。客户端代码从不处理对象,只处理 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:添加倒置逻辑入口

【问题讨论】:

    标签: database language-agnostic data-modeling


    【解决方案1】:

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

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

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

    【讨论】:

    • 我担心第三个最终会超出可管理性。
    • 我不会单独使用第三种策略。使用适配器使 SQL 生成更容易,然后将该计划与前两个之一结合使用。
    【解决方案2】:

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

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

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

    【讨论】:

    • 我正在实现的实际数据模型是图数据模型。当前基于图的数据模型不符合我的需求,所以我自己实现了一个。
    • 我还没有决定是应该让客户端代码直接操作对象还是通过标识符通过数据库接口操作对象。
    • 嗯,一般来说,最好让类根据外部数据自行操作。但是,我仍然不清楚你在做什么,所以我真的不能说任何有用的东西。也许其他人可以:)
    猜你喜欢
    • 1970-01-01
    • 2021-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-15
    • 1970-01-01
    • 2019-07-23
    • 2020-06-30
    相关资源
    最近更新 更多