-
Notifications
You must be signed in to change notification settings - Fork 37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature request: Non-nullable Message and Oneof parameter generation #242
Comments
My initial reaction is that this goes against the spirit of the protocol buffer design. That said, I definitely see the appeal of making these fields non-nullable when you're using pbandk with a validator like One other thought that just occurred to me: many protobuf libraries (including the official ones) do not expose an optional field as nullable in the generated code. Instead, accessing an optional field that was not present returns the default value of that field rather than a val home: Location? = null whereas libraries like val home: Location = Location.defaultInstance
val hasHome: Boolean = false pbandk prefers the first approach because Kotlin has such great support for nullable types that it's natural to use |
This was a company-wide decision so I couldn't do much but I agree, I think I feel closer to proto2 rather than proto3 in that sense. I suppose 3 feels newer but that is not the case. More like they are two different things, 3 is just 2-lite? But I still feel like as long as we use those custom libraries such as So if validation is done via
This is one of the reasons why I want to use
I agree, but I also think it depends on the use case. If we want to mark a field as required, it is considered as a breaking change. Because we do not reflect this in source-code doesn't mean it won't break. I feel like we are assuming things are not null or nullable implicitly in code which makes cross-collaboration hard. I am just finding myself reading proto comments all the time. I think it mostly drills down to the reason why people should switch to proto3 from proto2. If there are valid reasons (more language support, performance optimizations etc.) then I think backwards compatibility should be something left to the user. |
@garyp I had some time to think about this, here are my thoughts: A View on Required Fields & PbandKProto is a wire protocol and PbandK is built on top of proto. So, the required fields do not exist in the wire format, but it doesn't mean that they shouldn't exist at the API level. Nevertheless, I think everyone agrees some contracts do not make sense if a field is not set (e.g. business logic makes it required). ServerSo, let's see how individual parts of the system play together:
So assuming PbandK sits right between the proto and the API (when we use gen-validate) I don't think having required types in code is against proto3's compatibility standards. (i.e this is still satisfied) It is just an encapsulation of the service level logic to a properly formatted class structure with more precise null support. ClientsFrom the client's perspective, after the proto version is upgraded, it means the contract has changed. So the client is just responsible for updating its logic to populate that field which is 100% OK in my opinion. Also, the case described here is not true for all systems. There can be only a single consumer for protos too. For example, we store data efficiently using a proto structure and some might think backward compatibility is not an issue because of how they roll the required fields. It just depends on the situation and libraries like PbandK should be able to respond to those edge cases better than the generic proto implementation. For example, a field can be marked as ImplementationOne thing to take note of is how we will generate entities with default constructors, I think the approach I suggest would work because circularly dependent validated fields do not make sense Final OpinionsI feel like without changing the proto-compatibility standards PbandK should be able to provide an interface to its consumers that is flexible enough to cover all needs. People have different implementations for PbandK servers and clients, they can have interceptors, proto-generated classes etc. that can be used to bridge the actual proto-wire code and generated libraries. Sorry for the very long thread I just feel like this is still something very debatable because of the parities I see in real life vs. standards introduced by protocol buffers 🙂 |
@Dogacel thanks for taking the time to write up your thoughts. I really appreciate it. On a practical level, I share your perspective with regards to many of the points you brought up. But on a philosophical level, I'm hesitant to take pbandk in a direction that strays too far from the "protobuf way". After all, there are many serialization formats out there. One of the reasons many of us choose protobuf is because of its opinionated stance on how to best support backward and forward compatibility. I'm not ready to say that the feature you're requesting should not be implemented in pbandk, but I need some more time to mull it over. I do want to clarify one point though. You said:
What I was suggesting above was that if pbandk generates a message Person {
Location home = 1;
} currently generates this code: val home: Location? = null With my proposal it would instead generate: val home: Location = Location.defaultInstance
val hasHome: Boolean = false I.e. the |
I am not clear on one thing, I hope we are not changing how PbandK generates a field for the proto definition So, in short:
I think it would work pretty fine with Finally, in Carbon, we started using proto3 widely recently so the version of the proto3 compiler we use includes the message Person { Location home = 1; } here we assume So even though message Person { optional Location home = 1; } so from both the client and server's perspective, they usually map those proto messages to some POJO with a not-null |
From README,
Currently there is no way to mark a
message
type oroneof
type as required in proto3. But this is possible via plugins / options for example: protoc-gen-validate.It could be super cool if we can generate not nullable message fields if the option exists (And possibly we can make it customizable):
and the generated code would have a
not-nullable
home type as soI think there can be stuff that we need to consider, because this will definitely break the default constructor implementation for all protos and backwards compatibility. So we might need to add additional checks and throw exceptions like validators do to overcome unexpected errors.
The text was updated successfully, but these errors were encountered: