如何在 protobuf 中实现一个真正可选的字段?
How to implement a really optional field in protobuf?
我有一个描述可能每月、每年或在特定日期发生的事件的原型。其基本结构是:
enum PeriodType {
MONTHLY = 1;
YEARLY = 2;
SPECIFIC_DATE = 3;
}
message Event {
PeriodType period_type = 1;
...
}
但是应该有一种方法可以指定发生的日期。所以我制作了以下原型:
message Event {
PeriodType period_type = 1;
Date period_specific_date = 2;
...
}
该解决方案在我们的内部代码审查期间被禁止。原因是"proto should not contain fields which are used only when there is a particular value in another field"。我需要以某种方式重写它,这样当 event
有 period_type == MONTHLY
时就不可能调用 event.getPeriodSpecificDate()
。我该怎么做?
一个可能的解决方案是这样:
message Event {
message Period {
PeriodType period_type = 1;
}
message PeriodWithDate {
Period period = 1;
Date period_specific_date = 2;
}
oneof period {
Period period_without_date = 1;
PeriodWithDate period_with_date = 2;
}
...
}
但这并不能真正解决问题,而且看起来有点矫枉过正。还有其他办法吗?
如果给出了日期,您实际上并不需要 PeriodType。
所以你可以这样做:
enum RegularPeriod
{
MONTHLY = 1;
YEARLY = 2;
}
oneof period
{
RegularPeriod regular = 1;
Date specific_date = 2;
}
That solution was banned during our internal code review. The reason is that "proto should not contain fields which are used only when there is a particular value in another field".
告诉你的评论者我是 Protocol Buffers v2 的作者,我认为这条规则是不现实的。虽然强制执行类型系统中的所有内容很诱人,但实际上 Protobuf 类型系统的表现力远不足以制定这种硬性规则。在 real-world 中,使用 "this field should only be present if field X has value Y" 等记录约束的字段实际上很常见,这真的没问题。
话虽如此,在这种特殊情况下,@jpa 的回答是合理的。它具有权衡:您现在将在代码中有多个级别的分支,这可能很丑陋,并且如果您的协议变得更复杂,可能会变得更丑陋。但它确实设法表达了类型系统中的所有约束。
(不要接受我的回答,接受@jpa的。)
我有一个描述可能每月、每年或在特定日期发生的事件的原型。其基本结构是:
enum PeriodType {
MONTHLY = 1;
YEARLY = 2;
SPECIFIC_DATE = 3;
}
message Event {
PeriodType period_type = 1;
...
}
但是应该有一种方法可以指定发生的日期。所以我制作了以下原型:
message Event {
PeriodType period_type = 1;
Date period_specific_date = 2;
...
}
该解决方案在我们的内部代码审查期间被禁止。原因是"proto should not contain fields which are used only when there is a particular value in another field"。我需要以某种方式重写它,这样当 event
有 period_type == MONTHLY
时就不可能调用 event.getPeriodSpecificDate()
。我该怎么做?
一个可能的解决方案是这样:
message Event {
message Period {
PeriodType period_type = 1;
}
message PeriodWithDate {
Period period = 1;
Date period_specific_date = 2;
}
oneof period {
Period period_without_date = 1;
PeriodWithDate period_with_date = 2;
}
...
}
但这并不能真正解决问题,而且看起来有点矫枉过正。还有其他办法吗?
如果给出了日期,您实际上并不需要 PeriodType。 所以你可以这样做:
enum RegularPeriod
{
MONTHLY = 1;
YEARLY = 2;
}
oneof period
{
RegularPeriod regular = 1;
Date specific_date = 2;
}
That solution was banned during our internal code review. The reason is that "proto should not contain fields which are used only when there is a particular value in another field".
告诉你的评论者我是 Protocol Buffers v2 的作者,我认为这条规则是不现实的。虽然强制执行类型系统中的所有内容很诱人,但实际上 Protobuf 类型系统的表现力远不足以制定这种硬性规则。在 real-world 中,使用 "this field should only be present if field X has value Y" 等记录约束的字段实际上很常见,这真的没问题。
话虽如此,在这种特殊情况下,@jpa 的回答是合理的。它具有权衡:您现在将在代码中有多个级别的分支,这可能很丑陋,并且如果您的协议变得更复杂,可能会变得更丑陋。但它确实设法表达了类型系统中的所有约束。
(不要接受我的回答,接受@jpa的。)