0

REST与RPC = 面向对象和函数式编程

 9 months ago
source link: https://www.jdon.com/70772.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

REST与RPC = 面向对象和函数式编程

REST 与 RPC 的争论:

REST API ! = HTTP 远程过程调用
作为开发人员,每当需要 API 时,我们常听到的一句话就是 "哦,我们可以为此开发一个 REST API"。好吧,这没什么不好。
但是,

  • 如果需求是可操作的呢?向服务器发送关于客户端操作的更新,比如点击按钮。
  • 或者获取一些涉及计算的数据--比如获取查询结果,

这些可以称为 REST API 吗?

GET /toptenstories

POST /sendaclientupdate

答案是 "否"!这些是远程过程调用!至于这是不是真正的远程过程调用,另当别论,因为远程过程调用的主要特点是位置透明。客户端进行本地函数调用,但实际上是跳转网络在服务器上执行。但为了简单起见,我还是称之为远程过程调用(Remote Procedure Invocation)。在这里,HTTP 语义并没有被破坏,我使用 GET 来读取一些内容,而使用 POST 来执行一些可能会改变服务器状态的操作。

REST 的核心是资源--资源建模。由于 HTTP 无处不在,我们可以利用 HTTP 工具包来实现 REST 系统。在上述示例中,我们使用 HTTP 作为调用远程程序的传输方式。这就带来了紧密耦合!

REST 的关键特性之一是 HATEOAS,它被认为是使系统完全 REST 化的特性。HATEOAS 是 "超媒体作为应用状态引擎"(Hypermedia as the Engine of Application State)的缩写。它定义了每个资源的 "下一步"。

对于 REST 应用程序接口:

  1. 我们首先需要一个端点,如 https://myrestapi.mydomain.com。
  2. 然后,客户端就可以像浏览网站一样 "浏览 "应用程序接口。
  3. 对资源的每个 GET 请求都会获取有关资源的信息、可对资源执行的操作以及作为超媒体(链接)的相关资源信息。

这确保了客户端和服务器之间的低耦合性。服务器可以更改资源网址,由于客户端使用超媒体来 "浏览 "应用程序,因此资源网址的更改不会影响客户端。

REST != JSON over HTTP
EST 有六个约束条件。
REST 是一种分布式系统的架构风格,如在 HTTP 上运行的网络。
REST 的提出是为了规范在 HTTP 上运行的网络。因此,REST 和 HTTP 有相似之处,也有交叉之处。

但作为一个概念,REST 并不要求以 HTTP 作为传输方式。REST 的要点是使用资源表示法传输状态(应用程序状态和资源状态)。资源可以用 JSON、XML、文本、媒体等多种格式表示。REST 并不规定 JSON 为格式。RESTful 系统的关键在于真正遵守六大约束。

面向过程vs.面向对象
面向过程是一种旨在实现代码重用的机制。您将想要重用的代码包装在可以参数化的签名中,您的工作效率就会立即大大提高。

过程是无状态的。可重用代码对您传递给它的参数进行操作,并且可以选择返回结果。
过程化代码:
DepositMoney(account, amount)

面向对象编程迫使开发人员区分影响过程行为的值或 OOP 术语中的方法以及正在修改的应用程序状态。
面向对象代码:
account.DepositMoney(amount)

两者比较:

  • OOP 方法:非常清楚地表明,account 正在被 amount 更改。
  • 面向过程方法:在更复杂的过程和交互中,开发人员理解可能会变得困难。

REST = OOP

  • Rest中Resource资源等同于OOP的Object对象,只不过是基于Web的系统。
  • 资源与对象的主要区别在于,资源是通过 URL 而不是通过某种引用或指针来访问的。

"面向资源 "对开发人员的好处与 "面向对象 "相同,因为它明确区分了被操作的系统状态和进行操作的方法参数。

HTTP:

POST /accounts/23434/depositMoney
Content-Type: application/json
{
  "amount": 100
}
=>
200 OK

然而,很多人会认为这 "不是 RESTful"。

RESTful是将账户“交易”专门建模为“资源”,以便使用 POST 方法创建事务。

POST /accounts/23434/transactions
Content-Type: application/json
{
 "type": "deposit"
  "amount": 100
}
=>
201 OK

虽然后一种设计确实为消费者提供了根据账户查询交易的机会,但它迫使 API 设计者暴露了他们可能并不想支持的资源。

所以这两者都是可行的,符合RESTful

可将 HTTP 方法视为 CRUD 的映射,任何其他动词都违反了这一约束。

在 URL 中加入一个动词并不能让 API 突然变成 RPC。

banq注:其实REST和RPC没有必要分得那么清楚,动词在主语名词后面,还是在名词之前,这取决于上下文

  • 主语思维 是面向对象致命缺点,让主语变成无所不能的上帝,
  • 以动词为先的函数式编程虽然是面向过程的再包装,但是约束比面向过程强很多,在形式逻辑上存在很多要求约束才是函数式编程。

过程化代码:
DepositMoney(account, amount)
这行代码只是过程,不是函数式的,因为有两个方法参数:account, amount,比较歧义,如果变成:
depositMoney(depositCommand)
就清晰清楚了,动作动词depositMoney说明是存款,参数类型是depositCommand命令,命令的意思存款进入指定账户多少钱,amount多少金额包含在depositCommand中。

面向对象代码:account.DepositMoney(amount)
表面上很清晰:以账户为主语,实现存款多少钱,实际上,存款多少钱只是账户的一个上下文场景,账户还有取款多少钱这个上下文。
如果将每个上下文场景涉及的动作都建模到账户中,账户变成一个万能跨越上下文的上帝对象,这是不符合DDD限界上下文中聚合概念。
聚合对象应该被置于上下文BC内,而不是凌驾其上。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK