Hacker News new | ask | show | jobs
by adamkl 1920 days ago
Code generation and strong contracts are good (and C#/Java developers have been doing this forever with SOAP/XML), but they do place some serious restrictions on flexibility.

I’m not sure how gRPC handles this, but adding an additional field to a SOAP interface meant regenerating code across all the clients else they would fail at runtime while deserializing payloads.

A plus for GraphQL is that because each client request is a custom query, new fields added to the server have no impact on existing client code. Facebook famously said in one of their earlier talks on GraphQL that they didn’t version their API, and have never had a breaking change.

Really, I don’t gRPC and GraphQL should even be compared since they support radically different use cases.

3 comments

> I’m not sure how gRPC handles this, but adding an additional field to a SOAP interface meant regenerating code across all the clients else they would fail at runtime while deserializing payloads.

This is basically the reason every field in proto2 will be marked optional and proto3 is “optional” by default. IIRC the spec will just ignore these fields if they aren’t set or if they are present but it doesn’t know how to use them (but won’t delete them, if it needs to be forwarded. Of course this only works if you don’t reserialize it. Edit: this is not true see below).

Even if a process re-serializes a message, unknown fields will be preserved, if using the official protobuf libraries proto2 or 3.5 and later. Only in 3.0 did they drop unknown fields, which was complete lunacy. That decision was reverted for proto 3.5.

Some of the APIs (C++ for example) provide methods to access unknown fields, in case they were only mostly unknown.

Oh, I see now - https://github.com/protocolbuffers/protobuf/releases/tag/v3.... (General) - I wasn't aware of that as I think I've started using proto3 after that version. Good to know.
I do remember some debate around required/optional in proto2, and how the consensus was to not have required in proto3 - parties had good arguments on both sides, but I think ultimately the backward-forward compatibility argument won. With required, you can never retire a field, and older service/client would not work correctly. I haven't used proto2 since then, been using proto3 - but was not aware of what another poster here mentioned about proto 3.5 - so now have to read...
Learned that at Google, for each service method, introduce individual Request and Response messages, even if you can reuse. This way you can extend without breaking.

Also never reuse old/deleted field (number), and be very careful if you change the type (better not).

These were basic principles I put in place at a previous company that had a number of API-only customers. Request/Response messages. Point releases could only contain additive changes. Any changes to existing behaviors, removal of fields, or type changes required incrementing the API version, with support for current and previous major versions.
Protobuf was designed to keep backwards/forwards compatibility, you can easily add any fields to your messages without breaking old clients at the network layer (unless you intend to break them at the application layer);