我鄙视使用过度设计的API,这些API并不简单.尽管如此,我正在为一个开源库设计一个API,我开始觉得我陷入了过度工程陷阱.我当然无法确定,因为当然,我写了一些令人讨厌的东西,所以它的工作原理对我来说比其他任何人都更明显.从开发人员的角度来看,您的API可能过度设计有哪些警告信号?
公开自定义集合与通用集合的框架设计指南是什么?例如
public class ImageCollection : Collection<Image>
{
...
}
public class Product
{
public ImageCollection {get; set;}
}
Run Code Online (Sandbox Code Playgroud)
VS
public class Product
{
public Collection<Image> Images{get; set;}
}
Run Code Online (Sandbox Code Playgroud) 我正在创建一个包含一些解析字符串日期和时间的方法的库.当字符串参数不可解析时,我很难确定这些方法应该抛出的异常.我正在考虑几种选择:
1. java.lang.IllegalArgumentException - 一个无效的字符串显然是一个非法的论点,但对我来说,IllegalArgumentException通常意味着编程错误,并且很少想要try catch为一个字符串做一个明确的.我认为字符串解析通常用于外部输入,更像是一种值得特殊处理的特殊情况.例如,如果您有一大块代码解析用户输入并对其执行其他操作,您可能希望将该代码包装在try catch块中,以便您可以处理包含无效字符串的用户输入的情况.但是捕获IllegalArgumentException对于查明无效的用户输入并不是很好,因为很可能在代码中有多个地方可以抛出它(而不仅仅是用户输入的解析).
2. java.lang.NumberFormatException - 它Integer.parseInt(String)和其他类似的解析方法一起被抛出java.lang.因此,大多数Java开发人员都熟悉,当您尝试解析可能有效或无效的字符串(例如用户输入)时,它会被捕获.但它的名字中有"数字",所以我不确定它是否真的适合日期和时间这些在某种意义上是数字的东西,但在我看来在概念上是不同的.如果只是它被称为"FormatException"...
3. java.text.ParseException - 不是真正的选择,因为它已被检查.我想要不加控制.
4.自定义异常 -这得到周围人的缺点IllegalArgumentException和NumberFormatException,故能扩大IllegalArgumentException了.但我不认为向库中添加异常是个好主意,除非真的需要它们.引用Josh Bloch的话说,"如果有疑问,请把它留下来".(另外,在我的例子中,对于解析日期和时间的包,很难命名这样的异常:"DateFormatException","TimeFormatException","CalendricalFormatException"(如JSR 310) - 当应用于方法时,似乎没有一个对我来说是理想的解析日期,时间,日期时间等.我认为如果它们都只用于识别不可解析的字符串,那么在单个包中创建多个异常会很愚蠢.)
那么您认为哪种选择最有意义?
注意:我有充分的理由不想使用java.util.Date或Joda Time,或JSR 310,因此无需提出建议.另外我认为如果这个问题保持相当普遍会很好,因为这一定是其他设计API的人一直在努力解决的问题.日期和时间也可以是IP地址,URL或具有需要解析的字符串格式的任何其他类型的信息.
其他图书馆设定的先例
我发现的几个例子:
java.sql.Timestamp.valueOf(String) throws IllegalArgumentException
java.util.Date.parse(String) throws IllegalArgumentException (已弃用的方法,并且未声明异常,但您可以在源代码中看到它)
java.util.UUID.fromString(String) throws IllegalArgumentException
org.apache.axis.types.Time(String) throws NumberFormatException (也是Apache Axis中的Day类)
org.apache.tools.ant.util.DeweyDecimal(String) throws NumberFormatException
com.google.gdata.data.DateTime.parseDateTime(String) throws NumberFormatException
java.lang.Package.isCompatibleWith(String versionString) throws NumberFormatException (在Java 7中,这需要带点的字符串版本号 - 有点像某个意义上的日期或时间)
我确信有很多软件包使用自定义异常,因此我怀疑提供这些例子有很多意义.
根据Swagger的教程,似乎swagger只支持Jersey框架(参见https://github.com/wordnik/swagger-core/wiki/java-jax-rs)
有没有人有过使用CXF JAX-RS实现大摇大摆的经验?你能在这里分享你的建议吗?
我正在设计一个JSON Web API,并希望通过唯一ID来区分客户端,以便监控使用情况并阻止恶意/行为不端的客户端.API不是封装在JavaScript库中,也不是Web应用程序独有的,任何客户端类型都可以使用它(桌面,电话等).
问题是,Web应用程序(官方网站)也是API本身的客户端,因此必须公开其API密钥.因此,某些用户可以从页面上的JavaScript中提取密钥并使用它,而不是生成自己的密钥.
是否有可能以某种更好/更聪明的设计选择来某种方式缓解这个问题,或者我是否必须忍受这样一个事实:任何恶意使用API的人都可以利用这个?
我可以100%控制前端应用程序(EmberJS)和后端服务器(Go),因此可以建议任何更改.
注意:问题不在于身份验证或安全性本身,而是如何要求第三方用户另外使用API密钥(!)进行身份验证!
在资源上表示POST/ PUT/ 的HATEOAS链接的最佳方法PATCH是什么?这些操作具有有效载荷,但我们没有选择在HATEOAS链接中表示有效载荷,因为它们不是预先确定的并且可能很重.那么仅仅指定结束点并指定操作就足够了吗?
对于使用HATEOAS POST/ PUT/ PATCHlink 的JSON响应,将非常感谢任何示例或示例.
我正在使用Celery和RabbitMQ来处理来自API请求的数据.过程如下:
请求 - > API - > RabbitMQ - >芹菜工人 - >返回
理想情况下,我会产生更多的芹菜工人,但我受内存限制的限制.
目前,我的流程中的瓶颈是从传递给worker的URL中获取和下载数据.粗糙,过程看起来像这样:
celery_gets_job(url):
var data = fetches_url(url) # takes 0.1s to 1.0s (bottleneck)
var result = processes_data(data) # takes 0.1ss
return result
Run Code Online (Sandbox Code Playgroud)
这是不可接受的,因为工作人员在获取URL时被锁定了一段时间.我期待通过线程改进这一点,但我不确定最佳做法是什么:
有没有办法让芹菜工作者在不同的线程中同时处理数据时异步下载传入的数据?
我是否可以通过RabbitMQ获取具有某种形式的消息传递的单独工作者获取和处理?
我们在REST服务器上有一些资源,结构如下:
/someResources/foo/someResources/bar/someResources/baz其中someResource是远离分布式对象的服务器表示.
我们想告诉服务器通过在网络中查看并更新服务器的缓存来"刷新"其对"分布式对象"的表示,即我们不能简单地将新值放入.
什么是干净的REST方式?
a)是否要POST到/refreshes/新的"刷新请求"?
b)是否要PUT(带空白文件)http://ip/someResources?
c)还有别的吗?
我喜欢(a)因为它会给我们一个id来识别和跟踪刷新命令,但担心我们创建了太多资源.有什么建议?
给定以下操作的预期/正确 HTTP 状态代码是什么:
400)401)403)404)501)5xx)资源当前被禁用,从而阻止操作以预期结果完成。用户可以更改资源的状态并重试相同的请求。有关资源为何无法执行所要求的操作的信息将包含在响应正文中。
我的想法是这409 Conflict将是最好的响应,因为用户可能会更改资源的状态并重新提交请求,但也许有更好的方法表明“您通常允许使用此方法,但资源当前处于状态这会阻止它按预期完成。”
对不同 API 端点中的同一实体使用多个 DTO 是否是一种好习惯。例如:我有一个 api 端点,它接受以下 Dto:
public class AddressDto
{
public string City { get; set; }
public string Country { get; set; }
public string Contact { get; set; }
public string Street1 { get; set; }
public string Street2 { get; set; }
public string State { get; set; }
public string Zip { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
现在有第二个 Api 接受相同的 dto 但在那个 api 调用中,我只使用了Streer1, Street2, Contact所有其他的都被忽略了。
我应该让另一个DTO为第二api endpoint,如:
public …Run Code Online (Sandbox Code Playgroud) api-design ×10
api ×4
rest ×3
.net ×2
c# ×2
http ×2
java ×2
celery ×1
collections ×1
cxfrs ×1
hateoas ×1
hypermedia ×1
python ×1
rabbitmq ×1
security ×1
swagger ×1
web-services ×1