【问题标题】:Modeling Object Inheritance in a REST Api在 REST Api 中建模对象继承
【发布时间】:2012-11-02 07:05:22
【问题描述】:

问题

我有一个具有User 对象和Student 对象的应用程序。 一些用户是学生。所有学生都是用户。在数据库(基于 django-ORM)中,这表示为一个 Student 表,并带有一个指向 User 表的外键。

我正在尝试创建一个 REST API,并在 iOS 应用程序中创建一个对象层次结构来模拟这个 API。我在决定如何建模时遇到了麻烦。

当前的解决方案

我想出的最好的方法是:在 iOS 中有一个 User 模型,在 iOS 中有一个 Student 模型,它继承自 User 并使用更多属性对其进行扩展。然后,有一个从服务器接收 JSON 响应的方法,并根据字典创建或者UserStudent 模型。

最后,服务器需要总是给我最具体的类型。即,当我登录服务器时,它将决定我是学生还是普通用户,并返回正确的字典。

这是最好的方法吗?

这听起来有点复杂。但是我想到的任何其他建模方式,例如改变数据库的布局方式,给了我一个数据库不知道所有约束的设计。例如,Student 对象被允许拥有其他对象(例如,homework_paper)。我可以用User 对象而不是Student 对象的外键对此进行建模,并说Student 只是用户的扩展。但是数据库并没有强制要求homework_paper 必须由学生拥有。

有没有更好的方法来解决我错过的这个问题?

【问题讨论】:

    标签: objective-c django api oop rest


    【解决方案1】:

    没有任何内容表明您的 UI 层中的类需要与您的域类进行一对一匹配。就像您的域类不必完全遵循您的数据库表一样。

    您可以将您的 UI 层的类视为一组不同的类。使您的 UI 正常工作所需的类,或者需要在不损害域模型和/或数据库设计中的业务规则的情况下使用框架来发挥您的优势。

    您的用户界面类很可能是一个包含用户和学生域类的类。它将具有用户和学生域类的知识。然后由这个包装类来实例化用户或学生。

    另一种方法是将 User-Student 关系建模为“has a”关系而不是“is a”。毕竟,当用户不仅可以是学生,还可以是老师时,你会怎么做。例如,当一名教师参加了他所教的课程以外的其他课程时。通常,这些类型的关系最好使用角色建模而不是“是”关系。有关 Dealing with Roles 的更多信息,请参阅 Martin Fowler。

    在任何情况下,用户 UI 类都将成为您在 REST 实现中表示的基础,并根据它是与用户还是学生打交道,或者 - 在基于角色的方法中 - 在该表示中填充额外的部分与学生资料相关联的用户:

    {
      "user": "/users/1234",
      "name": "Some non student's name",
      "stats": {
        ...
      }
    }, 
    {
      "user": "/users/4567",
      "name": "Some Student's name",
      "stats": {
        ...
      }
      "papers": [
        { "paperid": "/users/papers/111"
          ...
        },
        { "paperid": "/users/papers/222"
          ...
        },
        { "paperid": "/users/papers/333"
          ...
        }
      ]
    }
    

    编辑以响应 cmets

    无论如何,服务器必须在某个级别做出决定,除非您想让您的 UI 在 URI 级别区分用户和学生。我建议反对。它使用户界面无法使用。用户对实现细节不感兴趣,也不想面对它们。

    但不,如果不需要的。

    充分利用多态性。

    服务器可以很好地利用多态性,从它的数据访问框架为它通过 id 检索的任何用户接收学生实例。毕竟学生总是可以被称为用户。因此,服务器可以简单地忽略它从数据访问框架获得的用户引用可能是学生这一事实。当服务器确实需要做/添加特定学生的东西时,它应该在派生类中这样做。

    为此,无需在任何地方使用 if 语句。甚至在 UI 类中也没有。 UI 只需要知道它收到的用户引用也可能是学生并采取相应的行动。最好不要通过if User is Student(这会将UI 方式与类层次结构紧密联系在一起),而是通过if IUser implements IStudent:询问用户引用是否还实现了学生接口,然后获取并使用该学生接口引用。

    【讨论】:

    • 如果我理解正确,这似乎与我的解决方案非常相似 - 在 UI 中有一个 User 类,它知道特定用户是否是学生(可能是老师,下来线)。按需实例化,提供额外信息。我看到的唯一区别是,服务器返回一个带有学生额外详细信息的“用户”对象,而不是返回一个“学生”对象,如果它是一个学生(其中也嵌入了用户的详细信息),或者用户对象,如果它只是一个用户而不是一个学生。我理解正确吗?
    • 是的,你理解正确。让用户界面处理将各种域类聚合成 MVC 三元组。这毕竟是 UI 的功能,以帮助用户的方式使域中的东西可用(而不是让用户遵循域)。它还有助于将 UI 层与域层解开,这样当域中的某些内容发生变化时,您就不必(尽可能多地)更改/重新编译 UI 层。
    • 问题是,那么服务器必须实际决定,当返回一个用户对象时,它实际上是一个用户还是一个培训师,并且每次都返回“层次较低”的对象。这是服务器中很多不太好的if 语句。
    • 您基本上是在说,根据编辑,在服务器上的类和 UI 上的类中都使用多态性。那么唯一需要if 的人是助手类,它从服务器接收“用户或学生”,并返回用户或学生类。顺便说一句,我不确定这在 Django 的 ORM 中是否真的可行,这就是为什么我问是否有必要。所以我们基本上同意这是正确的通用方法......
    • 是的。我们是一致的。 :-) 虽然我会敦促您进一步深入研究 Martin Fowler 的角色文档。这是一种比继承更好的方式来处理人们可以拥有的许多不同角色......
    猜你喜欢
    • 2018-02-15
    • 1970-01-01
    • 2012-06-08
    • 1970-01-01
    • 1970-01-01
    • 2013-09-19
    • 2015-02-01
    • 1970-01-01
    • 2012-01-05
    相关资源
    最近更新 更多