String在Java中是不可变的.从广义上讲,以下片段是"错误的".
String s = "hello world!";
s.toUpperCase(); // "wrong"!!
System.out.println(s); // still "hello world!"!!!
Run Code Online (Sandbox Code Playgroud)
尽管这是"错误的",代码编译和运行,也许是许多初学者的困惑,他们必须被告知错误是什么,或者通过查阅文档找出自己.
阅读文档是理解API的重要部分,但我想知道是否可以通过额外的编译时检查来补充它.特别是,我想知道是否可以使用Java的注释框架来强制执行某些方法返回的值不被忽略.然后,API设计者/库作者将在其方法中使用此批注来记录不应忽略的返回值.
一旦API补充了这个注释(或者可能是另一种机制),那么每当用户编写如上所述的代码时,它就不会编译(或者通过严厉的警告进行编译).
那么这可以做到,你会怎么做这样的事情?
很明显,在一般情况下,Java 应该允许忽略方法的返回值.可以在大多数时间安全地忽略像List.add(always true),System.setProperty(previous value)这样的方法的返回值.
然而,也有很多的方法,其返回值应不被忽略.这样做几乎总是程序员错误,或者不正确使用API.这包括以下内容:
String,BigInteger等)的方法,它返回操作结果而不是改变它被调用的实例.InputStream.read(byte[])返回读取的字节数,这应该不被假定为阵列的整个长度)目前,我们可以编写忽略这些返回值的代码,并让它们在没有警告的情况下编译和运行.静态分析检查器/ bug查找器/样式执行器/等几乎可以肯定地将这些标记为可能的代码气味,但如果可以通过API本身(可能通过注释)强制执行,那么它似乎是合适的/理想的.
一个类几乎不可能确保它总是"正确"使用,但它可以做些什么来帮助指导客户正确使用(参见:Effective Java 2nd Edition,Item 58:对可恢复的条件使用已检查的异常和编程错误的运行时异常和项62:记录每种方法抛出的所有异常).有一个注释可以强制客户端不要忽略某些方法的返回值,并且编译器在编译时以错误或警告的形式强制执行它,这似乎符合这个想法.
以下是初步尝试,简洁地说明了我想要实现的目标:
@interface Undiscardable { }
//attachable to methods to indicate that its
//return value must not be discarded
public class UndiscardableTest { …Run Code Online (Sandbox Code Playgroud) 考虑到数据类型的各种怪癖和本地化,Web服务与应用程序之间传递货币价值的最佳方式是什么?某处有标准吗?
我的第一个想法是简单地使用数字类型.例如
"amount": 1234.56
Run Code Online (Sandbox Code Playgroud)
在使用浮点数据类型进行货币计算时,我已经看到很多关于缺乏精度和舍入误差的问题的论点 - 但是,我们只是传递值而不是计算,所以这无关紧要.
EventBrite的JSON货币规范指定如下:
{
"currency": "USD",
"value": 432,
"display": "$4.32"
}
Run Code Online (Sandbox Code Playgroud)
Bravo用于避免浮点值,但现在我们遇到另一个问题:我们可以容纳的最大数字是多少?
一条评论(我不知道它是否属实,但似乎是合理的)声称,由于数字实现在JSON中有所不同,因此您可以期待的最好的是32位有符号整数.32位有符号整数可以容纳的最大值是2147483647.如果我们表示次要单位中的值,那么是21,474,836.47美元.2100万美元似乎是一个巨大的数字,但是某些应用程序可能需要使用大于此值的值,这并不是不可思议的.对于1000个未成年单位成为主要单位的货币,或者货币价值低于美元的货币,问题会变得更严重.例如,突尼斯第纳尔分为1,000毫米.2147483647 milim,或2147483.647 TND是$ 1,124,492.04.在某些情况下,更有可能超过100万美元的价值.另一个例子:越南盾的子单位因通货膨胀而变得无用,所以让我们只使用主要单位.2147483647越南盾是98,526.55美元.我相信很多用例(银行存款,房地产价值等)远高于此.(EventBrite可能不必担心票价会那么高!)
如果我们通过将值作为字符串传递来避免该问题,那么字符串应该如何格式化?不同的国家/地区具有截然不同的格式 - 不同的货币符号,无论符号出现在金额之前还是之后,无论是否在符号和金额之间有空格,如果使用逗号或句点来分隔小数,如果逗号用作千位分隔符,括号或减号来表示负值,可能还有更多我不知道的值.
如果应用知道它正在使用的语言环境/货币,请传达类似的值
"amount": "1234.56"
Run Code Online (Sandbox Code Playgroud)
来回,并相信应用程序正确格式化金额?(另外:是否应避免使用小数值,以及以最小货币单位指定的值?或者主要和次要单位是否应列在不同的属性中?)
或者服务器应该提供原始值和格式化值?
"amount": "1234.56"
"displayAmount": "$1,234.56"
Run Code Online (Sandbox Code Playgroud)
或者服务器应该提供原始值和货币代码,并让应用程序格式化它?"amount":"1234.56""currencyCode":"USD"我假设使用的方法应该在两个方向上使用,与服务器之间进行传输.
我一直无法找到标准 - 您是否有答案,或者可以指向我定义此资源的资源?这似乎是一个普遍的问题.
我最近正在观看关于如何创建流畅的DSL的网络直播,我不得不承认,我不明白为什么会使用这种方法(至少对于给定的例子).
网络广播提供了一个图像大小调整类,它允许您指定输入图像,调整大小并使用以下语法将其保存到输出文件(使用C#):
Sizer sizer = new Sizer();
sizer.FromImage(inputImage)
.ToLocation(outputImage)
.ReduceByPercent(50)
.OutputImageFormat(ImageFormat.Jpeg)
.Save();
Run Code Online (Sandbox Code Playgroud)
我不明白这是如何比采用一些参数的"传统"方法更好:
sizer.ResizeImage(inputImage, outputImage, 0.5, ImageFormat.Jpeg);
Run Code Online (Sandbox Code Playgroud)
从可用性的角度来看,这似乎更容易使用,因为它清楚地告诉您该方法期望作为输入.相比之下,使用流畅的界面,没有什么可以阻止你省略/忘记参数/方法调用,例如:
sizer.ToLocation(outputImage).Save();
Run Code Online (Sandbox Code Playgroud)
关于我的问题:
1 -是否有某种方法可以提高流畅界面的可用性(即告诉用户他应该做什么)?
2 -这种流畅的界面方法是否只是C#中现有的命名方法参数的替代?命名参数会使流畅的接口过时,例如类似Objective-C提供的东西:
sizer.Resize(from:input, to:output, resizeBy:0.5, ..)
Run Code Online (Sandbox Code Playgroud)
3 -流畅的界面是否过度使用仅仅是因为它们目前很受欢迎?
4 -或者它只是一个被选为网络广播的坏榜样?在这种情况下,请告诉我这种方法的优点是什么,使用它的意义何在.
顺便说一句:我知道jquery,看看它有多容易,所以我不是在寻找关于那个或其他现有例子的评论.
我正在寻找一些(一般)评论来帮助我理解(例如)何时实现流畅的界面(而不是经典的类库),以及实现它时需要注意的事项.
我目前正在设计一个API,我遇到了一个小问题: 当你应该能够通过ID或slug来识别项目时,RESTful API的URL应该怎么样?
我可以想到三个选择:
GET /items/<id>
GET /items/<slug>
Run Code Online (Sandbox Code Playgroud)
这要求slu and和ID是可区分的,在这种情况下不一定给出.我想不出这个问题的干净解决方案,除非你做这样的事情:
GET /items/id/<id>
GET /items/slug/<slug>
Run Code Online (Sandbox Code Playgroud)
这样可以正常工作,但是这不是我想要通过slug或ID来识别项目的唯一地方,当想要为其他操作实现相同的方法时,它很快会变得非常难看.它只是不太可扩展,这导致我们采用这种方法:
GET /items?id=<id>
GET /items?slug=<slug>
Run Code Online (Sandbox Code Playgroud)
这似乎是一个很好的解决方案,但我不知道它是否是人们期望的,因此它可能导致由于错误使用而导致的令人沮丧的错误.而且,为这个实现路由并不是那么容易 - 或者说是干净利落的.但是,它很容易扩展,看起来非常类似于获取多个项目的方法:
GET /items?ids=<id:1>,<id:2>,<id:3>
GET /items?slugs=<slug:1>,<slug:2>,<slug:3>
Run Code Online (Sandbox Code Playgroud)
但这也有一个缺点:如果有人想要识别他想用ID获取的一些物品,但其他人有一个slu ?? 混合这些标识符并不容易实现.
对于这些问题,最好和最广泛接受的解决方案是什么?一般来说,在设计这样的API时重要的是什么?
我将为一个Web应用程序构建一个API,我对人们可以建议的良好实践感兴趣.
我已经计划将其版本化(版本1只能控制系统的某些方面,版本2可以控制更多,但这可能需要更改执行与版本1不兼容的身份验证的方式),以及身份验证将与人们用于登录的标准用户名/密码不同(如果有人使用恶意工具,则无论api允许的话,都不会打开它们进行完全模拟).
有没有人有更多的想法,或者您使用过特别好的API的网站示例?
我有以下接口,使用回调返回类型T的泛型参数...
public interface IDoWork<T>
{
T DoWork();
}
Run Code Online (Sandbox Code Playgroud)
但是我也有以下接口,但它不会调用回调,因为它返回void.
public interface IDoWork
{
void DoWork();
}
Run Code Online (Sandbox Code Playgroud)
我可以组合这两个接口并使用运行时逻辑来确定差异吗?我怎样才能做到这一点?
假设我们有以下REST调用:
GET api/companies/5
Run Code Online (Sandbox Code Playgroud)
(获得id为5的公司)
如果公司'5'不存在,我们通常会返回一个404 Not Found回复.
但是现在,让我们接听这个电话:
GET api/companies/5/invoices/10
Run Code Online (Sandbox Code Playgroud)
(从公司5获得发票10)
现在,如果公司'5'不存在,我们还会退货404 Not Found吗?或者,如果无法找到最外层的资源(在这种情况下为发票10),则仅返回404.
会Bad Request也许是一个更好的选择吗?
rest api-design http-status-code-404 asp.net-web-api asp.net-web-api2
在新的Swift API设计指南中,Type正在使用常用的协议后缀.虽然这对于独立(SequenceType成为Sequence)协议很容易做,但我不确定如何更新我的API,其中协议为实现提供了基础.以下是流行框架的一些示例:
Result,混凝土成功/失败枚举,并且ResultType,通用基础协议用于成功/失败类型,向其中Result符合.Signal和SignalProducer,由SignalType和支持SignalProducerType.在这两种情况下,大部分实现都是对协议的扩展,允许扩展使用类型约束的全部功能,并允许实现是通用的.这是从协议的情况下,不同AnySequence风格类型擦除类型:你是不是真的有望实现你自己的这些协议,或统一不同的类型.
假设我正在用C编写一个小库 - 比如一些数据结构.如果我无法分配内存,该怎么办?
这可能非常重要,例如我需要一些内存来初始化数据结构,或者我正在插入一个键值对并希望将它包装在一个小结构中.它也可能不太重要,例如类似于pretty_print构建内容的良好字符串表示的函数.然而,它通常比你的平均错误更严重 - 可能没有任何意义继续下去.malloc如果返回,大量的在线样本使用直接退出程序NULL.我猜很多真正的客户端代码也会这样做 - 只是弹出一些错误,或写入stderr并中止.(而且很多真正的代码可能根本不检查返回值malloc.)
有时回归是有意义的NULL,但并非总是如此.错误代码(或只是一些布尔success值),无论是返回值还是输出参数都可以正常工作,但似乎它们可能会混乱或损害API的可读性(那么,可能在C语言中有点期待?) .另一种选择是让调用者可以随后查询某种内部错误状态,例如使用get_error函数,但是你必须小心线程安全,并且可能很容易错过; 无论如何,人们往往会对检查错误松懈,如果它完全是一个单独的功能,他们可能不知道它,或者他们可能不会打扰(但我猜这是他们的问题).
(我有时看到malloc包裹在一个函数中,只是再次尝试,直到内存可用...
void *my_malloc(size_t size)
{
void *result = NULL;
while (result == NULL)
result = malloc(size);
return result;
}
Run Code Online (Sandbox Code Playgroud)
但这似乎有点愚蠢,也许很危险.)
处理这个问题的正确方法是什么?
假设我们有'用户'资源,对'name'有唯一约束.您将如何设计REST API来处理find-or-create(按名称)用例?我看到以下选项:
客户:
POST /user
{"name":"bob"}
Run Code Online (Sandbox Code Playgroud)
服务器:
HTTP 409 //or something else
Run Code Online (Sandbox Code Playgroud)
客户:
GET /user?name=bob
Run Code Online (Sandbox Code Playgroud)
服务器:
HTTP 200 //returns existing user
Run Code Online (Sandbox Code Playgroud)
客户:
POST /user
{"name":"bob"}
Run Code Online (Sandbox Code Playgroud)
服务器:
HTTP 200 //returns existing user
Run Code Online (Sandbox Code Playgroud)
(如果实际创建了用户,则返回HTTP 201)
客户:
POST /user
{"name":"bob"}
Run Code Online (Sandbox Code Playgroud)
服务器:
HTTP 409 //as in option1, since no CREATE took place
{"id": 1, "name":"bob"} //existing user returned
Run Code Online (Sandbox Code Playgroud) api-design ×10
rest ×3
api ×2
c# ×2
annotations ×1
c ×1
currency ×1
dsl ×1
generics ×1
java ×1
json ×1
malloc ×1
nul ×1
return-value ×1
swift ×1