我正在构建一个REST API,我有一个实体Contact
(接口),有两个实现:
interface Contact {
val id: String
val email: String
}
class IndividualContact(
override val id: String,
override val email: String
val name: String,
val lastName: String) : Contact
class CompanyContact(
override val id: String,
override val email: String
val tradeName: String) : Contact
我有一个端点“GET / contacts”,它会返回所有联系人,个人和公司。所以,响应看起来像这样:
[
{"id": "1", "name": "John","lastName": "Doe", "email": "john@mail.com"},
{"id": "2", "tradeName": "ACompany", "email": "hello@acompany.com"}
]
如您所见,属性不同。这是一种不好的做法吗?即使我在每个项目中都包含一个鉴别器属性type
,这是不好的做法吗?
答案 0 :(得分:1)
这是一种不好的做法吗?即使我在每个项目中都包含一个鉴别器属性类型,这是一种不好的做法吗?
我不认为这是一种不好的做法 - 但它可能是不完整的。
似乎缺少的部分是看起来像一个稳定的架构的任何东西;消费者期望对存在的数据,缺失的数据等做出什么样的假设。
例如,在这种情况下,我们可能有类似
的架构Required: { id: integer, email: string}
Optional-Extension-1 : { name: string, lastName string }
Optional-Extension-2 : { tradeName: string }
表示这种方式,你有一组同类的属性。在您的示例中,第一个答案包含Required
和Optional-Extension-1
部分,其中第二个条目包含Required
和Optional-Extension-2
部分。
只要客户清楚地了解他们必须 - 忽略/必须转发他们不理解的可选部分,并且对于他们期望的部分缺失时要做什么标准事情有一定意义,您可以在心灵内容中添加(记录)扩展。
Greg Young的Versioning in Event Sourced Systems是一个很好的起点。您还可以在文档中找到许多标准消息格式(协议缓冲区,Avro等)的良好提示。
最基本的规则是:您无法向现有消息架构添加新的必填字段,也无法更改已定义字段的含义。 (如果您需要执行其中任何一项,则完全定义新的消息架构。)