REST风格的设计:何时使用子资源? [关闭](RESTful design: when to

2019-07-04 00:32发布

当设计资源层次,一个时,应使用子资源?

我曾经相信,当资源不能没有另一个存在,它应该代表其子资源。 最近,我跑过这个反例:

  • 一个员工在所有企业唯一标识。
  • 员工的访问控制和生命周期取决于公司。

我模仿此为: /companies/{companyName}/employee/{employeeId}

请注意,我并不需要查找该公司为了找到员工,所以要这样呢? 如果我这样做,我付出的代价查找我不需要的信息。 如果我不这样做,这个URL错误地返回HTTP 200:

/companies/{nonExistingName}/employee/{existingId}

  1. 我应该如何代表一个资源属于另一个事实?
  2. 我应该如何代表一个事实,即资源不能没有相互识别呢?
  3. 在子资源意味着什么关系,并不意味着模型?

Answer 1:

这是问题,因为它已经不再明显,用户属于一个特定的公司。

有时,这可能会突出显示与您的域模型的一个问题。 为什么一个用户属于一个公司? 如果我改变的公司,我是全新的人吗? 如果我对两家公司的工作是什么? 我是两个不同的人?

如果答案是肯定的,那么为什么不采取一些公司唯一标识符访问用户?

例如:用户名:

company/foo/user/bar

(这里bar是我的用户名是唯一特定公司命名空间内)

如果答案是否定的,那么为什么我不是一个用户(人)的自己,以及company/users收集只是指我: <link rel="user" uri="/user/1" />注意:员工似乎更合适)

现在你的具体的例子之外,我认为,当涉及到使用 ,而不是所有权 (这就是为什么你与识别一个公司的隐含标识企业用户的冗余挣扎)资源子资源的关系是比较合适的。

我的意思这是一个users实际上是一个企业资源的子资源,因为使用是定义一个企业与员工之间的关系-说的另一种方式是:你之前,你可以定义一个公司开始雇佣员工。 同样,用户(人)必须定义(出生)之前,你可以招募他们。



Answer 2:

