Web 服务“强制/可选”领域:XSD 设计时与运行时
我们目前正在构建一堆SOAP Web Service来前端访问各种后端系统。
在定义请求/响应消息 XML 时,我们看到多个服务需要具有不同“强制/可选”字段的“帐户”对象。
我们应该如何定义和强制验证同一消息上的这些“强制/可选”字段?我看到这些选项
1) 通过创建不同的“帐户”复合类型来强制使用 XSD 进行验证
优点:设计时清晰。
缺点:对象类型激增,对象重用较少,
2)通过扩展+限制单个基本“帐户”类型来强制使用 XSD 进行验证
优点:设计时清晰。
缺点:不确定是否支持扩展+限制功能(java、.Net)
3)使用单个“帐户”类型并在运行时(即在代码中)强制验证。
优点:简单
缺点:没有设计时验证。需要通过规范文档传达现场需求。
对此你有什么想法?
We are currently building a pile of SOAP Web Service to front the access of various backend systems.
While defining our Request/Response message XML, we see multiple services needing the ‘Account’ object with different ‘mandatory/optional’ fields.
How should we define and enforce the validation of these ‘mandatory/optional’ fields on the same Message? I see these options
1) Enforce validation with XSD by creating different 'Account' Complexe Type
Pros : Design time clarity.
Cons : proliferation of Object Type, Less reuse of Object,
2) Enforce validation with XSD by Extending+Restriction a single base 'Account' type
Pros : Design time clarity.
Cons : Not sure of the support of the Extend+Restriction feature (java, .Net)
3) Using a single 'Account' type and enforcing validation in runtime (ie in the Code).
Pros: Simple
Cons: No design time validation. Need to communicate field requirements via a specification doc.
What are you’re thoughts on that?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我必须假设:i)您所说的一些可选字段实际上是不适用于(没有意义)所有帐户的字段,ii)我们不是在谈论琐碎的场景(例如两种类型的帐户)每种东西都有 2 个字段)。
首先,我想说,除非你真的很幸运,从需求的角度来看,否则无论你选择什么选项,你最终都会得到某种“运行时验证”。 XML Schema无法表达一些常见的数据验证需求,例如跨字段验证;或者仅仅因为 XML 中的数据不足以提供验证消息完整性的规则(消息中的数据是取消/编组 XML 时可用数据的子集)。
其次,我会避免通过限制派生新的复杂类型;从创作的角度来看,您在重用方面没有取得太多成就,并且最终可能会遇到 XSD 如何将其解释为代码工具的问题。我喜欢认为通过限制推导的初衷是为了给人们在xsd:redefine场景下使用提供一个工具;对于那些不想摆弄其他人编写的 XML 模式的人来说。如果某人拥有(作者)该模式,则可以通过首先定义“较小”对象并从中扩展来解决限制的需要。
至于“对象的扩散”,你也可以通过选项#2 得到它(与#1 相比);我的意思是,我所知道的所有工具都会为 XSD 中的每个命名(全局)复杂类型创建一个类;因此,如果您必须拥有三种类型的帐户,则场景#1 中您将拥有三个帐户,如果您选择从一个或多个基类扩展,则需要四个左右;后者的最坏情况是当您需要三个专业化(如果您愿意,可以具体化);无论如何,根据我的经验,现实生活场景的差异并不会真正以某种方式影响决策。
在 XML Schema 中扩展基本类型有利于重用;然而,重用会带来耦合;如果您从前向/后向兼容性的角度进行分析,则扩展基本类型中的某些内容可能会扰乱不想更改的服务客户端的某些 XML 解组(反序列化)他们的代码库,但您只想为所有人维护一个 Web 服务端点;在这种情况下,依赖于合成器末尾的 xsd:any (xsd:sequence) 的前向兼容性策略将在您的第一个版本中变得毫无用处,该版本会扩展您的基本类型。
还有更多;因此,我认为没有正确的答案,只是针对您通过设置优点/缺点似乎暗示的标准。
下面我的所有首选选项都假设您高度重视确保服务的前向/后向兼容性的要求,并且您希望最大限度地降低客户处理您的服务的成本(由于 XML 架构更改)。
我想说,如果您的所有域(特别是帐户)都可以完全建模(假设将来基本上没有变化)并且有足够的通用性来证明重用是合理的,那么就去使用选项#2。否则,请选择选项 #1,因为我还没有看到不会改变的事情...
如果您的域建模可以完成 80% 或更多(或您认为很高的某个数字)并且< /strong> 有足够的通用性来证明重用的合理性,那么我仍然会选择选项#2,但需要注意的是,跨帐户的公共属性的任何未来扩展都必须应用于每个单独的帐户(基本上将您的选项变成混合帐户) ,通过执行#1)。
对于其他任何事情,我都会选择#1。哇,我不敢相信这一切都是我写的......
I would have to assume that: i) some of what you would call optional fields are actually fields that are not applicable (don't make sense) to all accounts and ii) we're not talking trivial scenarios (like two type of accounts with 2 fields each-kind of thing).
Firstly, I would say that unless you're really lucky, from a requirements perspective, then you're going to end up with some sort of "validation in runtime" no matter what option you're going with. XML Schema can't express some common data validation requirements, such as cross field validation; or simply because the data in your XML is not sufficient to feed the rules to validate the integrity of the message (the data in the message being a subset on what's available at the time the XML is being un/marshalled).
Secondly, I would avoid deriving new complex types through restricton; from an authoring perspective you don't achieve much in terms of reuse, and you might end up with problems in how that is interpreted by your XSD to code tooling. I like to think that the original intention of deriving through restriction was to provide a tool for people to use in xsd:redefine scenarios; for people that wouldn't want to fiddle with XML Schemas that were authored by someone else. If one owns (authors) the schema, one can work around the need to restrict by defining the "lesser" object first and extend from that.
As to the "proliferation of objects", you are kind of getting that with option #2 as well (when compared with #1); what I mean by that, all the tools I know will create a class for each named (global) complex type you have in your XSD; so if you have to have three type of accounts, you'll have three for scenario #1, and four, or so, if you choose to extend from one, or so, base classes; a worst case scenario for the later would be when you need three specializations (concrete if you wish); anyway, from my experience, the difference in real life scenarios is not something that would really tip the decision one way or the other.
Extending base types in XML Schema is good for reuse; however, reuse brings coupling; if you're analysing this from a forward/backward compatibility point of view, extending something in the base type could mess up some of the unmarshalling (deserialization) of the XML for clients of your service(s) that don't want to change their code base, yet you want to maintain only one Web Service endpoint for all; in this case, a forward-compatibility strategy that relies on an xsd:any at the end of a compositor (xsd:sequence) would be rendered useless in your first release that goes and extends your base type.
There is even more; because of this, I don't think there's a correct answer, just for the criteria you seem to imply by setting your pro/cons.
All of my preferred options below assume that you put high value on the requirement to ensure forward/backward compatibility of your services, and you want to minimize the cost of your clients having to deal with your services (because of XML Schema changes).
I would say that if all your domain (accounts in particular) can be fully modeled (assume no future change basically) and that there is enough commonality to justify reuse, then go with option #2. Otherwise, go with option #1 since I have yet to see things that don't change...
If the modeling of your domain can be done 80% or more (or some number that you think is high) and that there is enough commonality to justify reuse, then I would still go with option #2, with the caveat that any future extensions for common attributes across accounts, must be applied for each individual account (basically turning your option into a hybrid, by doing #1).
For anything else, I would go #1. Whew, I can't believe I wrote all of this...