我试图设计一个RESTful API来为前端JS应用程序提供数据,以及将来一个本机移动应用程序,一旦我开始编写它。
我对前端开发人员来说相当新,所以API设计对我来说也是一个新手。我正在写一个乒乓球联盟应用程序来开始我的学习,其中一个端点似乎不适合我读过推荐的API结构的任何例子。
我有两个实体,联赛和球员。联盟有一系列球员,当输入结果时,球员会切换位置"如果胜利者在比赛进入之前低于失败者,则在联盟中。
标准REST API可能具有以下端点,以更新联盟中特定玩家的详细信息:
(POST / PATCH) - / api / v1 / leagues / {league-id} / players / {player-id}
e.g。 / API / V1 /联赛/ 1 /播放器/ 12
这很好,但在我的情况下,当结果输入到网络应用程序中时,2个不同的玩家需要他们的"位置"通过API更新值。理想情况下,我会将此设置为数据库中的唯一字段,因此在任何给定时间内,只有1名玩家可以在联盟中的每个位置。但是,如果是这种情况,使用上面的API端点,我的前端应用程序将需要根据输入的结果计算玩家的新位置,更新玩家1,然后如果成功更新玩家2(回滚)失败)。遵循这种结构,位置字段不能是唯一的,因为在播放器1的更新之后,它们都具有相同的位置值,直到播放器2被更新。
我能想到的唯一其他解决方案是让一些其他适当命名的端点采用"结果"对象,是否在服务器端计算玩家新位置的逻辑,相应地更新,并返回一些数据供UI重新绑定和更新。
所以我的问题是:你会选择上面列出的两种方法中的哪一种,为什么?
如果您选择后者,您将从API调用中返回哪些数据以供UI绑定?一个完整的球员数据联盟?或者只是两个已更新的玩家?
由于
答案 0 :(得分:0)
选择在联盟中计算位置的位置是非常主观的 - 我建议在服务器上进行,因为它涉及再次搜索数据库(其他玩家的分数)。
由于您有多个玩家并且您可以一次更新2个玩家,因此最好发送玩家'请求正文中的得分及其位置,并在每个请求的响应中返回计算的全联盟信息,因为这将简化您的客户端代码并确保您获得最新数据。
这个建议是基于一个联盟中没有大量玩家的假设(可能> 100)。在这种情况下,我建议方法1更好。
因此,您的API网址可以是..
(POST)/ api / v1 / leagues / {league-id}
您的请求正文可以
"玩家":[ {"玩家ID":" 101"," newScore":" 10"}, {"玩家ID":" 103"" newScore":" 20"} ]
您的回复可以是最终联赛中球员的完整列表。
"玩家":[ {"玩家ID":" 101","位置":" 1"}, {" player-id":" 102"," position":" 2"}, {"玩家ID":" 103""位置":" 3"} {"玩家ID":" 104""位置":" 4"} {"玩家ID":" 105""位置":" 5"} ]
答案 1 :(得分:0)
我想我看到了两个问题
尝试这样的事情
PUT /api/v1/matches/{match-id}
{ winner : { id }, loser : { id }, ... }
向API提供描述游戏结果的消息(POST是可以接受的,PUT对于幂等性更好)。
作为此消息到达的副作用,将结果合并到您的域模型中。这是你的领域模型,应该包括描述玩家排名在游戏结束时如何变化的规则。
当有人想看到球员的排名时......
GET /api/v1/leagues/{league-id}/standings
您将它们发送到资源,该资源返回模型中当前排名的表示。
uri的拼写并不特别重要;我更喜欢“积分榜”,因为我相信你的领域是真实的。但是,如果您想在没有其他上下文的情况下反映资源的数据结构,则可以使用类似
的拼写GET /api/v1/leagues/{league-id}/players?orderBy=position
客户端发送给您的请求正文中的数据表示不是域模型中实体的序列化,而是发送到域模型的消息的序列化。