一年后,我用下面的妥协(对于包含一个唯一的标识符数据库行)结束:

  1. 分配所有资源的规范URI在根目录(例如/companies/{id}/employees/{id}
  2. 如果资源不能没有另一个存在,它应该表现为它的子资源; 然而,治疗操作作为搜索引擎查询。 含义,而不是立即执行的操作,只需返回HTTP 307 ("Temporary redirect")在标准URI指向。 这将导致客户重复对标准URI的操作。
  3. 你的规范文档应该只露出满足您的概念模型(不依赖于实施细节),其根的资源。 实现细节可能会改变(你行可能不再是唯一可识别的),但你的概念模型将保持不变。 在上面的例子中,你会告诉客户/companies ,但没有/employees

这种方法具有以下优点:

  1. 它消除了需要做无谓的数据库查找窗口。
  2. 它减少了完整性检查的数量为每一个请求。 至多,我要检查员工是否属于公司,但我再也不用为做两个验证检查/companies/{companyId}/employees/{employeeId}/computers/{computerId}
  3. 它具有对数据库的可扩展性的混合影响。 一方面,你被锁定较少的表,对于较短的时间内减少锁争用。 但在另一方面,你都在增加,因为每一根资源必须使用不同的锁定顺序死锁的可能性。 我不知道这是否是一个净损益,但我乐意接受这样的事实数据库死锁无法阻止无论如何,所得锁定规则是容易理解和执行。 如果有疑问,选择简单。
  4. 我们的概念模型保持不变。 通过确保规范文档只公开我们的概念模型,我们可以自由地丢弃包含在未来实施细则的URI不会破坏现有的客户。 请记住,没有什么能阻止你在中间的URI暴露的实现细节,只要你规范声明其结构为未定义。


Answer 3:

您的规则来决定,如果一个资源应该被建模为子资源是有效的。 不从错误的概念模型出现你的问题,但你让你泄露的数据库模型到您的REST模式。

从的概念图的employee ,如果它只能在存在于company的关系被建模为组合物 。 该employee可能因此只能通过鉴定company 。 现在数据库开始发挥作用,所有employee行获得一个唯一的标识符。

我的建议是不要让数据库模型泄漏你的概念性的模型,因为你暴露基础设施问题,以你的API。 例如,当你决定要切换到像MongoDB的文档面向对象数据库在那里你可以作为公司文档的一部分,你的员工建模,不再有这种人为的唯一的ID,会发生什么? 你想改变你的API?

要回答你的问题外

我应该如何代表一个资源属于另一个事实?

通过URL链接通过子资源,其他协会组成。

我应该如何代表一个事实,即资源不能没有相互识别呢?

在资源URL同时使用ID值,并确保不要让你的数据库通过检查“组合”存在泄漏入您的API。

在子资源意味着什么关系,并不意味着模型?

子资源非常适合于成分,但更普遍地说,以模型,资源不能没有父资源存在,并永远属于一个母公司的资源。 您的规则when a resource could not exist without another, it should be represented as its sub-resource是这一决定一个很好的指导。



Answer 4:

如果一个子资源是唯一可识别的不拥有它的实体,它是没有子资源,应该有自己的名称空间(即/用户/用户{}而非/公司/ {*} /用户/用户{})。 最重要的是:永远不everer使用您的实体的数据库主密钥作为资源标识符。 这是最常见的错误,其执行细节泄漏到外面的世界。 你应该始终有一个自然的业务键(如用户名或公司数目,而不是用户ID或公司ID)。 在这样一个关键的独特性可以通过一个唯一约束强制执行,如果你愿意,而是一个实体的主键应该永远everer离开你的应用程序的持久层,或者至少不应该是一个参数的任何服务方法。 如果你去了这条规则,你不应该有成分区分任何麻烦(/公司/ {}公司/用户/用户{})和协会(/用户/用户{}),因为如果你的子资源没有自然业务键,标识它在全球范围内,你可以非常肯定这真的是一个根据子资源(或您必须首先创建一个业务键,使其在全球识别)。



Answer 5:

这是你能解决这个问题的一种方法:

/公司/ {CompanyName}的/员工/ {}雇员 - 有关雇员>返回数据,还应该包括人员的数据

/人/ {的peopleid} - >返回关于人数据

谈到员工是没有意义也没有谈论公司,但讲的是人有一定道理,即使没有一个公司,甚至如果他被多家公司聘请。 一个人的存在是独立的是否他的任何公司录用,但劳动的存在不依赖于该公司。



Answer 6:

这个问题似乎是在没有具体的公司,而是员工在技术上属于某个公司或组织,否则他们可以被称为烧伤或政治家。 作为一个员工的地方,但并不意味着公司/组织关系的特定的一个。 员工也可以连续工作超过一个公司/组织。 当需要特定的公司背景,然后你的原创作品/companies/{companyName}/users/{id}

比方说,你想知道EmployerContribution为您的IRA / RSP /养老你会使用: /companies/enron/users/fred/EmployerContribution你得到的具体数额贡献的安然公司(或$ 0)。

如果你想EmployerContribution任何或所有公司弗雷德作品(ED)对于s?
你并不需要一个具体的公司为它是有意义的。 /companies/any/employee/fred/EmployerContribution

这里的“任何”显然是一个抽象或占位符的时候,员工的公司并不重要,但作为一个雇员做了。 你需要拦截“公司”处理程序,以防止数据库查询(虽然不知道为什么公司不会被缓存?有多少能有?)

你甚至可以改变抽象表示类似的弗雷德被使用在过去10年中的所有公司。 /companies/last10years/employee/fred/EmployerContribution



文章来源: RESTful design: when to use sub-resources? [closed]