在REST Api中建模对象继承

Eda*_*aor 5 oop api django rest objective-c

问题

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

我正在尝试在iOS应用程序中创建一个REST API和一个对象层次结构来模拟这个API.我无法决定如何建模.

当前的解决方案

我提出的最好的是:User在iOS中有一个模型,在iOS中有一个Student模型,它继承User并扩展了更多的属性.然后,具有从该服务器接收的JSON响应,并创建一个方法或者一个User或一个Student模型,这取决于dictinoary.

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

这是最好的方法吗?

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

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

Mar*_*ema 2

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

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

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

另一种方法是将用户-学生关系建模为“有一个”关系而不是“是一个”关系。毕竟,当用户不仅可以是学生,还可以是老师时,你该怎么办?例如,当老师报名参加他所教授的课程之外的其他课程时。通常,使用角色来建模这些类型的关系比使用“是”关系更好。有关处理角色的更多信息,请参阅 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"
      ...
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

编辑回应评论

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

但不不需要if

利用多态性来发挥你的优势。

服务器可以充分利用多态性,从其数据访问框架接收通过 ID 检索的任何用户的学生实例。毕竟,学生始终可以被称为用户。因此,服务器可以简单地忽略它从数据访问框架获取的用户引用可能是学生的事实。当服务器实际上需要执行/添加特定的学生内容时,它应该在派生类中执行此操作。

为此,无需在任何地方使用 if 语句。即使在 UI 课程中也不行。用户界面只需要知道它收到的用户引用也可以是学生并采取相应的行动。最好不是通过if User is Student(这会将 UI 方式深深地绑定到类层次结构),而是通过if IUser implements IStudent:询问 User 引用是否也实现 Student 接口,然后获取并使用 IStudent 接口引用。