But it can require a bit more more thought in your protocol design. So for example in this case, the options would be
- design things such that 0 is ok to mean "most current" (so start revisions at 1) (this is hard after the fact, but if you know from day 0 that missing values for int types will be 0, you can design everything to start at 1) (Edit: maybe this is how etcd works?)
- explicitly break out revision into a message type (so you can notice if it's not provided)
- use something like "-1" to mean "now", so that 0 isn't overloaded
etc...
(You could argue maybe the right call for proto3 was to have a flag on a field saying if you want to be able to notice if it was provided or not. Best of all worlds, at cost of a bit of complexity.)
But now you can't figure this out at all without adding another, boolean field, _and setting it separately_, which I'm pretty sure nobody is going to do unless they really have to, leading to the type of issue we're seeing here.
Google themselves provide https://github.com/protocolbuffers/protobuf/blob/master/src/... to deal with this situation.
Quoted from the documentation:
> Wrappers for primitive (non-message) types.
> These types are useful for places where we need to distinguish between the absence of a primitive typed field and its default value.
It should probably be advertised more, as we've experienced that default values of optional fields are a surprising feature for smart developers who are new to protobufs. Maybe it's seen as a wart in the design? Getting rid of Null is hard.
I kinda wish they went with the approach that all fields are required, unless they are explicitly declared as optional. This is how Rust does it, and people seem to like it.
It’s the distinction between an optional type and an optional value (default value). With optional values but no optional types, you can’t be certain about the caller’s intentions. It’s a distinction that’s subtle but important, therefore a “gotcha”.
Getting rid of null is a noble idea, because of the headaches that null tends to induce. Optional types (like Rust’s) is a neat way to get the behavior of null without the value of null. Proto3 doesn’t have null, it’s replaced with arcane wrapping that’s arguably less straightforward.
Please let me know if I’m talking past you, it isn’t intentional, just late in the day. :)
Yes, I would love if there were set/unset bits available. Even if it was awkward.
and sometimes defining your own, e.g. nullable lists.
It's not elegant, but it is simple.