เหตุใดจึงจำเป็นและไม่ใส่ก็ได้ถูกลบใน Protocol Buffers 3


214

ฉันเพิ่งใช้gRPCกับproto3และฉันสังเกตเห็นว่าrequiredและoptionalถูกลบในไวยากรณ์ใหม่

ใครบ้างกรุณาอธิบายว่าทำไมลบ / จำเป็นต้องใช้จะถูกลบใน proto3 ข้อ จำกัด ประเภทนี้ดูเหมือนจะจำเป็นเพื่อให้คำจำกัดความแข็งแกร่ง

ไวยากรณ์ proto2:

message SearchRequest {
  required string query = 1;
  optional int32 page_number = 2;
  optional int32 result_per_page = 3;
}

ไวยากรณ์ proto3:

syntax = "proto3";
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

คำตอบ:


390

ประโยชน์ของrequiredการเป็นหัวใจของการถกเถียงและสงครามเปลวไฟ ค่ายใหญ่มีอยู่ทั้งสองด้าน ค่ายหนึ่งชอบรับประกันว่ามีคุณค่าอยู่และยินดีที่จะอยู่กับข้อ จำกัด ของมัน แต่ค่ายอื่น ๆ รู้สึกว่าrequiredเป็นอันตรายหรือไม่ช่วยเหลือเนื่องจากไม่สามารถเพิ่มหรือเอาออกได้อย่างปลอดภัย

ให้ฉันอธิบายเหตุผลเพิ่มเติมว่าทำไมrequiredควรใช้ฟิลด์อย่างไม่ จำกัด หากคุณใช้โปรโตแล้วคุณไม่สามารถเพิ่มฟิลด์ที่ต้องการได้เพราะแอปพลิเคชันเก่าจะไม่ให้ฟิลด์นั้นและแอปพลิเคชันโดยทั่วไปไม่สามารถจัดการกับความล้มเหลวได้ดี คุณสามารถตรวจสอบให้แน่ใจว่าแอปพลิเคชันเก่าทั้งหมดได้รับการอัปเกรดก่อน แต่สามารถทำผิดได้ง่ายและไม่ช่วยถ้าคุณเก็บโปรโตในที่เก็บข้อมูลใด ๆ (แม้อายุสั้นเช่น memcached) สถานการณ์แบบเดียวกันนี้ใช้เมื่อลบฟิลด์ที่ต้องการ

ฟิลด์ที่ต้องกรอกจำนวนมากจำเป็นต้องมี "ชัดเจน" จนกระทั่ง ... พวกเขาไม่ได้ สมมติว่าคุณมีidเขตข้อมูลสำหรับGetวิธีการ นั่นคือเห็นได้ชัดต้อง ยกเว้นภายหลังคุณอาจจำเป็นต้องเปลี่ยนidจาก int เป็นสตริงหรือ int32 เป็น int64 ที่ต้องเพิ่มmuchBetterIdเขตข้อมูลใหม่และตอนนี้คุณถูกทิ้งไว้กับidเขตข้อมูลเก่าที่จะต้องระบุ แต่ในที่สุดก็จะถูกละเว้นอย่างสมบูรณ์

เมื่อรวมสองปัญหาเข้าด้วยกันจำนวนrequiredฟิลด์ที่เป็นประโยชน์จะมี จำกัด และค่ายโต้เถียงกันว่ามันยังมีคุณค่าหรือไม่ ฝ่ายตรงข้ามrequiredไม่จำเป็นต้องขัดกับความคิด แต่เป็นรูปแบบปัจจุบัน บางคนแนะนำให้พัฒนาไลบรารีการตรวจสอบที่มีความหมายมากขึ้นซึ่งสามารถตรวจสอบrequiredพร้อมกับสิ่งที่ก้าวหน้ากว่าเช่นname.length > 10เดียวกันในขณะเดียวกันก็ต้องแน่ใจว่ามีโมเดลความล้มเหลวที่ดีกว่า

Proto3 โดยรวมดูเหมือนจะชอบความเรียบง่ายและrequiredการลบนั้นง่ายกว่า แต่อาจจะน่าเชื่อถือมากขึ้นการลบrequiredความรู้สึกที่เหมาะสมสำหรับ proto3 เมื่อรวมกับคุณสมบัติอื่น ๆ เช่นการลบการมีอยู่ของฟิลด์สำหรับการพื้นฐานและการลบค่าเริ่มต้นที่แทนที่

ฉันไม่ได้เป็นนักพัฒนา protobuf และฉันก็ไม่ได้มีอำนาจในเรื่อง แต่ฉันก็ยังหวังว่าคำอธิบายจะเป็นประโยชน์


23
อ๋อ ดูคำอธิบายเพิ่มเติมเกี่ยวกับสิ่งต่าง ๆ ที่ผิดปกติอย่างน่ากลัวกับสาขาที่ต้องการ: capnproto.org/ …
Kenton Varda

8
ตัวเลือกจะไม่ถูกลบ ทุกอย่างเป็นตัวเลือกใน proto3 แต่ใช่การแสดงผลข้อมูล (has_field) ได้ถูกลบออกวิทยาการ หากคุณต้องการข้อมูลการใช้งานการแสดงผลwrappers.protoStringValueซึ่งมีข้อความเช่น เนื่องจากเป็นข้อความจึงมี has_field นี่คือ "มวย" ที่มีประสิทธิภาพซึ่งพบได้ทั่วไปในหลายภาษา
Eric Anderson

