The problem is that protobufs aren’t just an interchange format, they’re also a system for generating the code used to interact with said interchange. Said code has a habit of leaking into the types used by your code base. It’s too easy to just pass protoc-generated objects around and use them all over your code base, hence the majority of the criticisms.
Protobuf seems to encourage this… instead of a hard boundary where your serialization logic ends and your business logic begins, every project I’ve worked on that uses protobuf tends to blur the lines all over the place, even going as far as to make protoc-generated types the core data model used by the whole code base.
You can take the wire format and ignore the code generator, if you like. I often do, especially for languages other than C++. For C++ I quite like the generated code.
Protobuf seems to encourage this… instead of a hard boundary where your serialization logic ends and your business logic begins, every project I’ve worked on that uses protobuf tends to blur the lines all over the place, even going as far as to make protoc-generated types the core data model used by the whole code base.