6

在我工作的这些年里,我注意到了一种我认为是反模式的明显趋势:将内部数据维护为大的 XML 字符串。尽管两个最严重的违规者非常相似,但我已经看到了很多不同的方法。

网络服务

第一个应用程序是 Web 服务,它提供对 SQL 数据库中潜在的大量数据的访问。在启动时,它或多或少地从数据库中提取所有数据,并将其作为 XML 存储在内存中。(三次。)此应用程序的所有者称其为缓存。我称之为慢,因为在解决这个问题时遇到的每一个性能问题都可以直接追溯到这个东西。(这是一个公司环境,毫无疑问,客户端会因为性能故障而不是服务而受到指责。)这个应用程序确实使用了 XML DOM。

进口商

第二个应用程序读取作为从第三方数据库导出的结果而生成的 XML 文件。目标是将这些数据导入专有系统(归我们所有)。执行此操作的应用程序读取整个 XML 文件,并在整个导入序列中维护至少两个、有时多达四个 XML 文件的副本。请注意,数据可以在导入之前进行操作、转换和配置,因此导入器在其整个生命周期内都拥有 XML 格式的数据。不出所料,当提供一个中等大小的 XML 文件时,这个导入器就会爆炸。此应用程序仅将 XML DOM 用于其中一个副本,其余的都是原始 XML 字符串。

我对常识的理解表明,XML不是一种在内存中保存数据的好格式,而是数据在输出/传输时应转换为 XML,并在读入和导入时转换为内部数据结构。问题是,我经常遇到完全忽略可伸缩性问题的生产代码,并且为此付出了大量额外的努力。(这些应用程序中字符串解析的庞大数量令人恐惧。)

这是一个常见的失败,没有为其他人遇到的工作应用正确的工具吗?还是只是我运气不好?还是我错过了一些非常明显和好的情况,在这些情况下将大量数据存储在内存中作为 XML 是正确的和好的?

4

9 回答 9

4

存储在内存中的任何数据都应该在类中。我们谈论的数据量越大,这一点就越重要。Xml 是一种非常臃肿的格式,会降低性能。XML 应该只用于在应用程序之间传输数据。恕我直言。

于 2009-06-17T17:54:26.707 回答
2

不,我同意。对于您的第一个示例,数据库应该处理几乎所有的缓存,因此将所有数据存储在程序内存中是错误的。这适用于它是否以 XML 或其他方式存储在内存中。

其次,您应该尽快将 XML 转换为有用的表示形式,可能是数据库,然后以这种方式使用它。只有当它是少量数据时,才适合将内存中的所有工作作为 XmlDocument(例如使用 XPath)来完成。字符串解析应该非常谨慎地使用。

于 2009-06-17T17:50:54.060 回答
1

@Matthew Flaschen 提出了一个很好的观点。我想补充一点,当您加入任何现有项目时,您可能会发现一些您不同意的设计和实施决策。

我们都一直在学习新事物,我们都会犯错误。虽然我同意这似乎是一个“duh”类型的问题,但我确信其他开发人员正在尝试通过缓存的概念来优化代码。

关键是,有时它需要一种温和的方法来说服人们,尤其是开发人员,改变他们的方式。这不是编码问题,而是人员问题。您需要找到一种方法让这些开发人员相信您建议的这些更改并不意味着他们无能。

我建议同意他们的观点,即缓存可能是一个好主意,但您希望通过它来加速功能。创建一个快速演示,与旧方法相比,您的(更合乎逻辑的)实现如何工作。很难与显着的速度改进争论。只是要小心直接攻击他们在对话中实施的方式。你需要这些人与你一起工作。

祝你好运!

于 2009-06-17T18:01:11.563 回答
0

我也同意,而且我确实认为有些运气不好。

...但是抓住了一根稻草,我可以看到将数据存储为 XML 的唯一用途是用于自动化单元测试,其中 XML 提供了一种模拟测试数据的简单方法。不过,绝对不值得。

于 2009-06-17T17:58:34.657 回答
0

我发现我必须这样做才能与旧版 COM 对象进行交互。COM 对象可以采用 xml 或类。填充类的每个成员的互操作开销太大了,处理 xml 是一个更快的选择。我们本可以让 ac# 类与 COM 类相同,但在我们的时间范围内真的很难做到。所以xml它是。并不是说这将是一个好的设计决策,但在处理大型数据结构的互操作时,这是我们能做到的最快的。

我不得不说我们在 C# 端使用了 LinqtoXML,所以使用起来稍微容易一些。

于 2009-06-17T17:58:36.667 回答
0

OOP 和数据库呢?Xml 有它的用途,但是(如您所见)将它用于一切可能会出现问题。

数据库可以允许索引、事务等,这将加快您的数据访问

在大多数情况下,对象更易于使用,它们可以更好地了解您的域等。

我不反对使用 xml,但它就像模式一样,它们是一种工具,我们应该了解何时何地使用它们,而不是爱上它们并尝试在任何地方使用它们......

于 2009-06-17T18:01:22.640 回答
0

格雷格,

在几个应用程序中,我确实或多或少地遵循了您描述的模式:

编辑:没有划痕。我从未将 XML 存储为字符串(或多个字符串)。我只是将它解析成一个 DOM 并使用它。那很有帮助。

我已将 XML 源代码导入 DOM(Microsoft Parser)并将它们保存在那里以进行所有必需的处理。我很清楚 DOM 导致的内存开销,但我发现该方法仍然非常有用。

  • 处理过程中的一些检查需要随机访问数据。selectPath 语句可以很好地用于此目的。

  • DOM 节点可以作为参数在应用程序中来回传递。另一种方法是编写包装每种类型对象的类,并随着 XML 模式的发展对其进行更新。这是一个可怜的(VB6 / VBA)人的多态性方法。

  • 将 XSLT 转换应用于 DOM 的全部或部分是轻而易举的事

  • 文件 I/O 也由 DOM 处理(xmldoc.save...)

对象的链接列表将消耗相当数量的内存并需要更多代码。我必须自己编写所有搜索和 I/O 功能。

我所认为的反模式实际上是应用程序的旧版本,其中 XML 或多或少被手动解析为结构数组。

于 2009-06-17T18:04:46.127 回答
0

对于大量数据,答案是否定的,没有充分的理由将数据直接作为 XML 字符串存储在内存中。

但是,这里有一个由 Alex Brown 撰写的有趣演示文稿,介绍了如何以更有效的方式将 XML 保存在内存中。作为“冰冻的溪流”。

这里还有一段视频,以及 XML 布拉格 2009 上的其他演示文稿。

链接文本

于 2009-06-17T18:19:22.390 回答
0

一般来说,我会尝试使用独立于 XML 序列化的内部数据模型。

但是,在我看来,在一种情况下使用 XML 作为内部数据结构是有意义的:如果您的数据模型需要捕获其格式可以由第 3 方扩展的层次关系,并且如果您的应用程序需要在保留扩展的同时转发此数据信息。

举个例子,伐木工人日志框架:这个想法是有一个基于 XML 的事件数据模型,其中每个应用程序都可以提供有关事件的分层信息(警告、错误等)。该框架负责收集事件并将它们分发给适当的处理程序。第 3 方可以轻松定义自己对格式的添加,并提供适当的生成器和处理程序。

这里重要的部分是框架必须将 XML 与所有 XML 信息完整地从生成器转发到处理程序。在这种情况下,实现一个捕获所有必要信息的内部数据结构会导致大多数 XML 本身的重新实现。因此,使用适当的 DOM 框架进行内部数据表示是有意义的。

于 2012-07-20T10:41:11.117 回答