Dlaczego Protobuf 3 uczynił wszystkie pola w komunikatach opcjonalnymi?

15

Składnia 3 protokołu protobuf spowodowała, że ​​wszystkie pola stały się opcjonalne, odrzucając słowa kluczowe requiredi optionalpoprzednią składnię proto2. Czytając niektóre komentarze od programistów , wydaje się, że zrobiono to w celu zwiększenia kompatybilności binarnej do przodu / do tyłu.

Ale dla mnie może to być wymuszone przez wersjonowanie nazw pakietów, powiedzmy, com.example.messages.v1a następnie pozwólmy klientom wdrożyć deserializatory, które rozumieją. Jednocześnie usuwa niektóre umowy określone jako typ, które są użyteczne z punktu widzenia inżynierii oprogramowania. Na przykład jeśli mam

message Location {
   double latitude = 1;
   double longitude = 2;
}

W proto3 możliwe jest utworzenie kopii zapasowej w połowie wspieranej, ale doskonale poprawnej Location, nie podając jednego z wymaganych pól.

Czy nie jest to duża wada podczas tworzenia formatu serializacji opartego na schemacie do wymiany danych między klientami? Czy nie jest gorsze przenoszenie dodatkowego kodu weryfikacyjnego do każdego klienta sprawdzającego, czy wszystkie wymagane pola mają prawidłowe wartości?

tonicebrian
źródło
leanpub.com/esversioning
VoiceOfUnreason

Odpowiedzi:

13

Proto3 wprowadza wiele zmian mających (jak rozumiem) uczynić go znacznie bardziej użytecznym w scenariuszach międzyplatformowych. Jawne śledzenie „przypisanego” vs „nieprzypisanego, ale zgłoszenie wartości domyślnej” może być bardzo trudne do wdrożenia na niektórych platformach docelowych, a także może być mylące w użyciu. Jako taki, proto3 przyjmuje znacznie prostsze podejście:

  • niejawna wartość domyślna jest naturalną wartość zero (liczba / teksty stałe), false (wartości logiczne) lub pusty ciąg (ciągi)
  • dozwolone jest tylko domyślne domniemanie; żadne inne wartości domyślne nie są dozwolone
  • jeśli pole ma tę wartość domyślną, nie jest serializowane; nie ma znaczenia, czy zostało jawnie przypisane do zera / fałszu / pustego ciągu vs nigdy nie przypisane
  • z tego powodu nie ma pojęcia „wymagane”, ponieważ „jawnie przypisano wartość zerową” i „nigdy nie przypisano wartości” wygląda identycznie

W proto3 możliwe jest utworzenie w połowie wspieranej, ale doskonale poprawnej lokalizacji, nie podając jednego z wymaganych pól.

Inna wartość to: zero. Fakt, że nie przypisałeś go jawnie do zera, jest dyskusyjny. To, czy jest to pożądane, zależy od ciebie, ale ma to dla mnie sens i jest to, jak wiele „inicjowania nowego obiektu / struktury” działa na wielu platformach.

Czy nie jest gorsze przenoszenie dodatkowego kodu weryfikacyjnego do każdego klienta sprawdzającego, czy wszystkie wymagane pola mają prawidłowe wartości?

Nie ma nic do sprawdzenia! Układ jest dokładnie taki, jaki byłby, gdyby wartość zero została wyraźnie przypisana. Jeśli jest to legalne, jest legalne. Jeśli jest to nielegalne (ponieważ zero nie ma dla ciebie sensu), jest nielegalne; ale byłoby to niezgodne z prawem, czy byłoby jawne czy dorozumiane. Kwota wymaganej weryfikacji nie zmienia się.

Czy nie jest to duża wada podczas tworzenia formatu serializacji opartego na schemacie do wymiany danych między klientami?

Nie zwykle nie ... zwłaszcza, że ​​wersja schematu jest jawna. Jeśli chcesz użyć proto2: użyj proto2. Nic nie zmienia się automatycznie.

Marc Gravell
źródło
Zastanawiam się, co kupuje je „tylko naturalne zero jako domyślne”, ponieważ protobuf nie jest tak naprawdę użyteczny bez jakiegoś schematu. Zapewnienie spójnych ustawień domyślnych nie brzmi o wiele trudniej niż zapewnienie spójnych schematów w pierwszej kolejności.
CodesInChaos
1
@CodesInChaos to interesujące, ponieważ robiłem protobuf bez schematu dla ... cóż, na zawsze :) w protobuf-net, oczekuje się, że większość użytkowników będzie miała kod i nie będzie schematu. I co ciekawe (przynajmniej dla mnie) większość „prostych, głupich” domyślnych strategii, których używa protobuf-net, jest dokładnie taka sama, jak ta, którą wybrał proto3. Nie zamierzam twierdzić, że to potwierdza moje losowe partyzanckie decyzje, ale ... całkowicie to robi :)
Marc Gravell
Uważam klasę C # za rodzaj schematu iz pewnością można określić wartości domyślne za pomocą atrybutów. Porównaj to np. Z msgpack lub json, które mogą stworzyć znaczącą strukturę danych bez żadnego schematu.
CodesInChaos
@CodesInChaos zgodził się i odnotował - i tak, protobuf-net będzie przestrzegać i szanować wszelkie takie deklaracje
Marc Gravell