react中的可组合模式#take-1
构建react应用的功能性方法。如何让API调用变得更好?
玩乐高对许多不同年龄段、不同教育或社会背景的人都有吸引力。将砖块点击在一起,形成更复杂的物体,既不需要艺术天赋,也不需要技术知识。玩乐高最好的部分是,唯一限制你的是你自己的想象力。
那么,乐高的核心口号是什么?
创造一些积木,然后用它们来玩。
这种模式在其他工业领域也很适用。例如,家具制造。宜家创造了模块化的家具套装,并将其出售给他们的客户,同时还提供手册,说明如何将基本单元构建和连接成所需的、自我设计的套装。
有趣的事实:数学教授Søren Eilers计算出,有超过 9.15亿种方式 来组合六块八爪的乐高砖。
1957年,乐高积木的互锁原理诞生了,1958年,螺柱和耦合系统获得了专利,这为建成的作品增加了很大的稳定性。而这也使它们变成了今天孩子们使用的乐高砖。
自从子程序出现在计算机编程的早期尝试中以来,开发人员一直试图将其代码模块化。如果我们能把软件当作乐高积木,那么我们就可以混合和匹配各种碎片,通过简单地把它们的组件拼接在一起来构建灵活的应用程序。然而,拥抱乐高哲学有一个主要问题。
我们没有像lego那样的螺柱和耦合的标准。而我们希望我们的函数/类/程序能有足够的通用性来处理所有可能的情况。我们怎么能把一个程序设计得如此通用,以至于它可以被任何其他程序所消费。这似乎是一个不可能的任务,不是吗?
作为一个软件工匠,我们有自己的设计理念可以使用。
S.O.L.I.D是软件工程中使用的一个缩写,描述了一套面向对象的设计原则。当一个系统通过使用这些原则来实现时,代码库是可理解的、可重用的、可测试的、可维护的和灵活的。这个概念起源于Robert C. Martin。从那时起,它就被软件工程师们采用并使用。
不要重复自己(DRY)--当然,这是最容易理解的软件原则,但并不是所有的事情都那么明显。
我相信以上2个原则的组合能压制住真理的蟾蜍。
让我们看看它是否真的可行
U宁静的故事。 鉴于我有一个按钮
*Fetch*,在页面上,当我点击*Fetch*,来自一个api的用户应该显示在下面的表格中
听起来相当直截了当。让我们从一开始就做出一些框架/包的选择来启动这个应用。我将使用create-react-app来搭建脚手架,使用fetch来进行api调用。我将使用托管在reqres.in/的mock-users-api。
现在,如果我们看一下用户故事,有3个具体的元素是我们必须要建立的
- 创建一个客户端来进行http调用。
- 因为这是一个react应用,所以要将api的响应存储在一个状态中。然后,这将触发一个渲染周期,导致UI组件重新渲染。
- 创建一个UI组件,其中有一个按钮
Fetch。将UI组件与上面的2个点击整合起来。
客户端
这段代码几乎是不言自明的。我们有一个客户端抽象,它有一个invoke 方法。在引擎盖下,invoke 方法使用fetch 来进行http调用,并将响应转换为json来返回给调用者。
钩子
为了让反应组件渲染数据,响应必须被存储在一个状态中,这将触发渲染周期。因此,让我们建立一个钩子,消费我们的客户端useJsonApi ,消费一个客户端,进行api调用,并将响应和元数据存储在状态中;简单-容易的柠檬汁。
应用程序
这将在屏幕上呈现一个按钮,点击后将从api中获取用户信息,并在一个div标签中呈现结果。仔细看一下这两个函数是如何组成的。现在的实现非常简单,但请注意......它将会变得非常有趣。
使改变变得容易的一个基本策略是将软件设计模块化 - Martin Fowler
***假设。***用户是由一些其他进程异步创建的。所以api有可能在该操作仍在进行时返回一个
*404*而该操作仍在进行中。 用户故事。 考虑到一个用户的存在,当我点击*Fetch*时,用户应该显示在下表中。客户端
由于我们不想因为这个设计选择而影响用户体验,轮询是最简单的客户端实现。仔细看一下retriableJsonApiClient 的签名。它接受可检索的参数和一个Client ,并返回一个Client 。在引擎盖下,我们把invoke 方法包装成一个可检索的块。现在它将等待,直到重试用尽或重试条件返回错误。一旦完成,它将解决这个承诺。
这就是我们消费它的方式
我们创建了一个100ms延迟的retriableApi ,重复5次,直到我们得到一个200 ok 响应。然后把jsonApiClient 包在一个retriableApi 里面,再把它传给useJsonApi
所以,刚刚发生了什么。我们给客户端增加了更多的功能,而没有改变它的源代码。这些功能现在是可组合的。
虽然这不是一个用户故事,但是一个更好的重试实现可以是一个指数后退的实现。
这就是我们可以使用它的方法
这是另一个实现,用于记录请求和响应的客户端
这就是我们可以使用它的方法
深吸一口气,想一想我们取得了什么。我们想出了不同风味的json-api-client ,而没有像generic-json-api-client 那样承诺一个单一的实现。同时,客户端的消费者,在这种情况下,App ,可以组成不同的实现,只要它们符合合同并创建不同的抽象。
我们在开始时谈到的乐高咒语是什么?
创造一些积木,然后用它们来玩。
快乐的日子。所以,我们看到了我们如何组成json-api-client的不同实现。接下来,我们将探索如何组成不同的钩子实现。请继续关注#take-2