Google Protocol Buffer缺陷

之因此要列出protobuf的缺陷,就是爲了在使用Protobuf的時候能夠規避這些缺陷;沒有一個工具是十全十美的,咱們在使用工具的時候須要揚長避短,所以要對其優勢和缺點都有所瞭解才能夠設計出更好的軟件系統!!!

1. repeated字段二義性

repeated字段表明傳輸0~N個數據對象。當傳輸的數據對象個數大於0時,接收方能夠按照覆蓋的方式,使用新的數據,替換以前的全部數據。可是,當傳輸的數據對象個數等於0的時候,接收方如何意會發送方的意圖呢?是保留不變仍是刪除列表? java

解決辦法:影子字段,爲每一個repeated type name = i;增長一個include影子字段, optional bool include_name = i+1; 當 include_name 的值爲true時,表示須要修改內容,當include_name爲false時,接收方忽略name字段。 c#

2. repeated字段冗餘

repeated字段每次傳輸的是一個列表的全部對象的數據。列表的內容改變時,特別是有時候真是新增或者減小几個數據對象時,依舊須要傳輸整個完整的列表數據。這在數據量比較少的時候不成問題,可是若是列表的成員爲成千上萬個的時候,恐怕使用單一的repeated字段是沒法知足的。在此時最好是repeated字段只傳輸那些變更的數據對象,例如值傳輸全部新增的,或者值傳輸全部被刪除的。 數據結構

解決辦法:所以再次最好增長一個枚舉和一個字段。 工具

enum RepteateFieldOpType { add = 0; del = 1; replace = 3;} ui

optional      RepteateFieldOpType  op_name = i+2 [ default = replace]; spa

3.消息對象冗餘

    protoc.exe代碼生成器生成的消息對象不但引用了protobuf庫的基礎消息,並且還添加了不少額外的字段。生成的消息類沒法直接用在工程的業務邏輯對象中。 設計

     所以,須要在工程中,重複定義一套業務對象,數據結構和protobuf 的message對象至關。而且在業務對象和消息對象之間進行數據的賦值。  指針

  解決辦法:工程中,涉及到和業務邏輯對象相關的消息,最好採用自動化工具從class對象中提取字段,而且映射爲消息。並使用工具自動生成class對象和protobuf 消息對象之間的負值,如toMessage和fromeMessage等方法。   對象

4.數據類型單一

    普通數據類型單一,可使用最大化的方式解決。而複雜數據,protobuf只有一種模式,message。對於java,c#語言來講,能夠認爲是引用。可是對於C++語言來講,是映射爲指針對象呢?仍是普通的複合對象成員呢?通常狀況下能夠根據optional或者required來關聯。複合對象使用required字段,指針對象使用optional字段。另外repeated表明的是一個列表,repeated message,是值對象的列表仍是值引用(指針)的列表,這個也很差區分。  map(字典)也不能直接映射到protobuf. 繼承

以C++爲例的解決方案:

    對於C++ class中的普通數據成員,直接映射爲protobuf的相應的數據成員。

    對於C++class,映射爲一個 message

   對於 C++ class中的普通複合成員,直接映射爲 required message便可。

   對於C++ class中的指針複合成員,直接映射爲optional message便可。既然是指針,那麼傳輸的對象若是是整個類,和普通的複合成員也就沒有多大的區別。可是若是此類設計到繼承時,傳輸的時候能夠只傳輸基類的內容,使得接收方能夠根據基類的相關信息找到業務對象,而不是重新建立一個業務對象。所以還須要爲每一個指針複合成員定義一個find方法,用於把消息中的值,映射爲業務對象。    

5.繼承問題

C++,Java,C++的類都不多是無父類的,在一個稍微複雜點的系統,業務對象都有本身的繼承體系的。而protobuf的message和C的struct同樣,是沒有結構的概念的。

如何把C++中的繼承體系映射到protobufmessage中,能夠借鑑一下C的struct的作法。

有1中方式。第一種是分散式的,每一個繼承的子類都使用一個獨立的消息,在消息中的第一個字段爲父類的消息,而且名稱固定爲base。例如

Class A {}; Class B : public {}

message B {

required A base = 1;

.....

在多繼承模式下,我的無能爲力,那位有更好的 !!

另一種方式是集中式,整個繼承體系使用一個獨立的類,把全部的子類都封裝在一塊兒,使用起來相似於C中的union。

例如

Class A ;

Class B : public A;

class C : public A;

message XX {

required message A a =1;

optional message B b = 2;

optional message C c = 3;

相關文章
相關標籤/搜索