Search code examples
javarpcthriftgrpc

Where to store thrift or grpc interfaces?


thrift interface can be compiled across multiple languages. it's just text files, why there are no online tools like swagger hub? I don't want to copy paste interface across projects that use that interface

also i don't find it useful to package interface with jar file, because only jvm languages can resolve that interface and also it's not user friendly way. It's not only about thrift, it's about grpc also. I didn't find any docs concerned with this question and couldn't find any best practises


Solution

  • Assuming you have a .proto file with your interfaces, each sub project will need to know about the file. There are two main approaches to this problem: Vendor the file, or copy the file.

    Vendor the File

    In this option, you make an addition project (like a git repo) which stores all your interface definitions. Each project that needs to know about the interfaces will include a reference (git submodule or git subtree) which includes the interface project. When you build your project, the interfaces will need to be synced and then used to generate the necessary code.

    The downside of this approach is that git subtree and submodule (or whatever version control you use) are more difficult to use, and require extra work by people building your code. If you make changes to the interface in the subproject it can be difficult to apply those changes back upstream to the interface project.

    Copy the File

    In this option, you manually copy the file around between projects, and manually keep them in sync. Each time you make a change, you'll want to apply that change to every other project that depends on the interface. When using Protobuf though, it is important to note that you don't have to do this. Protos are designed to be highly backwards compatible.

    For example, code that is changing a proto definition from one form to the other can actually use both forms. Old code will look at the old form, and new code can decide on looking at the old or new form. Once all users have been upgraded, you can remove the old form.

    The downside to this approach is that it pushes complexity into the decoding portion of your code. You end up needing to be backwards compatible, with an unknown number of older clients. Since not every project will be in sync with the interface definitions, all the users of the interface will need to be more flexible. This problem is not specific to Proto, but happens naturally; it happens to everyone.

    A second downside is having to manually copy changes. You must make sure never to reuse field numbers or names. If you have a lot of projects that depend on the interface, its more work for you.

    Which to Choose?

    Neither approach is objectively better than the other. Each one pushes complexity into a different part of your build. From what I have seen, most people prefer to copy the file, since it is easier than learning advanced git commands.