在 REST Api 中建模对象继承 [英] Modeling Object Inheritance in a REST Api

查看:21
本文介绍了在 REST Api 中建模对象继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have an application that has a User object and a Student object. Some users are students. All students are users. In the database (django-ORM based), this is represented as a Student table with a foreign-key to the User table.

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

I'm trying to create a REST API, and an object hierarchy in the iOS app that models this API. I'm having trouble deciding how to model this.

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

The best I've come up with is this: Have a User model in iOS, have a Student model in iOS which inherits from User and extends it with more properties. Then, have a method which receives a JSON response from the server, and creates either a User or a Student model, depending on the dictinoary.

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

Finally, the server will need to always give me the most specific type. I.e., when I log in to the server, it will decide whether I'm a student or just a regular user, and will return me the proper dictionary.

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

This sounds a little complicated. But any other way I've thought of modeling it, e.g. changing the way the database is laid out, gives me a design in which the database isn't aware of all the constraints. For example, Student objects are allowed to own other objects (e..g, homework_paper). I can model this with a foreign key to a User object instead of to the Student object, and say that the Student is simply an extension of the user. But then the database doesn't force the fact that a homework_paper has to be owned by a student.

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

Is there a better way to solve this problem that I'm missing?

推荐答案

没有说 UI 层中的类需要与域类一对一匹配.就像您的域类不必完全遵循您的数据库表一样.

There is nothing that says the classes in your UI layer need to match 1-on-1 with your domain classes. Just like your domain classes do not have to follow your database tables exactly.

您可以将 UI 层的类视为 UI 表示的一组不同的类.使您的 UI 工作所需的类,或需要使用框架以发挥您的优势而不影响域模型和/或数据库设计中的业务规则的类.

You can think of the classes for your UI layer your UI representations as a different set of classes. Classes you needed to make your UI work, or needed to use a framework to your advantage without compromising the business rules in your domain model and/or database design.

您的用户 UI 类很可能是一个同时包含用户和学生域类的类.它将具有 User 和 Student 域类的知识.然后由这个包装类来实例化用户或学生.

Your User UI class could well be a class that wraps both user and student domain classes. It would have knowledge of both User and Student domain classes. It is then up to this wrapper class to instantiate either a User or Student.

另一种方法是将 User-Student 关系建模为has a"关系而不是is a".毕竟,当用户不仅可以是学生还可以是老师时,您要做什么.例如,当一名教师注册了他所教授的课程之外的其他课程时.通常,使用角色比是"关系更好地建模这些类型的关系.有关处理角色的更多信息,请参阅 Martin Fowler.

Another approach would be to model the User-Student relation as a "has a" relation instead of a "is a". After all, what are you going to do when user's can not only be students but teachers as well. For example when a teacher enrolls in some other course than the one (s)he teaches. Usually, these kinds of relations are better modelled using Roles than as "is a" relations. See Martin Fowler for more info on Dealing with Roles.

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

In any case, the User UI class would be the basis for your representation in your REST implementation and fill extra parts in that representation dependent on whether it is dealing with a user or a student or - in the role based approach - a user that has student stuff associated with it:

{
  "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"
      ...
    }
  ]
}

根据评论进行编辑

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

The server has to decide that anyway at some level, unless you want to have your UI differentiate between users and students at the URI level. Which I recommend AGAINST. It makes for unusable UI's. The user isn't interested in the implementation details and doesn't want to be confronted with them.

但不,如果不需要.

充分利用多态性.

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

The server can put polymorfism to good use receiving a student instance from its data access framework for any user that it retrieves by id. Students after all can always be referenced as users. So the server can simply ignore the fact that the user reference it gets from the data access framework might be a student. When the server actually needs to do/add specific student stuff, it should do so in a derived class.

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

No if statement needs to be used anywhere for this. Not even in the UI classes. The UI just needs to know that the User reference it receives could also be a Student and act accordingly. Preferably not by if User is Student (that would be tying the UI way to deeply to the class hierarchy), but by if IUser implements IStudent: asking the User reference whether it also implements the Student interface, and then getting and using that IStudent interface reference.

这篇关于在 REST Api 中建模对象继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