设计思考 – Protocol Buffers 3 为什么这样设计
内容提要
协议缓冲区3移除了“必需”和“可选”关键字,允许在数据正确性上有更大的灵活性。它将空值和默认值视为等同,简化了设计并减少了存储空间。这与“少即是多”的原则一致。
延伸解读
数据正确性检查的责任转移
proto3 移除 required 和 optional 关键字,并非放弃数据正确性,而是将检查责任交给应用程序。文章以 Stock 为例,指出不同角色对“正确数据”的定义不同:新增记录时 mtime 可能非必需,读取时却应存在。因此,protobuf 只负责编码解码,各角色自行校验,避免为不同场景定义多个 message。
默认值等同 null 的潜在风险
proto3 将基本类型的 null 与默认值视为等同,未设置的 int 字段会被当作 0。文章举例:未盘点的库存记录 {productId: 1} 经编解码后会变成 {productId: 1, count: 0},可能被误判为已售罄。官方文档也警告无法区分字段是显式设为默认值还是未设置,使用时需格外留意。
包装类型如何弥补语义缺失
为表达可选字段,proto3 提供包装类型如 Int32Value。文章示例中,productId 用 int32 表示必填,count 用 Int32Value 表示可选。这样类型本身就能提示字段是否可为空,且检查非硬性,不会导致新增方法失败。同时,默认值无需存储,换来更精简的存储空间和更贴近静态语言的类型。
Q&A
Protocol Buffers 3 为什么移除了'required'和'optional'关键字?
因为数据的正确性检查应由应用程序的每个角色自行负责,而不是由protobuf强制执行。
Protocol Buffers 3 如何处理空值和默认值?
在proto3中,空值和默认值被视为等同,简化了设计并减少了存储空间。
使用Protocol Buffers 3时,如何表示可选字段?
可以使用包装类型(如Int32Value)来表示可选字段,提供类型检查的灵活性。
Protocol Buffers 3的设计原则是什么?
设计原则是'少即是多',强调简化设计以提高效率。
Protocol Buffers 3对基本类型的处理有什么特别之处?
proto3将基本类型的null视为预设值,这可能导致数据处理错误。
Protocol Buffers 3如何避免动态语言中的常见错误?
通过将基本类型设计得更贴近主流静态语言,避免了动态语言中的常见错误。