在我进入工作岗位的那些年里,我注意到了一种我认为是反模式的明显趋势:将内部数据维护为XML的大字符串。我已经看到这种做法有很多不同的方式,尽管两个最严重的罪犯非常相似。
第一个应用程序是一个Web服务,可以访问SQL数据库中可能存在的大量数据。在启动时,它会将数据中的所有数据或多或少地从数据库中提取出来,并将其作为XML存储在内存中。 (三次。)此应用程序的所有者将其称为缓存。我称之为缓慢,因为在对抗此问题时遇到的每个性能问题都可以直接追溯到这个问题。 (这是一个企业环境,客户端因为性能故障而不是服务而受到指责应该不足为奇。)这个应用程序确实使用了XML DOM。
第二个应用程序读取从第三方数据库导出时生成的XML文件。目标是将此数据导入专有系统(由我们拥有)。执行此操作的应用程序读取整个XML文件,并在整个导入序列中维护至少两个,有时多达四个XML文件的副本。请注意,可以在导入之前对数据进行操作,转换和配置,因此导入器在整个生命周期内都以XML格式拥有此数据。不出所料,当提供中等大小的XML文件时,此导入程序会爆炸。此应用程序仅将XML DOM用于其中一个副本,其余的都是原始XML字符串。
我对常识的理解表明,XML 不是用于在内存中保存数据的良好格式,而是在输出/传输数据并将其转换为内部数据结构时,应将数据转换为XML在读入和导入时。问题是,我经常遇到完全忽略可扩展性问题的生产代码,并经历了 ton 的额外努力。 (在这些应用程序中,字符串解析的绝对数量令人恐惧。)
这是否是为其他人遇到的工作应用正确工具的常见失败?或者这只是我的运气不好?或者我错过了一些非常明显和良好的情况,在这种情况下,将大量数据作为XML存储在内存中是正确的还是可以的?
答案 0 :(得分:4)
存储在内存中的任何数据都应该在类中。我们谈论的数据量越大,这一点就越重要。 Xml是一种非常臃肿的格式,会降低性能。 Xml应仅用于在应用程序之间传输数据。 IMHO。
答案 1 :(得分:2)
不,我同意。对于您的第一个示例,数据库应该处理几乎所有的缓存,因此将所有数据存储在程序存储器中是错误的。这适用于它是以XML还是以其他方式存储在内存中。
对于第二种,您应该尽快将XML转换为有用的表示形式,可能是数据库,然后以这种方式使用它。只有当它是少量数据时才适合在内存中作为XmlDocument进行所有工作(例如使用XPath)。应该非常谨慎地使用字符串解析。
答案 2 :(得分:1)
我们都在不断学习新事物,我们都会犯错误。虽然我同意这似乎是一种“问题”,但我确信其他开发人员正试图通过缓存的概念来优化代码。
关键是,有时需要一种温和的方法来说服人们,特别是开发人员改变他们的方式。这不是编码问题,而是人的问题。您需要找到一种方法来说服这些开发人员,您建议的这些更改并不意味着他们不称职。
我建议他们同意缓存可能是一个好主意,但是你想要加速它以加速功能。与旧方法相比,创建一个快速演示,了解您的(更合理的)实现方式。很难与戏剧性的速度提升争论。要小心直接攻击他们在对话中实施的方式。你需要这些人与你合作。
祝你好运!答案 3 :(得分:0)
我同意,我确实认为运气不好。
...但抓住吸管,我可以看到将数据存储为XML的唯一用途是用于自动化单元测试,其中XML提供了一种模拟测试数据的简便方法。但绝对不值得。
答案 4 :(得分:0)
我发现我必须这样做才能与传统的COM对象进行交互。 COM对象可以使用xml或类。填充类的每个成员的互操作开销太大,处理xml是一个更快的替代方案。我们本可以使一个c#类与COM类相同,但在我们的时间范围内确实太难了。所以它是xml。这并不是一个好的设计决策,但在处理大量数据结构的互操作时,它是我们能做的最快的。
我不得不说我们在C#端使用LinqtoXML,因此它使得使用起来更容易。
答案 5 :(得分:0)
OOP和数据库怎么样? Xml有它的用途但是可能存在问题(正如你所看到的)将它用于所有事情。
数据库可以允许索引,事务等,从而加快数据访问速度
在大多数情况下,对象更容易使用,它们可以更好地描述您的域等。
我并不反对使用xml,但它就像模式一样,它们是我们应该了解何时何地使用它们的工具,不会爱上它们并尝试在任何地方使用它们......
答案 6 :(得分:0)
格雷格,
在几个应用程序中,我确实或多或少地遵循了您描述的模式:
编辑:没有划痕。我从未将XML存储为字符串(或多个字符串)。我只是把它解析成一个DOM并使用它。这很有帮助。
我已将XML源代码导入DOM(Microsoft Parser)并将其保留在那里以进行所有必需的处理。我很清楚DOM导致的内存开销,但我发现apporach非常有用。
处理过程中的某些检查需要随机访问数据。 selectPath语句非常适用于此目的。
DOM节点可以作为参数在应用程序中来回传递。另一种方法是编写包装每种类型对象的类,并在XML模式发展时更新它们。这是一个穷人(VB6 / VBA)男人的多态性方法。
将XSLT转换应用于全部或部分DOM非常简单
文件I / O也由DOM处理(xmldoc.save ...)
对象的链接列表将消耗相当数量的内存并需要更多代码。我必须自己编写所有搜索和I / O功能。
我认为反模式实际上是应用程序的旧版本,其中XML被或多或少地手动解析为结构数组。
答案 7 :(得分:0)
对于大量数据,答案是否定的,没有充分理由将数据直接存储为内存中的XML字符串。
然而,Alex Brown提供了一个有趣的presentation,关于如何以更有效的方式在内存中保留XML。作为'冷冻流'。
还有一个视频,以及XML Prague 2009 here中提供的其他演示文稿。
答案 8 :(得分:0)
通常,我会尝试使用独立于XML序列化的内部数据模型。
但是,在我看来有一种情况,使用XML作为内部数据结构是有意义的:如果您的数据模型需要捕获层次关系,其格式可以由第三方扩展,如果您的应用程序需要转发此数据,同时保留扩展信息。
以the lumberjack logging framework为例:我们的想法是建立一个基于XML的事件数据模型,其中每个应用程序都可以提供有关事件的分层信息(警告,错误等)。该框架负责收集事件并将它们分发给适当的处理程序。第三方可以轻松定义自己对格式的添加,并提供适当的生成器和处理程序。
这里的重要部分是框架必须将所有XML信息从生成器转发到处理程序的XML。 在这种情况下,实现捕获所有必要信息的内部数据结构会导致大部分XML本身的重新实现。因此,使用适当的DOM框架进行内部数据表示是有道理的。