9
ในทางตรงกันข้ามดูเหมือนว่า "ตัวเลือก" ถูกลบใน proto3 มีทุกฟิลด์อยู่และเติมด้วยค่าเริ่มต้น คุณไม่มีทางรู้ว่าฟิลด์ดั้งเดิมถูกกรอกโดยผู้ใช้หรือตามค่าเริ่มต้น ช่องข้อความซึ่งเป็นตัวชี้โดยทั่วไปเป็นตัวเลือกในการที่พวกเขาสามารถมีค่าเป็นศูนย์
คนจรจัด

14
ฉันรู้สึกว่า protobuf เป็นภาษาที่ออกแบบมาอย่างชัดเจนเพื่อเริ่มสงครามไฟ
แรนดี้ L

5
ดูเหมือนว่าคนส่วนใหญ่ไม่ต้องการรุ่น API ของพวกเขา ง่ายกว่าสำหรับพวกเขาที่จะทำให้ทุกอย่างเป็นตัวเลือกสำหรับ "ความเข้ากันได้แบบย้อนหลัง"
Holoceo

41

คุณสามารถหาคำอธิบายในปัญหาprotobuf Github นี้ :

เราปล่อยเขตข้อมูลที่ต้องการใน proto3 เนื่องจากเขตข้อมูลที่ต้องการโดยทั่วไปถือว่าเป็นอันตรายและเป็นการละเมิดความหมายของความเข้ากันได้ของ protobuf แนวคิดทั้งหมดของการใช้ protobuf คือช่วยให้คุณสามารถเพิ่ม / ลบฟิลด์ออกจากข้อกำหนดโพรโทคอลของคุณในขณะที่ยังคงเข้ากันได้อย่างสมบูรณ์ / ย้อนหลังเข้ากันได้กับไบนารีใหม่ / เก่า ช่องที่จำเป็นจะต้องใช้วิธีนี้ คุณไม่สามารถเพิ่มเขตข้อมูลที่ต้องการลงในคำจำกัดความ. proto อย่างปลอดภัยและคุณไม่สามารถลบเขตข้อมูลที่ต้องการที่มีอยู่ได้อย่างปลอดภัยเนื่องจากการกระทำทั้งสองอย่างนี้ทำให้การเข้ากันได้ของสาย ตัวอย่างเช่นถ้าคุณเพิ่มเขตข้อมูลที่ต้องการลงในคำจำกัดความ. proto ไบนารีที่สร้างขึ้นด้วยคำจำกัดความใหม่จะไม่สามารถแยกวิเคราะห์ข้อมูลที่เป็นอนุกรมโดยใช้คำนิยามเก่าได้เนื่องจากเขตข้อมูลที่ต้องการไม่มีอยู่ในข้อมูลเก่า ในระบบที่ซับซ้อนที่ไหน คำจำกัดความโปรโตมีการใช้งานร่วมกันอย่างกว้างขวางในองค์ประกอบต่าง ๆ ของระบบการเพิ่ม / ลบฟิลด์ที่ต้องการสามารถนำมาลงหลายส่วนของระบบได้อย่างง่ายดาย เราได้เห็นปัญหาการผลิตที่เกิดจากหลาย ๆ ครั้งและมันถูกแบนมากทุกที่ใน Google เพื่อให้ทุกคนสามารถเพิ่ม / ลบฟิลด์ที่ต้องการ ด้วยเหตุนี้เราจึงลบฟิลด์ที่จำเป็นทั้งหมดใน proto3

หลังจากการลบ "จำเป็น", "ตัวเลือก" เป็นเพียงการสำรองเพื่อให้เราลบ "ตัวเลือก" เช่นกัน


6
ฉันไม่เข้าใจ อะไรคือความแตกต่างระหว่างการทิ้งข้อความหลังจากดีซีเรียลไลซ์และดีซีเรียลไลเซชัน? มันจะถูกทิ้งโดยไคลเอนต์รุ่นเก่าเนื่องจากไม่มีฟิลด์ที่จำเป็น (เช่น id)
Shmuel H.

6
ฉันอยากเห็นด้วยกับ @ShmuelH เขตข้อมูลที่ต้องการจะเป็นส่วนหนึ่งของ API หรืออีกวิธีหนึ่ง นั่นรองรับโดยอัตโนมัติผ่านทางไวยากรณ์ที่ให้กับทั้งสองฝ่ายหรือซ่อนอยู่ในแบ็กเอนด์ก็ยังมีอยู่ อาจทำให้มองเห็นได้ในนิยาม api
Cruncher

7
ฉันเห็นด้วยกับ @ShmuelH ทั้งหมด จำเป็นต้องมีฟิลด์ใน API ไม่ทางใดก็ทางหนึ่งและเป็นประโยชน์สำหรับลูกค้าที่จะรู้เรื่องนี้ นี่ทำให้ฉันคิดว่าเรายังไม่ได้รับเวอร์ชันเลย
patrickbarker

6
โหวตอีกครั้งสำหรับ @ShmuelH หากคุณเปลี่ยน API ของคุณในแบบย้อนหลังที่เข้ากันไม่ได้ (เพิ่มเขตข้อมูลที่จำเป็น) คุณต้องการให้ parser ตรวจพบหรือไม่ รุ่น API ของคุณ! คุณยังสามารถทำมันได้อย่างสมบูรณ์ใน Protobuf oneof { MessageV1, MessageV2, etc. }ถ้าคุณต้องการใช้
Timmmm

1
มันไม่สามารถพิสูจน์ได้ว่ามีช่องที่ต้องเริ่มต้น และการเพิ่มเขตข้อมูลที่จำเป็นคือการเปลี่ยนแปลงที่เข้ากันไม่ได้และโดยทั่วไปควรได้รับการจัดการโดยการเปลี่ยนรุ่นโปรโตคอล (เช่นประเภทข้อความใหม่)
กาญจน์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.