我正在评估基于Java的服务的Google协议缓冲区(但希望使用与语言无关的模式)。我有两个问题:
第一个是一个广泛的一般性问题:
我们看到人们使用什么模式?所述模式与类组织(例如,每个.proto文件,打包和分发的消息)和消息定义(例如,重复字段vs.重复封装字段*)等有关。
在Google Protobuf帮助页面和公共博客上,此类信息很少,而对于已建立的协议(例如XML)则有大量信息。
对于以下两种不同的模式,我也有特定的问题:
将消息表示为.proto文件,将它们打包为一个单独的jar,然后将其发送给服务的使用者-这基本上是我认为的默认方法。
这样做,但在每条消息周围包括手工包装器(不是子类!),这些消息实现了至少支持这两种方法的协定(T是包装器类,V是消息类(使用泛型,但为简化起见简化了语法) :
public V toProtobufMessage() { V.Builder builder = V.newBuilder(); for (Item item : getItemList()) { builder.addItem(item); } return builder.setAmountPayable(getAmountPayable()). setShippingAddress(getShippingAddress()). build(); } public static T fromProtobufMessage(V message_) { return new T(message_.getShippingAddress(), message_.getItemList(), message_.getAmountPayable()); }
我从(2)中看到的一个优点是,我可以隐藏由它引入的复杂性,V.newBuilder().addField().build()
并在包装器中添加一些有意义的方法,例如isOpenForTrade()
或isAddressInFreeDeliveryZone()
等。我在(2)中看到的第二个优点是我的客户端处理了不可变的对象(可以在包装类中强制执行的事情)。
我在(2)中看到的一个缺点是我复制了代码,并且不得不将包装类与.proto文件进行同步。
有没有人对这两种方法有更好的技巧或进一步的批评?
*通过封装重复字段,我的意思是像这样的消息:
message ItemList {
repeated item = 1;
}
message CustomerInvoice {
required ShippingAddress address = 1;
required ItemList = 2;
required double amountPayable = 3;
}
而不是像这样的消息:
message CustomerInvoice {
required ShippingAddress address = 1;
repeated Item item = 2;
required double amountPayable = 3;
}
我喜欢后者,但很高兴听到反对它的争论。