RESTful API 是移动/集成应用程序所需的技术,但它们的额外费用可能不适用于 Web 应用程序。问题是,移动/集成需求可能会在稍后出现,而系统的架构并未做出响应。
但是,我们能否想象一种技术可以使创建 API 比构建单体应用程序 更快、更简单 ?这种技术将改变建筑经济学的游戏规则。
业务驱动力:对速度的需求
像 CA 这样的行业领导者开创了 软件驱动业务 的愿景。他们有说服力地指出,战略业务优势在于上市时间和决策时间:
“揭示了应用经济 对速度的需求 。随着公司转型为软件驱动型企业,将高质量的应用程序更快地推向市场成为最关键的差异化因素之一。”
我们都痛苦地意识到业务用户对创建和修改系统需要多长时间感到沮丧。他们看到看起来几乎像电子表格一样简单的问题需要几周……到几个月的时间。
IT 部门怎么可能花费数月时间来构建一个需要数天才能处理电子表格的系统?
技术现实:API 是正确的……但价格昂贵
在此背景下,考虑构建一个 Web 项目。众所周知,RESTful API 提供健壮的、面向网络的数据库访问。这样的体系结构使组织能够很好地满足未来的需求,例如移动或集成。
但是 REST API 远不止是基本的数据访问。 “SQL 传递”——简单地重新定义 SQL 数据——不满足 企业级扩展、集成和实施的要求 :
- 规模 ——API 需要分页来处理大型结果集,需要嵌套文档来减少延迟,需要乐观锁定来确保并发性。这些不在简单的 SQL 传递中提供——您必须手动对它们进行编程。
- 集成 ——向导可以从模式对象生成 API,但它不能处理多个数据库,也不能集成非 SQL 数据源,例如 ERP、其他 RESTful 服务或 NoSQL。
- 强制执行 ——API 需要强制执行我们的安全性(下至行级别)和数据的完整性。这些都是重要的任务,遗憾的是,它们通常放在无法共享的客户端按钮中。
提供这些企业级服务需要大量时间、专业知识和费用。所以我们在“正确”和上市时间之间有一个经典的碰撞:
我们知道 REST 是一种更好的方法。
但是时间压力驱使我们采用传统方法。
胖客户端:按钮中的逻辑(和成本)
时间压力并不止于 API,它们直接影响到应用程序设计。将完整性和安全逻辑集中到服务中比较麻烦,因此我们只是将其放在“按钮”(UI 控制器)中。这有时称为胖客户端(不要与富客户端混淆),一种反模式:
- 胖客户端复制逻辑,导致错误。例如,下新订单可能会检查信用,但“选择不同产品”按钮可能不会。
- Fat Client 可以通过应该在更靠近数据库的地方发出的额外数据库调用来降低性能。
- 胖客户端逻辑不能轻易提取到未来的服务中以供集成或移动应用程序访问;通常需要重写。
- 胖客户端逻辑不在异构 Web 客户端技术之间共享。
制度化问题
尽管如此,大多数组织被迫应对时间压力,接受业务需求凌驾于技术正确性之上。很难说这是错误的。考虑到当前的技术形势,这可能是正确的商业决策。
一些组织接受时间与质量的必然性,甚至将问题 制度化 。定义2个架构标准:
- 部门级: 对于小型战术项目,使用熟悉的 RAD 工具,快速完成工作。
- 企业: 对于大型战略项目,使用不同的方法(例如 J2EE)来驱动面向服务的架构
这是相当可怕的。我们承认时间和质量不可避免地存在冲突,因此继续创建面临动员/整合/扩展问题、支持多种技术(学习曲线、员工专业化)等的次优系统。
但是,如果正确地做同样快呢?
事实上,如果做对了真的能 省钱呢?
需要的是能够消除时间与质量权衡的技术。这有可能改变经济驱动软件架构。
让“正确”变得容易:Instant Enterprise REST
这样的技术是存在的。我们称之为 Instant Enterprise REST。
为了实现软件驱动业务,我们需要提高从编码到业务的抽象级别。我们需要业务驱动软件。
它由3个核心技术组成:
- 企业模式自动化 ——创建内置企业级可扩展性的 API(分页、嵌套文档、乐观锁定等)
- 声明式 ——在简单的点击式 UI 中使用类似电子表格的规则指定您的 API、集成和执行策略
- 可扩展性 ——使 RESTful API 能够通过标准的服务器端 JavaScript 在 JVM 内部或外部调用您现有的逻辑。
这 3 种技术的结合使您能够以 10 倍的速度为数据库后端创建 RESTful API——您系统的一半。让我们在下面简要检查一下。
技术一:企业模式自动化
数据域中有众所周知的模式,描述了数据结构和通过 SQL 的访问。还有用于在 RESTful 服务上下文中管理 SQL 数据的众所周知的模式。
众所周知的模式可以自动化。让我们想象一个服务(例如,通过浏览器访问的服务器)来自动化这些模式,如下所述, 只需将服务连接到数据库:
- 模式发现——表、视图、存储过程: 系统为每个模式对象创建一个完整的(默认)API。请注意,这包括存储过程,它通常代表一项重大投资。
- 企业模式自动化: 由此产生的 API 为过滤、排序、分页、乐观锁定、处理生成的键等提供众所周知的服务。
因此,该服务立即提供了默认的企业级 API。因此,在您的项目几秒钟内,您就可以测试正在运行的 API:
还不够,还没有完成,但这是一个很好的开始。
技术 2:声明式
声明是关键(“是什么,而不是如何”)。它对具有易于理解的基础模式的领域产生了显着影响。 Max Tardiveau 说得很好:
任何 可以 声明的, 都将 是声明的。
例如,电子表格是声明性的——它们催生了 PC 行业。 SQL 是声明式的——它本身就是一个行业。两个改变游戏规则的人。
因此,挑战在于将声明精神应用于 REST 集成和实施。风险很高——成功可以带来惊人的敏捷性。
声明式集成:多数据库自定义 API,点击
Enterprise Pattern Automation 提供了一个良好的开端,但 API 并不丰富。它是一个扁平的单表 API,实际上只是“重新定义”的 SQL。我们真正需要的是
- 嵌套文档 ——在 单个调用 中返回多种类型(例如,一个订单、一个项目列表和一个联系人姓名列表)可以减少延迟(相对于每种类型的单独调用)。 REST 非常适合这个。
- 多数据库 API ——RESTful 服务器提供了在单个调用中集成多个数据库的机会,从而使客户端免受底层复杂性的影响。
嵌套文档很简单:只需选择表格(通过用户界面或命令行)即可定义它们。外键用于默认连接。添加选择/别名列的能力,我们正在走向一个非常好的 API。
但是没有外键的数据库呢?还是多数据库 API?
利用 模式并不意味着我们 受限 于它。我们需要做的就是:
- 提供一种方法来为服务定义“虚拟”外键(即存储在模式之外)
- 将其扩展到数据库之间的外键
我们现在拥有丰富的多数据库 API。如下所示以声明方式定义,无需代码,几分钟内即可运行,可为客户端开发做好准备:
声明式执行:完整性逻辑,具有类似电子表格的规则
所以现在考虑执行,特别是数据库完整性。任何项目的一个非常重要的部分是定义数据处理方式的多表验证和计算。
“Your code goes here”意思是很多代码。我们需要一个更强大、更具声明性的范例。
在电子表格中,您将表达式分配给单元格。每当引用的数据发生更改时,单元格都会更新。由于单元格引用可以链接,一系列简单的表达式可以解决非常复杂的问题。
如果我们对数据库数据做同样的事情呢?我们可以将派生表达式分配给列,将验证表达式分配给表。然后,API 可以“监视”更改引用列的请求,并(有效地)重新计算计算列。就像在电子表格中一样,对链接和正确排序的支持是必需且隐含的。
为了解决 多表 逻辑,此类表达式需要解决对相关表的引用。只有在这一点上,逻辑才变得非常强大。
让我们举个例子。要在 Customer / Purchaseorder / Lineitem 应用程序中 检查信用 ,我们可以定义类似电子表格的表达式,例如:
实际上有一个声明式的子分支来解决这个问题:响应式编程。这是 声明性的 , 因为您不需要编写观察者处理程序的代码。
结果是上面的逻辑 完全可以执行。 无需编写更改检测/更改依赖性代码——它由 API 自动调用和强制执行以响应 RESTful 更新。 SQL 处理也是隐式的,包括底层优化(缓存、修剪等)。
影响是巨大的——上面的 5 个表达式表达了与数百行代码相同的逻辑。这是一个巨大的 40X 更简洁 。改变游戏规则。
并且质量上升,因为规则是自动应用的。
声明式执行:安全、角色/表的过滤器表达式
我们可以提供一种类似的安全方法:为角色(如 SalesRep)定义过滤器表达式,以便当角色访问表时,API 添加过滤器。这样,具有该角色的用户只能看到他们被授权的行。
技术 3:基于标准的可扩展性
声明式很棒,但您可能会想“好吧,但您无法通过声明式解决 所有 问题”。你是对的。
商业价值要求我们将声明性方法与熟悉的、基于标准的程序性方法集成在一起,并使我们能够集成现有软件。
自动 JavaScript 对象模型
许多项目的第一阶段是构建一个 ORM,用于自然编程访问数据:JPA、Hibernate、Entity Framework。这不是一个小项目,并且在发生变化时维护起来很麻烦。
事实上,对象模型可以直接从模式创建。因此,您将拥有一个用于 Purchaseorder、Lineitem 等的对象类型。该模型提供对属性和相关数据以及持久性服务的访问。然后您可以如下所示使用它。
JavaScript 似乎是最好的语言选择:跨技术基础合理(每个人都使用 JavaScript),而且它的动态特性消除了代码生成的麻烦。
JavaScript 事件
除了访问器和持久性之外,JavaScript 对象是 逻辑感知的。 也就是说,上面的保存操作执行与 OrderAudit(例如,更新者)和 JavaScript 事件 关联的任何 规则 。
以下是
PurchaseOrder
对象的示例事件,您可以在其中通过系统提供的
row
变量访问 JavaScript 对象模型:
可扩展逻辑
审计是一种常见的模式。应该可以用 通用的 方式一次性解决这个问题,然后重新使用它(例如,审计员工、订单等)。
因此,Instant Enterprise REST 应该使您能够提供可扩展逻辑——加载您自己的 JavaScript 代码并调用它。所以,上面的代码可以变成:
MyLibrary.auditFromTo(orderRow, "OrderAudit");
其中 auditFromTo 创建 OrderAudit 的一个实例,设置外键,设置类似名称的属性,并保存它。
可插拔认证
大多数组织都有现有的数据存储来识别用户及其角色,例如 Active Directory、LDAP、OAuth 等。安全性应该与这些系统集成,作为强制行/列访问的功能。
标准部署
最后,系统应该以熟悉的方式部署:在云端可用,或在本地虚拟设备或 war 文件中可用。标准还支持与相关的关键基础设施集成,例如 API 管理、ERP 系统等。
简单的客户端连接
REST 是一种网络服务。它只是一个 HTTP 调用,可以由任何语言发出。序列化的响应(结果)通常是 JSON,可以用任何语言轻松解析。
甚至还有用于记录 REST 的标准,例如 Swagger。这导致了一个有价值的生态系统,其中包括用于客户端工件的 SDK 生成,如 Java POJO 或 C# POCO。这使得在 Web 应用程序中使用 RESTful API 变得容易。
Instant Enterprise REST:比“胖客户端”更快/更简单
Instant Enterprise REST 改变了架构的经济性,它主要以 业务术语 而不是 技术术语 来创建我们软件的重要部分。