Operator Frog?
什么是 Operator Frog
Operator Frog 是我做的为期 < 24h 的思想实验。我想知道我们是否可以在 Dart 中编写一个看起来奇怪的 API 来进行 HTTP 通信,而无需任何代码生成。
它是如何工作的?
Operator Frog 重载了运算符,创建了一个不依赖于方法的 API。这并不能让它变得易读(除非是你),但它很好地展示了如何在 Dart 中重载运算符,以及某些类型的运算符(位运算符 vs 比较运算符)在返回类型方面具有一定的逻辑。
例如,Dart 中的任何位运算符(&, ^, |, >>, <<<)都允许直接链式调用下一个位运算符,而无需将语句放在括号中。而比较运算符(>=, >)会假设下一个运算符是在前一个运算符调用的左侧调用的。
这意味着你在定义链式 API 逻辑的方式上会受到一定的限制。例如,使用 Operator Frog 的客户端,你可以这样做:
final client = http > 'https://:8080';
await (client.post / 'todos' &
header >> {'Content-Type': 'application/json'} &
json >> {'title': 'A new Todo'});
请注意,我们是如何使用 >> 和 & 来设置我们的请求对象的?如果我们用 > 替换 >>,它会抱怨 The operator '>' isn't defined for the type 'HttpRequest'.,因为 > 是在 client.post / 'todos & header 的结果上调用的,而不是在 header 上调用的。
可读性
我试图通过使用特定的运算符执行特定的操作来保持客户端和服务器端某种程度的可读性。例如,创建请求(或在服务器上定义路由)的操作,我使用了 / 运算符,表示路径的开始:/some/path。
如果需要向对象添加内容,例如向 HttpRequest 添加标头或查询,我使用了 & 运算符,表示 this with that 或 this and that。
然后,如果我们想设置最终值,例如路由执行器或 body 的最终值,我使用了 >> 运算符,这应该读作 this uses that。
在服务器端,我决定使用 | 来链接路由或中间件。由于单个请求最多只能触发一个路由,因此这应该读作 this or that。
为了便于使用这些运算符,服务器和客户端包都提供了一些具有这些已定义运算符的常量值:
- 服务器
middleware > (Handler) => Handler:用于定义新的中间件处理器METHOD / 'path' >> (RequestContext) => Response:其中METHOD是提供的 HTTP 方法常量之一,get,post,put,patch,delete,head,options
- Client
http > 'http://host:port':用于创建一个新客户端client.METHOD / 'path':用于创建一个新的 http 请求,该请求也是可 future 的。request & RequestAttribution:用于添加body,json,query或header等属性。RequestAttribution >> dynamic:用于设置特定属性的值。
接下来呢?
老实说,这不应该以任何形式或意义上使用,因为它不具有可读性,而且这种方法可能存在很多我甚至没有想到的陷阱和问题。
充其量,这应该提醒我们,可以偏离“正确”的道路,自己进行一些探索,最好的情况是你会发现一个很酷的概念,最坏的情况是你可能会学到一些新东西。
致谢与感谢
我感谢 Dart Frog 的存在,它是用来构建这个 API 的。
我想特别感谢 Felix Angelov 对这个思想实验的容忍(和调试)。