-
-
Notifications
You must be signed in to change notification settings - Fork 685
Description
When we adopted protobuf as the basis for messages, we had 3 goals:
- Be able to define messages with an IDL
- Wide programming language support
- JSON serialisation format (for debuggability)
Protobuf satisfies all of those, but has some drawbacks.
The primary drawback is runtime dependencies. The protoc
code generator (or similar code generators in unofficial ports) generates code that depends on protobuf runtime libraries. This poses two challenges:
- Size. Loading all this code into a browser take a long time because the resulting code is megabytes.
- Compatibility. A project depending on a different version of protobuf than the one used by Cucumber might lead to conflicts
Another challenge with protobuf is maintenance cost. Because we want to inspect messages visually, we've decided to use the JSON serialisation format instead of the more commonly used binary representation. While JSON is "supported" by protobuf, the implementations have several bugs that we've had to work around or fix. These bugs exist because few people use protobuf with JSON.
During the weekly community meeting on 25 Feb 2021 two alternative solutions were put forward:
Keep .proto
but use custom code generator
We could implement a custom code generator that parses the messages.proto
file and reads a programming language-specific template file for code generation.
The code generator would generate code with an interface similar to the code generated by protoc
, but without any runtime dependencies. It would only support JSON serialisation and not the binary representation.
For TypeScript for example, this could be just messages.d.ts
(just the interface) and no implementation at all. We'd get type safety at compile time, and wouldn't need any runtime dependencies for serialisation (that would be handled by the stdlibrary JSON functions).
JSON Schema
(OpenAPI was suggested. OpenAPI has a lot of HTTP stuff in it that isn't relevant to us, and my understanding is that it relies on JSON Schema to define the schema of request/response payloads).
We could translate the .proto
schema to JSON Schema and use existing tools to generate lightweight code. Here are some existing ones:
- TypeScript: json-schema-to-typescript
- .NET: NJsonSchema
- Java: jsonschema2pojo
For dynamically typed languages such as Ruby, we wouldn't need code generation or any runtime dependencies at all.