按照Joel的说法,Daily Build可以在更大的时空尺度上缩短程序开发中编码-编译-调试的循环,从而提升团队效率和产品质量。对我来说,卸下那些繁琐的编译工作,倒开始有更多的时间来思考和总结问题了。传说中的Google员工,在正式的项目以外还有20%的时间来做自己喜欢的事情,20%的确高得让人羡慕,这样的宣传也是擅长媒体经营的互联网公司的传统长项,事实上类似比例的资源在不少公司都存在,关键在于你如何去发现和发掘了。
自从去年八月以两篇Mapping的故事开博以来,一年间又积累了一些关于Mapping的杂碎,也正好回顾和总结一下。
之前谈到O/X Mapping的时候,竟把meta data的一种使用技巧写成了一个技术营销的案例,实在有点年少轻狂,毕竟我对后者事实上没有太多的经历。然而后来的环境变化又迫使我继续向人们推销XObject的好处,以对抗XPath的侵袭。当时还进行过两者的比较,遗憾的是当时整理的资料已经作为技术预研中一个很次要的部分加以抛弃,只是依稀记得在动态访问XML内容的时候XPath还是最好的选择,在运行时对象持久化(比如程序配置信息的存储、在分布式环境中传输特定Schema的XML文档)方面XObject明显优于XPath。而且只要在解析xML文档的时候使用贪婪的策略,跳过不认识的节点并尽量多地从XML文档提取信息,XObject就可以动态地适应Schema的轻微改变。另外,对于类型的处理,XObject天生就是强类型的,而使用XPath还需要手工地进行危险的类型转换。
后来我在指导一个实习生的时候发现,为了让XObject发挥最好的效能,在定义XML Schema的时候,似乎还要遵守一些规则。事实上我们身边很多应用都使用了这些规则,大概是我们平时都太过于关注编程语言的设计模式,而忽略了这些脚本语言的Best Practise。(http://www.xfront.com/BestPracticesHomepage.html)
比如我们要定义一个结构来表达从数据库字段到DICOM的Mapping(真可怕,又是一种Mapping),有些人可能会这样定义。的确很直观明了,节点名就是字段的名称,值就是需要映射到的DICOM Tag。
<
DB_to_DICOM_Mapping
>
<
PID
>
00100020
</
PID
>
<
PName_EN
>
00100010
</
PName_EN
>
<
PName_CN
>
00101000
</
PName_CN
>
</
DB_to_DICOM_Mapping
>
但如果要定义一个XObject来映射这样一个结构,这个类可能就是:
public
class
DB_to_DICOM_Mapping : XObject
...
{
public string PID ...{ get; set; }
public string PName_EN ...{ get; set; }
public string PName_CN ...{ get; set; }
}
如果要增加一个字段映射,就要修改这个类的定义并且重新编译。可见,这个结构的确是不太适合用XObject来解析的。尽管用XPath可能会非常合适,而且很直观,比如病人ID就在/DB_to_DICOM_Mapping/PID的位置。
事实上,我们在进行任何一种设计的时候,对于需求的理解中最关键的一点应该是识别其中的扩展点,也就是说我们需要把什么东西设计成稳定的,什么设计成可变的。下面的结构可能更能适应这种变化。
<
DB_to_DICOM_Mapping
>
<
Item
DB_Field
="PID"
DICOM_Tag
="00100020"
/>
<
Item
DB_Field
="PName_EN"
DICOM_Tag
="00100010"
/>
<
Item
DB_Field
="PName_CN"
DICOM_Tag
="00101000"
/>
</
DB_to_DICOM_Mapping
>
不难发现,.Net Framework为应用程序提供的configuration file中的配置项也是这样定义的,它把Key和Value定义为一个相同名称节点的两个属性,然后把这些节点并列起来。
事实上对于这些语义上并列的XML节点,换一种方式可能更好,这样一来可以用增加字段而不是增加属性的方式来扩展每个Item的内容,比如需要在映射的同时增加其他的规则等等。
<
DB_to_DICOM_Mapping
>
<
Item
>
<
DB_Field
>
PID
</
DB_Field
>
<
DICOM_Tag
>
00100020
</
DICOM_Tag
>
</
Item
>
<
Item
>
<
DB_Field
>
PName_EN
</
DB_Field
>
<
DICOM_Tag
>
00100010
</
DICOM_Tag
>
</
Item
>
<
Item
>
<
DB_Field
>
PName_CN
</
DB_Field
>
<
DICOM_Tag
>
00101000
</
DICOM_Tag
>
</
Item
>
</
DB_to_DICOM_Mapping
>
这样我们只需要定义这样的XObject类就可以了
public
class
DB_to_DICOM_Mapping
: XObjectCollection
<
DB_to_DICOM_Mapping.Item
>

...
{
public class Item
...{
public string DB_Field ...{ get; set; }
public string DICOM_Tag ...{ get; set; }
}
}
XML的意义在于既便于机器读,也便于人读,换一种方式,并不会对人的阅读产生什么影响,反而极大方便了机器阅读。我想这应该是总结XML的各种Best Practise的出发点之一。
这样的XML结构为XObject的解析提供了便利,但就需要写更复杂的XPath语句来实现节点定位了。XPath的确很灵活,可以访问到任何XML结构中的任何一个角落,但通用性越强,它对特定环境的适应性就越差:好像在物种的适应性上也有一个类似的生物学规律。因此在具体项目中进行技术取舍的时候,如果真的需要适应非常灵活的变化,请使用XPath,并预先估算上更多的编码工作量。
本文探讨了使用XObject处理XML文档的最佳实践,通过对比XPath,详细分析了如何设计XML结构以提高XObject的解析效率,包括如何定义扩展性强的XML结构。

332

被折叠的 条评论
为什么被折叠?



