现在的位置: 首页 > 综合 > 正文

O/X Mapping 的故事续集的续集

2013年08月11日 ⁄ 综合 ⁄ 共 2114字 ⁄ 字号 评论关闭

多年前就在博客上写过O/X Mapping的故事,及其续集。O/X Mapping并不是一个常用的术语,只是借用了O/R Mapping的思路,自己对XML序列化的一个别称。

没想到的是,这么多年来,关于O/X Mapping的故事一直在延续。

每次当我为一个新项目搭建代码框架的时候,或多或少,都在这个XObject类库里面增加些新特性,来满足新的需求。尽管在大多数项目里面,没有人愿意把对一些基础类库的修改或重构的工作,列在进度表上,因为老板总是目标导向的。好像只有那些技术发烧友,才会从老板给定的时间里面,偷偷地榨取一部分,来进行一些优化和重构,以便在未来更长的一段时间里,用一种更加舒畅的心情进行编程。因此,这些重构就像外科手术一样,不仅要快,而且每一步都必须小心翼翼,免得耽误进度。

在软件生命周期里,大部分的时间都是在做维护,随着需求的变化和团队的发展,代码会慢慢变得杂草丛生,直到难以维护,推倒重来。我曾一度相信,在项目不忙的时候,会有人站出来说,咱们专门花一段时间来重构吧。但多年来,发现这只是个传说。人都是有惰性的,也许只有在时间紧压力大的时候,才会有重构的动力,而且往往这个时候找到的解决方案才是最简单,最没有过度设计的。所以,就让我们把这种悄悄地重构进行到底把,终有一天,你会为自己的代码感到自豪。

之前的一些小项目,曾经试过把XObject的底层全部换掉,替换成WCF中的DataContractSerializer,代码量一下小了很多。而且当时发现,它也能对XML Schema的版本变化也有一定程度的兼容性。虽然没有做过性能的比较,但它用做PRC过程中的数据交换,还算是个不错的选择。但如果用来做配置文件的读写,有个很讨厌的毛病,就是产生大量的xml命名空间的定义,这对XPath的支持,以及手工维护配置文件带来极大的不便。为了解决这个问题,必须在每个对象上面用Attribute来重新声明xml命名空间,很辛苦,也很容易出错。

后来想到System.Xml命名空间里的XmlSerializer,这个东西不像DataContractSerializer那样针对数据传输进行过定制,默认不产生xml命名空间,而且生成的xml带有换行缩进,看起来是用做配置文件读写的首选。但可怕的是,同一段代码在WinForm里面运行的好好的,在Windows Service里面,XmlSerializer反序列化时就报找不到类型的异常:因为生产环境中,程序通常是以插件加载到Windows Service的方式运行,难道XmlSerializer反序列化时候默认跑到system32下去找这些类型了?在网上一搜,发现还有人说XmlSerializer会产生内存泄露。幸亏单元测试做得及时,在程序中调用XmlSerializer的方法上,赶紧标上个Obsolete,小心使用。

最终还是选择了WCF的对象序列化机制,来做XObject的增强。这样,针对配置文件读写的部分,还是用之前自己编写的反射机制来实现,避免那些无聊(至少对配置文件来说)的命名空间,还可以对XML序列化反序列化过程进行精确的白盒控制;针对数据交换的部分,就用WCF来做JSON序列化和反序列化,毕竟时至今日,在很多领域XML已经慢慢被JSON取代。

但XObject最早是在.Net1.1时代写的,后来2.0有了泛型,做了些封装,但集合类型还是依赖于最古老的CollectionBase,郁闷的是WCF不认这个,它只认List<T>。于是,唯一的办法就是把原来XObject实现中基于继承的机制拿掉,改成类似修饰器模式的聚合机制,这样需要序列化的对象,就能同时使用WCF和原来XObject的序列化功能了。而且所有这些改动都可以封装到原来的XObject和XCollection基类里面,上层应用丝毫不用修改。

另外,在单元测试中发现,之前自己做的XML序列化工作并没有白费,精确的白盒控制不仅可以带来很多意想不到的好处,也能克服微软类库的一些缺点。比如WCF序列化,不管是XML还是JSON,都不能很好地处理这样的XML Schema,其中的MyElement都会被忽略掉。如果某个第三方定义的奇怪的XML Schema里面包含这样的结构,估计只能靠我们自己搞定了。

<MyCollection>
  <MyElement></<MyElement>
  <MyCollectionItem></MyCollectionItem>
  <MyCollectionItem></MyCollectionItem>
  <MyCollectionItem></MyCollectionItem>
</MyCollection>

--

XML文件是机器读的,不是人读的,你是人的话,就不要去读XML:这有点偏激,却是O/X Mapping构思之初的一个基本假设。也许只要这个假设存在,O/X Mapping的故事还会不断延续和丰富下去。

十分厌恶传统的Java开发里面,大量的配置文件的手工修改工作,这样的开发方式,低估了配置文件对程序行为的影响:凭什么代码修改就要通过测试才能上线,配置文件就可以随便让人修改。

抱歉!评论已关闭.