0

我目前正在研究 SOA 中的前端解决方案,并且在保存域对象时遇到了麻烦。

后端给了我相当大的域对象,它们也被保存为一个整体。另一端的前端将这些数据拆分为多个页面和子页面。

在分享我的实际问题之前,我想提供一些背景信息:

我们系统中的大多数任务都是自动化的,使用流程引擎、与 Web 服务对话和规则引擎。只有当输入数据不正确时才需要前端,以便人们需要更正它。前端的输入由 web 服务保存,当用户认为一切正确时,他将域对象传递回流程引擎。

即将出现的问题的简单示例

域对象(基本上是根实体)

  • 显示在页面 A 上的实体 1(以及来自根实体的一些字段)
  • 实体 2 显示在页面 B

过程识别每个实体中的错误并标记它们。给用户一个任务,前端加载域对象,显示页面 A。用户更正字段,当他移动到页面 B 时,应该保存输入,这样他已经完成的工作不会丢失。

问题:

负责保存域对象的 web 服务将抛出 ValidationException 因为实体 2 仍然有错误。您可能想知道最初是如何保存不正确的数据的?好吧,Web 服务公开了两种保存服务,一种称为“自动”,一种称为“手动”。操作 automaticSave 允许无效数据,因为流程引擎为返回的每个错误创建标记。manualSave 当前不允许出错。

我正在寻找如何解决这个问题的建议。

我认为这应该是 SOA 中一个相当普遍的问题。如果我错了,请纠正我:-)

一种方法是前端中的数据仅存储在会话中,用户必须修复所有错误才能持续存在,但在可用性方面我认为这不是最好的主意。

另一个想法可能是在后端进行部分验证,但这为输入错误数据打开了大门

我的最后一个想法是将流程引擎标记的错误传递给 manualSave,以便 web 服务知道“嘿,这个字段之前有错误,所以当只有这个无效时我不会抛出 ValidationException”

我期待着你的想法。

[更新] 在初始答案之后,我更新了域对象的结构。似乎这个问题可以扩展到“如何设计一个好的网络服务” :-)

4

4 回答 4

2

我认为这里有几个问题。我看到的第一个问题是在您的 Web 服务上有两个不同的操作,用于您试图坚持的聚合。聚合是指将域对象保存在一个事务中(作为一个整体)。最终你的问题是你没有为你试图自动保存的实体强制执行你的不变量。自动保存和手动保存没有区别——您仍在保存。在一个操作中,您说可以忽略否则会使实体无效的属性,而在另一个操作中,您实际上是在强制执行不变量,如果您不包含此数据,它就不是有效的域对象。

我只能假设您这样做是为了获得域对象的部分持久性,以便您可以容纳需要 ID 的多页步骤。自动保存操作保留部分域对象并返回一个 ID,因此您可以执行更新操作(手动保存)以确保正确完整地保存实体。

我认为您将实体数据存储在内存中的最初想法是一种更好的方法。我唯一要补充的是,您的服务持续存在的聚合的 ID 是在客户端上创建的,而不是由您的后端系统创建的。

这允许您从一个页面传递到另一个页面并根据需要更新尽可能多的模型(实体 1 和实体 2),以保持有效的聚合实体。每个视图模型都可以有自己的客户端验证,而不会影响另一个(您仍然可以拥有作为备份运行的服务器端验证)。

当您准备好保存域对象(作为一个整体)时,只需将视图模型(实体 1 和 2)映射到它并保存。然后,您可以确定域对象已考虑所有不变量,并且应该无错误地持续存在。鉴于您已经在客户端创建了 ID,因此无需往返。

于 2013-04-09T08:47:52.083 回答
1

Some observations:

  • (Minor) The names automaticSave and manualSave possibly leak a small amount of implementation details into the interface. These names seem to reflect the behind-the-scenes processing, rather than the client's idea of what is happening.
  • (Major) The same manual save is called twice from different contexts (page A and page B). In both cases the client provides Entity1 and Entity2, indicating that 2 entities should be processed each time. This is misleading & inefficient interface design.

I suggest the following:

  1. (Minor) Rename automaticSave to either backgroundSave or saveRequest. It does asynchronous processing (calls the process engine).
  2. (Minor) Rename manualSave to save. It does synchronous processing (validation, data persistence, error reporting and return response from within the method).
  3. (Major) Add two additional parameters to the save operation (and optionally, to the backgroundSave operation): isEntity1Updated & isEntity2Updated both of type boolean. Only perform validation, data persistence and error reporting for each entity if the corresponding flag is true.

Advantages:

  • Promotes flexibility, reusability & maintainability of your save operations - especially the validation of entities. Interface supports synchronous & asynchronous processing of singular & combined entities.
  • (Minor) Tightens up encapsulation by using client-specific terminology.
  • Allows you to follow your desired user workflow - page A corrections, then save entity 1, then page B corrections, then save entity 2
  • Good usability - page A corrections are not discarded just because of an error on page B (or lack of user follow-through to page B)
  • Can still throw ValidationException during manual save - but only for the relevant entity that was just edited
  • (Minor) Minimises network traffic - if an entity is not updated a null can be passed instead of passing a non-updated entity which will be ignored.
于 2013-04-10T04:46:50.367 回答
1

嗯,关于如何设计一个好的 SOA 的书籍已经写过,所以我不会在这里讨论它。似乎您处于“完成”模式,在这种情况下,我建议当用户提交页面 A 时,使用“自动保存”保存对象,因为您仍然允许错误。只有当用户的任务完成时,您才会使用“manualSave”。我不会以这种方式设计系统,但如果坚持使用这种方式,这似乎是最合理的方式,因为这符合服务客户的期望和服务合同。

于 2013-04-14T23:08:30.750 回答
0

我想帮助你,但我需要了解更多细节。

只有当输入数据不正确时才需要前端,以便人们需要更正它。前端的输入由 web 服务保存,当用户认为一切正确时,他将域对象传递回流程引擎。

域对象是什么意思?后端不能返回任何域对象,因为如果系统分层正确,域对象将保留在域层中,并且您正在与 API 层/服务层对话,所以您最多得到的是域对象。你可能看起来一样,但语义完全不同。

所以当你拿到代表一个领域对象的对象时,你说的是实体 1 和实体 2,但它们是什么?什么协议(REST,SOAP)?

您也可以向我们提供网络服务的方法吗,您正在参考验证服务和其他保存服务,所以我只想确保我了解所有内容。

一种方法是前端中的数据仅存储在会话中,用户必须修复所有错误才能持续存在,但在可用性方面我认为这不是最好的主意。

到目前为止,根据您的输入,这是唯一的方法,但不要忘记您总是有两个验证阶段,在前端和域中。

谢谢

更新

按照我的回复:

为了有效地使用 SOA,架构必须满足以下要求: 不同系统和编程语言之间的互操作性,为不同平台上的应用程序之间通过通信协议进行集成提供了基础。这种通信的一个例子取决于消息的概念。跨定义的消息通道使用消息降低了最终应用程序的复杂性,从而允许应用程序的开发人员专注于真正的应用程序功能,而不是通信协议的复杂需求。渴望建立资源联盟。建立和维护到联合数据库系统的数据流。这允许开发新功能以引用每个数据元素的通用业务格式

公平地说,调用 Web 服务的 Web 服务就是 SOA。

于 2013-04-09T22:08:12.237 回答