O/X Mapping 的故事續集

 按照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 getset; }
  
public string PName_EN getset; }
  
public string PName_CN getset; }
}

 

如果要增加一個字段映射,就要修改這個類的定義並且重新編譯。可見,這個結構的確是不太適合用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 getset; }
    
public string DICOM_Tag getset; }
  }

}

 

XML的意義在於既便於機器讀,也便於人讀,換一種方式,並不會對人的閱讀產生什麼影響,反而極大方便了機器閱讀。我想這應該是總結XML的各種Best Practise的出發點之一。

這樣的XML結構爲XObject的解析提供了便利,但就需要寫更復雜的XPath語句來實現節點定位了。XPath的確很靈活,可以訪問到任何XML結構中的任何一個角落,但通用性越強,它對特定環境的適應性就越差:好像在物種的適應性上也有一個類似的生物學規律。因此在具體項目中進行技術取捨的時候,如果真的需要適應非常靈活的變化,請使用XPath,並預先估算上更多的編碼工作量。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章