API设计的七宗罪


API设计的七宗罪

文章插图
Learning from bad examples
我当时正在帮助一个需要将物业管理系统中的房屋可用性与客户网站集成的朋友 。幸运的是,物业管理系统具有API 。而不幸的是,这一切都错了 。
这个故事的目的不是给二手系统带来不好的广告,而是分享不应该开发的东西,以及在设计API时学习正确的方法 。
任务我朋友的客户正在使用Beds24系统管理他们的财产清单,并在各种预订系统(预订,AirBnB等)之间保持可用性同步 。他们正在建立一个网站,并希望搜索机制仅显示可用于所选日期和客人人数的属性 。听起来像是一项艰巨的任务,因为Beds24提供了与其他系统集成的API 。不幸的是,开发人员在设计时已经犯了很多错误 。让我们逐步解决这些错误,看看到底出了什么问题以及应该如何解决 。
一宗罪:请求正文格式由于只对获取客户端属性的可用性感兴趣,因此仅对/ getAvailabilities调用感兴趣 。即使这是获取可用性的调用,但实际上这是一个POST请求,因为作者决定接受过滤器作为JSON正文 。以下是所有可能参数的列表:
{"checkIn": "20151001","lastNight": "20151002","checkOut": "20151003","roomId": "12345","propId": "1234","ownerId": "123","numAdult": "2","numChild": "0","offerId": "1","voucherCode": "","referer": "","agent": "","ignoreAvail": false,"propIds": [1235,1236],"roomIds": [12347,12348,12349]} 
让我遍历JSON对象并解释其参数出了什么问题 。
· 日期checkIn,lastNight和checkOut使用YYYYMMDD格式设置 。将日期编码为字符串时,绝对没有理由不使用标准ISO 8601格式(YYYY-MM-DD),因为这是大多数开发人员和JSON解析器都理解并期望的广泛采用的标准 。除此之外,lastNight字段似乎是多余的,因为提供了checkOut,它总是比前一天晚一天 。请始终使用标准日期编码格式,不要要求API用户提供冗余数据 。
· 所有Id以及numAdult和numChild字段都是数字,但被编码为字符串 。在这种特殊情况下,似乎没有理由将它们编码为字符串 。
· 我们具有以下字段对:roomId和roomIds以及propId和propIds 。因为可以使用roomIds和propIds传递ID,所以具有roomId和propId属性不仅是多余的,而且这里还存在类型问题 。请注意,roomId需要一个字符串,而roomIds需要一个数字数组 。这可能会造成混乱,解析问题,并且意味着即使我们在谈论相同的数据,后端本身也会对字符串执行某些操作,并对数字执行某些操作 。
请不要将开发人员犯此类愚蠢的错误,并尝试使用标准格式,并注意冗余和字段类型 。不要只是将所有内容包装在字符串中 。
二宗罪:响应正文格式如上一部分有关请求正文格式的说明,我们仅关注/ getAvailabilities调用 。这次让我们看一下响应主体格式,看看有什么问题 。请记住,我们有兴趣获取给定日期和许多客人可用的属性的ID 。以下是相应的请求和响应正文:
请求:
{"checkIn": "20190501","checkOut": "20190503","ownerId": "25748","numAdult": "2","numChild": "0"}响应:
{"10328": {"roomId": "10328","propId": "4478","roomsavail": "0"},"13219": {"roomId": "13219","propId": "5729","roomsavail": "0"},"14900": {"roomId": "14900","propId": "6779","roomsavail": 1},"checkIn": "20190501","lastNight": "20190502","checkOut": "20190503","ownerId": 25748,"numAdult": 2} 
· ownerId和numAdult在响应中突然变成数字,而不是在请求正文中为字符串 。
· 没有属性列表 。相反,属性是使用roomId作为键的顶级对象 。这意味着,为了获取可用属性的列表,我们需要遍历所有对象,检查是否存在某些参数(例如roomsavail),舍弃其他参数(例如checkIn,lastNight等)以获取属性列表 。然后,我们需要检查roomsavail属性的值,如果该值大于0,则将该属性视为可用 。但是请稍等,在这里仔细查看:" roomsavail":" 0",在这里" roomsavail":1.看到模式了吗?如果没有可用的房间,则值为字符串,而如果有可用的房间,则为数字!这将在诸如JAVA之类的强制执行类型安全的语言中引起很多问题,因为同一属性不应属于不同的类型 。请使用适当的JSON列表来显示数据集合,而不要像上面那样使用奇怪的键值构造,并确保不要在对象之间更改字段类型 。正确格式的响应如下所示(请注意,这种格式也可以在不重复任何内容的情况下获取有关房间的信息):


推荐阅读