API设计:公开XML或对象#2

我最近问了这个问题: 暴露XML或对象 – 感谢所有回复。

有一点需要澄清。

  • API将始终远程访问(即作为服务),最有可能通过Web服务或WCF访问。

我同意理论上一个强类型API将对象暴露为输入/输出是正确的方法。 但是,我觉得仍有一个论据要暴露XML。 我认为使用XML的原因是:

  1. 业务规则可以由Schematron的业务分析师编写。
  2. 接口是弱类型的,但只要它被调用,就可以根据数据和业务规则validation数据。
  3. 该服务的实现将更简单。 不需要创建域对象模型。
  4. XML模式已经定义(我们有一个模式的数据字典)。
  5. 使用Web服务技术意味着基于XML的API不需要随着新车“类型”的添加而改变,例如

    void AddNewCar( string newCarXml ) string[] GetCars( /* some query conditions */ ) 

    如果我们使用基于对象的API,那么添加新类型将需要一个新的查询方法来定义可以返回的可能的派生类型(请参阅扩展Web服务 )。 像这样更新Web服务需要重建和重新部署此服务和所有现有客户端。

基于对象的API给我们带来了什么? 强类型声明性接口。 它不提供比XML更多的抽象(XML本身就是一个抽象)。 基于对象的API的成本是多少? 它需要一整套域对象,这些对象需要业务规则和数据validation。

那么,我的问题是什么? 给我一个不可失败的,无可争议的理由,为什么我应该与对象一起去。

  • 对象可以表现得更好(在这里思考二进制序列化)。
  • 对象可以具有更强的简单类型validation。
  • 对象允许您将validation和业务规则放在更接近数据结构定义的位置。
  • 对象本质上允许您编写更简单的业务规则和validation,因为大部分内容都嵌入在对象定义本身中。
  • 对象也可以定义行为。
  • .Net可以很容易地将对象转换为Xml并通过序列化再次返回,从而为对象提供与xml大部分相同的好处。

如果您正在寻找支持XML的论据(而不是我特别支持XML):

  • 在数据方面,公开XML并提供XSD是不言自明的。 您可以传递该表单中的所有数据,它是自我记录的,并且可以合理地简单地validation。

  • 我可以针对我的数据库或代码模型编写一堆安全代码,并且可以以自包含且安全的方式将数据发布到需要最少文档或解释的其他业务单元。

  • 它易于阅读,通常您可以像阅读文档或代码注释一样轻松阅读。

然而,反对它的论点继续……以命名最严重的罪犯:

  • 过分冗长。
  • 巨大的网络开销。
  • 需要了解一项额外的技术,也许是不必要的(?)。
  • 你创造的东西越复杂,就越容易出错。

实际上任何类型的输入都存在强类型,因为程序员不会犯任何愚蠢的错误(例如,将字符串传递给期望int等的函数)。 最重要的是,这在编译时发生,并且在运行时不会花费任何成本,从而通过避免运行时检查(例如,适当的强制转换)和避免运行时非托管代码的exception行为来生成有效的代码。

就像你说的那样,Xml可以用来定义替换对象模型,但是这个对象模型需要在运行时进行相同的检查,以保证在一定程度上的可靠性。 但是这有一定的运行时开销。

话虽如此,我想说的是最后的选择是你的。 您是否愿意放弃“僵硬”物体模型所提供的安全性(有时是安心),或者您是否会更灵活地使用更灵活但可以拍摄自己的足部物体模型? XML需要更强的程序员纪律和警觉性(因此使其成为使用IMHO的苦差事)。

“基于对象”的API并不像你想象的那么严格,自动生成的XML模式可能不会做你真正想要它们做的事情。 基于对象的API如果设计得很好,可以像基于XML的API一样灵活。 动态类型有时也会有所帮助。

当您公开纯XML时,所有客户端都需要编写代码来生成和解析该XML。 在某些语言中很容易,在其他语言中很容易。

但是大多数语言都有Web服务API,可以在几秒钟内获取wsdl / xsd并生成完整的客户端库。 当然,他们必须编写一个映射实用程序来从他们的内部模型映射到您的模型以与您进行交互,但这是可以预期的。

您的Web服务将在内部处理所有Object < - > XML内容(对于客户端的视图),您不必担心SOAP等等。 你将定义你的界面:

 void addCar(Car newCar); Car getCar(String make, String model, String year); void removeCar(...); List getAllCars(); 

这对你的客户来说很有意义。 他们抓住你的wsdl并用Java,C#,PHP,Python等生成他们的客户端库。

没有什么可以阻止你添加:

 int addCarXML(String carXML); String getCarXML(int carID); 

但是为什么要添加两个级别的webservice cruft – 首先是wsdl,然后是XML模式的xsds …

在Web上查看有关Contract-First Design的文章,Spring网站就是一个很好的例子。 我正在开发一个新的网站,并采用了与XML Schema一起开始的方法,并使用它来设计我的应用程序域模型。 XML非常适合在不同系统甚至应用程序层之间发送数据。 它与编程语言无关,并且有许多工具可用于编辑,设计和实现基于XML的设计。

它是冗长的,但在事物的计划中,冗长是一个小麻烦。 它可以创建大文件,只需压缩它。 处理它有更多的开销,但我们开发人员总是交易纯粹的性能,易于使用,可维护性,可扩展性等。

这是另一个随机的想法 – 既不使用;-p我正在考虑其他交换格式。 我最近使用协议缓冲区做了很多工作 – 这提供了契约优先使用(通过“.proto”定义),但设计时考虑了安全可扩展性 – 即您可以设计事物以通过意外数据而不会破坏或者损失。 不幸的是,主协议缓冲区规范实际上并不包含inheritance,但我的实现(protobuf-net)通过扩展来消除它。

它是否足够成熟取决于场景 – 我只是认为它可能是有趣的。 顺便说一下,它(protobuf-net)也插入到WCF中以方便预卷RPC堆栈;-p