[實踐] 為原型系統設計簡單的純文字資料交換協議

樑濤發表於2011-11-15

[參考書目] TAOUP 5:1-3

[目的]
我們新組建了一個軟體公司,LZSoft,針對微型客戶需求進行快速小軟體開發。為了快速驗證功能需求可行性、實現複雜度與滿足程度,需要不停地建立模型和原型程式、在各種實現間迭代和微調。在該過程中使用著大量動態程式語言如Perl、Python、Ruby等,同時使用標準管道化工具如Shell、Sed、Awk、Grep等作為輔助開發手段。由於上述語言和工具間的微細異構性,必須設計一套合理的資料交換協議,以便在各子程式之間可靠通訊。

[考量]
1. 易讀:人眼可讀、可理解,不需要額外直譯器/格式化工具;
2. 易寫:可用各種標準Linux實用工具生成輸出,也可用標準Linux機上編輯工具(vi/emacs)手寫;
3. 邊界清晰:不同記錄間有明確的邊界,可輕易感知;
4. 無固定結構:不同記錄可以有不同結構,以描述不同應用;
5. 語法簡潔:任何人、任何程式均能快速理解記憶;
6. 相容能力強:不同語言編寫的程式可簡單地解析/合成記錄;
7. 層級簡單:可以在某種可接受的複雜程度上描述層級結構。

[設計]
考慮到原型系統中開發人員參與度非常高,資訊交換過程最關鍵之處是必須隨時可讀可寫,因此擯棄二進位制資料交換協議,初步定位為使用純文字資料交換協議。

開始時嘗試從現有資料交換協議中選取合適物件,有如下選擇:JSON,XML,CSV。三者均為純文字資訊交換協議,各有利弊:

  1. JSON優點有a)非常輕量與緊湊,協議本身使用一頁A4紙即可描述清楚;b)天然具備層級結構和集合結構;c)天然面向Web開發;d)可自描述;e)格式化後人眼讀寫都很方便;f)相關外部工具眾多。缺點有a)多條記錄混排輸出時邊界不清晰,難以定位;b)緊湊輸出時人眼讀寫困難;c)程式設計時需要載入第三方解析/生成庫。

  2. XML優點有a)天然具備層級結構和集合結構;b)可自描述;c)相容性與支援度最好;d)外部工具眾多,成熟、功能良好。缺點有a)多條記錄混排輸出時邊界不清晰,難以定位;b)手動編寫麻煩甚至困難;c)程式設計時需要載入第三方解析/生成庫;d)對文字資料限制過於嚴格。

  3. CSV優點有a)以行作為記錄邊界,多條記錄混排輸出時便於定位邊界;b)可匯入Excel進一步處理;c)手工編輯方便。缺點有a)相容性較差;b)外部工具較少;c)語法結構稍微複雜;d)轉義序列複雜易錯;e)程式設計時需要載入第三方解析/生成庫;f)缺少自描述能力。

由於主要該協議主要使用在原型系統中,強調快速辨識、修改以應對需求和功能的變化,而XML並不合適快速編輯與分析,故放棄;在有限前提下JSON可以使用,但不經過適當格式化,閱讀編輯都相當困難,出於開發效率考慮,同樣放棄;而CSV最大問題有兩個,一是不能自描述,二是轉義規則複雜,同樣只適合在有限前提下使用,也不得不放棄;最後,影響三個協議均不能入選的最終理由是,程式語言相容性都不夠高,必須載入第三方庫,從而產生較強的限制。

[結論]
設計一個用於原型系統的純文字資料交換協議,應當具備以下特點:
1. 邊界清晰,任何記錄混排輸出時均可快速識別,不論接收方是人眼還是機器;
2. 結構儘可能簡單,轉義規則能少則少,層級儘可能壓縮在兩到三層以內;
3. 能夠自描述各部分結構的語義,至少可以進行聯想;
4. 可以在記錄間插入空白、空行和註釋;
5. 程式設計時不必刻意載入第三方庫,使用語言提供的原生函式即可處理;
6. 最好可以對映為物件/雜湊表/關聯陣列。

[成果]
最終我選擇了以下這種簡單的純文字資料交換協議。
1. 以換行(\n,LF)作為記錄邊界,如資料中存在換行,可以用C轉義序列\n替換之,也可以完全禁止使用帶換行的資料;
2. 以管道符(|,Bar)作為欄位邊界,如資料中存在管道符,則以URI轉義序列%7C替換之;
3. 如果有需要,也可以使用製表符(\t,Tab)代替管道符;
4. 每個欄位由鍵名和值組成,之間以等號(=,Equal)分隔,鍵名兩邊可填入可選空白符,必要時值兩邊亦可填入可選空白符;
5. 鍵名中可以包括句點符(.,Period)表示層級結構。

[例項]
cmd=test_output|name=Tom|age=29|desc=Cannot say anything.

[缺點]
1. 如果從物件/雜湊表/關聯陣列中生成記錄,則欄位順序可能是亂的,擁有相同欄位的物件生成的記錄排在一起時比較好看,反過來則相當難看;
2. 資料超過一屏字元數時會折成多個邏輯行,記錄邊界定位難度上升;
3. 有效字元數與總字元數之比偏小,有效負載低。

相關文章