我开始在一个新的架构范例中开发我们拥有的一些遗留代码。让我们调用不同的范例v1和v2。
在v1上,我们有不同域(例如游戏)的模型,它们嵌套了实体的所有信息以及属性 - 多次混合实体和属性是什么。因此,当您点击端点时,您可以获得嵌套与域相关的所有内容的响应。 E.g / v1 / games会为你带来游戏+玩家+团队+竞技场。
在v2上,我们尝试更加面向资源,以便您实际获得您要查询的资源(例如) - 您有v2 /游戏的端点,然后您将拥有端点v2 / games / {id} / players。使用前者,您将获得游戏对象,而在第二种情况下,您将获得玩家对象。我认为它是自我纪录片的路径 - 你知道你通过查看你正在制作的请求会得到什么。
在v1上,我们有了这个巨大的模型,其中包含了所有内容 - 无论我们看到什么是"属性"域名。因此,我们的实际模型将包括相关的"属性" - 例如,游戏对象将包含一个玩家对象数组。
每当你获得或发布时,你实际上都会使用相同的模型,你只需要在GET上获得更多信息(嵌套对象),并且POST不需要一些字段(例如/你不会'需要发送你的帖子的玩家 - 我们有一个单独的端点。
class Game {
public $id;
public $datePlayed;
public $players = [];
public $homeTeam = [];
public $awayTeam = [];
}
在v2模型上,我们对数据库表进行了实际表示(就像建模的主动记录方法一样,模型基于持久层)。所以游戏模型不包括玩家(因为那是一个完全不同的对象)。
class Game {
public $id;
public $datePlayed;
public $homeTeamId;
public $awayTeamId;
}
到目前为止,我认为最终结果非常好,因为我们实际上获得了我们需要的资源,而不是具有大量冗长和不必要数据的嵌套版本。
但是我现在面临新的挑战。有些端点需要返回具有更多信息的响应,这些信息不是实际的数据库表示。由于我们不是一个完美的世界,我不希望使用我们的API的开发人员实际上对所有属性提出大量请求,我需要提出一个解决方案来帮助我提供一些基本信息相关资源。
例如,返回我们的游戏终点 - >创建我希望他们发送一个有效的数据库对象
{
"datePlayed": "2016-04-29T17:20:08+00:00",
"homeTeamId": 5,
"awayTeamId": 15
}
但是对于GET,我想用基本数据来装饰响应(不是整个对象,而是足够让开发人员获得基本信息,以便他们只提出新的请求来获取完整的相关资源,但不是基本信息)。
{
"datePlayed": "2016-04-29T17:20:08+00:00",
"homeTeam": {
"id": 5,
"name": "Killer clan"
},
"awayTeam": {
"id": 15,
"name": "Retry team"
}
}
首先,我将此职责委托给controller->存储库,该存储库将根据请求创建新对象并在GET方法上返回它,但会验证对实际模型的POST和PUT请求。但是,从长远来看,这似乎无法维护,因为您必须深入了解代码以了解您要发送的内容。
所以我给了它一个很长的想法,我有一个想法,创建一组新的模型与常规Stub(检查,收据,票据或其他文件的一部分撕下并保存为记录)将声明响应的结构。例如:/我会像这样创建一个GameStub模型类
class GameStub {
public $id;
public $datePlayed;
public $homeTeam = [];
public $awayTeam = [];
}
我认为占位符或元数据也是好的名称约定,但要点是相同的。
你们怎么看待这个解决方案?它有意义吗?
答案 0 :(得分:1)
具有明确的意义,因为它是将应用程序与api分离的好方法。
API中的资源!=应用程序模型。
我在我的应用程序中使用以下结构:
模型 - 游戏(这是你的模特) 帕拉姆 - GameParam(你希望通过api提供的模型/参数/资源) 变流器 - GameConverter(将模型转换为参数,将Param转换为模型)
答案 1 :(得分:1)
部分内容非常有意义,但我不理解你的存根隐喻以及它与问题的关系。
所以GET / games / gameId通常会返回团队ID。为了获得更多团队信息(例如团队名称),用户将使用GET / teams / teamId。您希望通过发送一些(但不是全部)团队信息作为游戏查询的一部分来避免其他查询。
那么您如何知道特定请求需要哪些附加信息?如果(例如)某些请求需要教练的名字怎么办?好像你会试图猜测需要什么,并最终再次发送所有内容。
您是否看过Facebook的图形查询语言? http://graphql.org/
基本思路是否允许请求指定他们真正需要的信息。所以你可能有GET / games / gameId?want = teamName,coachName
然后由服务器决定如何返回必要的数据。我建议您不要在应用程序中使用graphql。这几乎肯定是矫枉过正的。
但也许让消费者有能力指定他们需要的东西可能有所帮助。
一定要利用名为Command Query Responsibility Segregation(http://martinfowler.com/bliki/CQRS.html)的模式。与创建或更新对象有关的任何内容都应该在它自己的空间中。独立对待查询。