การออกแบบ API: แนวทางที่เป็นรูปธรรมและเป็นนามธรรม - แนวทางปฏิบัติที่ดีที่สุด


25

เมื่อพูดคุยเกี่ยวกับ API ระหว่างระบบ (ในระดับธุรกิจ) มักจะมีมุมมองที่แตกต่างกันสองประการในทีมของเรา: บางคนชอบมากกว่า - ให้พูดว่า - วิธีนามธรรมทั่วไป

ตัวอย่าง: การออกแบบ API ค้นหา "บุคคล" แบบง่าย รุ่นที่เป็นรูปธรรมจะเป็น

 searchPerson(String name, boolean soundEx,
              String firstName, boolean soundEx,
              String dateOfBirth)

คนที่ชื่นชอบเวอร์ชั่นคอนกรีตพูดว่า:

  • API คือการจัดทำเอกสารด้วยตนเอง
  • มันง่ายที่จะเข้าใจ
  • มันง่ายต่อการตรวจสอบ (คอมไพเลอร์หรือเป็นเว็บเซอร์: การตรวจสอบสคีมา)
  • จูบ

กลุ่มคนอื่น ๆ ในทีมของเราจะพูดว่า "นั่นเป็นเพียงรายการของเกณฑ์การค้นหา"

searchPerson(List<SearchCriteria> criteria)

กับ

SearchCritera {
  String parameter,
  String value,
  Map<String, String> options
}

ด้วยอาจทำให้ "พารามิเตอร์" บางประเภทการแจงนับ

ผู้เสนอพูดว่า:

  • โดยไม่ต้องเปลี่ยน (ประกาศ) API การดำเนินการสามารถเปลี่ยนแปลงได้เช่นการเพิ่มเกณฑ์หรือตัวเลือกเพิ่มเติม แม้ว่าจะไม่มีการซิงโครไนซ์การเปลี่ยนแปลงดังกล่าว ณ เวลาที่ใช้
  • เอกสารเป็นสิ่งที่จำเป็นแม้จะมีรูปแบบที่เป็นรูปธรรม
  • การตรวจสอบความถูกต้องของสคีมาถูก overrated บ่อยครั้งที่คุณต้องตรวจสอบความถูกต้องเพิ่มเติมสคีมาไม่สามารถรองรับทุกกรณี
  • เรามี API ที่คุ้นเคยกับระบบอื่นแล้ว - นำมาใช้ซ้ำ

ข้อโต้แย้งคือ

  • เอกสารจำนวนมากเกี่ยวกับพารามิเตอร์ที่ถูกต้องและการรวมกันของพารามิเตอร์ที่ถูกต้อง
  • ความพยายามในการสื่อสารที่มากขึ้นเพราะมันยากที่จะเข้าใจสำหรับทีมอื่น ๆ

มีวิธีปฏิบัติที่ดีที่สุดหรือไม่? วรรณกรรม?


3
ซ้ำแล้วซ้ำอีก "สายแรก / ชื่อบูล Soundex" คือการละเมิดที่ชัดเจนของแห้งและแสดงให้เห็นว่าการออกแบบนี้ล้มเหลวที่จะอยู่กับความจริงที่ว่าชื่อที่คาดว่าจะไปพร้อมกับ Soundex ต้องเผชิญกับข้อผิดพลาดการออกแบบที่เรียบง่ายเช่นนั้นมันรู้สึกยากที่จะดำเนินการวิเคราะห์ที่ซับซ้อนยิ่งขึ้น
gnat

ตรงกันข้ามกับ "คอนกรีต" ไม่ใช่ "ทั่วไป" มันคือ "นามธรรม" สิ่งที่เป็นนามธรรมมีความสำคัญมากสำหรับไลบรารีหรือ API และการสนทนานี้ไม่สามารถถามคำถามพื้นฐานอย่างแท้จริงได้แทนที่จะแก้ไขสิ่งที่ค่อนข้างตรงไปตรงมากับคำถามที่มีสไตล์ FWIW, ตัวโต้แย้งโต้กลับสำหรับตัวเลือก B เสียงเหมือนโหลดของ FUD, คุณไม่ควรต้องการเอกสารหรือการสื่อสารเพิ่มเติมหากการออกแบบ API นั้นสะอาดและครึ่งหนึ่งตามหลักการ SOLID
Aaronaught

@ ไม่ถูกต้องขอบคุณที่ชี้ให้เห็นว่า ("นามธรรม") มันอาจเป็นปัญหาการแปล "generisch" ในภาษาเยอรมันเสียงยังคงตกลงกับฉัน อะไรคือ "คำถามพื้นฐานที่แท้จริง" สำหรับคุณ?
erik

4
@Aaraught: คำถามไม่ได้เกี่ยวกับนามธรรม การแก้ไขที่ถูกต้องน่าจะตรงข้ามกับ "ทั่วไป" คือ "เจาะจง" ไม่ใช่ "คอนกรีต"
Jan Hudec

การลงคะแนนเสียงอีกครั้งสำหรับเรื่องนี้ไม่ได้เกี่ยวกับเรื่องทั่วไปและเป็นนามธรรม แต่เป็นเรื่องทั่วไปและเฉพาะเจาะจง ตัวอย่าง "คอนกรีต" ด้านบนเป็นจริงเฉพาะกับชื่อชื่อและ dateOfBirth ตัวอย่างอื่น ๆ ทั่วไปกับพารามิเตอร์ใด ๆ ไม่เป็นนามธรรมโดยเฉพาะอย่างยิ่ง ฉันจะแก้ไขชื่อ แต่ฉันไม่ต้องการที่จะเริ่มสงครามแก้ไข :-)
แมตต์ freake

คำตอบ:


18

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

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


7

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

มีสิ่งใหม่เกิดขึ้นไม่บ่อยนักภายใต้ดวงจันทร์ ลองดูที่ศิลปะก่อนหน้านี้โดยเฉพาะมาตรฐานและรูปแบบที่กำหนดไว้ (เช่นหลายสิ่งสามารถสร้างแบบจำลองหลังจากฟีดคำอธิบายเหตุการณ์ถูกอธิบายใน ical / vcal) ทำให้ API ของคุณง่ายขึ้นโดยที่เอนทิตีบ่อยและอยู่ทั่วไปทุกหนทุกแห่งเป็นรูปธรรมและส่วนขยายที่มองเห็นเป็นพจนานุกรม นอกจากนี้ยังมีรูปแบบที่เป็นที่ยอมรับสำหรับการรับมือกับสถานการณ์เฉพาะ ตัวอย่างเช่นการจัดการคำขอ HTTP (และคล้ายกัน) อาจเป็นแบบจำลองใน API ที่มีวัตถุคำขอและการตอบสนอง

ก่อนที่จะออกแบบ API ให้ระดมสมองในแง่มุมต่างๆรวมถึงสิ่งที่จะไม่ถูกรวมเข้าด้วยกัน แต่คุณต้องระวัง ตัวอย่างเช่นภาษาทิศทางการเขียนการเข้ารหัสสถานที่ข้อมูลเขตเวลาและสิ่งที่คล้ายคลึง ให้ความสนใจกับสถานที่ที่สามารถปรากฏหลายรายการ: ใช้รายการไม่ใช่ค่าเดียวสำหรับพวกเขา ตัวอย่างเช่นหากคุณกำลังออกแบบ API สำหรับระบบวิดีโอแชท API ของคุณจะมีประโยชน์มากขึ้นถ้าคุณสมมติว่ามีผู้เข้าร่วม N คนไม่ใช่แค่สองคน (แม้ว่ารายละเอียดของคุณในตอนนี้จะเป็นเช่นนั้น)

บางครั้งการเป็นนามธรรมช่วยลดความซับซ้อนลงอย่างมาก: แม้ว่าคุณจะออกแบบเครื่องคิดเลขเพื่อเพิ่มเพียง 3 + 4, 2 + 2 และ 7 + 6 มันอาจง่ายกว่ามากที่จะใช้ X + Y (ด้วยขอบเขตทางเทคนิคที่เป็นไปได้บน X และ Y และรวม ADD (X, Y) ให้กับ API ของคุณแทน ADD_3_4 (), ADD_2_2 (), ...

สรุปการเลือกหนึ่งทางหรืออีกวิธีหนึ่งเป็นเพียงรายละเอียดทางเทคนิค เอกสารของคุณควรอธิบายกรณีการใช้บ่อย ๆ อย่างเป็นรูปธรรม

ไม่ว่าคุณจะทำอะไรในด้านโครงสร้างข้อมูลให้ระบุฟิลด์สำหรับเวอร์ชัน API

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

ในด้านวรรณกรรมฉันอาจแนะนำโปรแกรมเมอร์ชั้นนำ "Beautiful Code" อธิบายว่าพวกเขาคิดอย่างไรโดย Andy Oram, Greg Wilson เนื่องจากฉันคิดว่าความงามนั้นเกี่ยวกับการรับรู้การซ่อนเร้นในแง่ดี (และความเหมาะสมสำหรับวัตถุประสงค์บางอย่าง)


1

ความชอบส่วนบุคคลของฉันคือความเป็นนามธรรม แต่นโยบายของ บริษัท ของฉันทำให้ฉันเป็นรูปธรรม นั่นคือจุดสิ้นสุดของการอภิปรายสำหรับฉัน :)

คุณได้ทำรายการข้อดีและข้อเสียที่ดีสำหรับทั้งสองแนวทางแล้วและถ้าคุณขุดต่อไปคุณจะพบข้อโต้แย้งมากมายทั้งสองฝ่าย ตราบใดที่สถาปัตยกรรมของ API ของคุณได้รับการพัฒนาอย่างเหมาะสมนั่นหมายถึงคุณได้รับความคิดว่าจะใช้อย่างไรในวันนี้และวิธีที่มันจะพัฒนาและเติบโตในอนาคต

ที่นี่สองบุ๊คมาร์คที่ฉันมีกับมุมมองตรงข้ามคือ:

นิยมเรียนนามธรรม

การเชื่อมต่อที่ชื่นชอบ

ถามตัวเองว่า: "API ตรงตามความต้องการทางธุรกิจของฉันหรือไม่ฉันมีเกณฑ์ที่กำหนดไว้อย่างดีสำหรับความสำเร็จหรือไม่ ดูเหมือนว่าวิธีปฏิบัติที่ดีที่สุดที่ง่ายที่สุดในการปฏิบัติตาม แต่จริงๆแล้วมันมีความสำคัญมากกว่าคอนกรีตและทั่วไป


1

ฉันจะไม่พูดว่า abstract API นั้นยากต่อการตรวจสอบ หากพารามิเตอร์เกณฑ์นั้นง่ายพอและมีการพึ่งพากันน้อยมากมันไม่ได้สร้างความแตกต่างมากนักไม่ว่าคุณจะผ่านพารามิเตอร์แยกต่างหากหรือในอาร์เรย์ คุณยังต้องยืนยันความถูกต้องทั้งหมด แต่นั่นก็ขึ้นอยู่กับการออกแบบพารามิเตอร์เกณฑ์และวัตถุเอง

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


1

อาร์กิวเมนต์การเปลี่ยนแปลงควรถูกยกเลิกด้วย YAGNI โดยพื้นฐานแล้วถ้าคุณไม่มีกรณีใช้งานอย่างน้อย 3 กรณีที่ใช้ API ทั่วไปแตกต่างกันโอกาสที่คุณจะออกแบบค่อนข้างต่ำเพื่อที่ว่าคุณจะไม่ต้องเปลี่ยนเมื่อกรณีใช้งานครั้งถัดไปเกิดขึ้น (และเมื่อคุณมีการใช้งาน - กรณีคุณต้องใช้อินเทอร์เฟซทั่วไปรอบระยะเวลา) ดังนั้นอย่าพยายามและพร้อมสำหรับการเปลี่ยนแปลง

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

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


1

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

ตามที่กล่าวไว้ก่อนหน้านี้ - ฉันชอบโอกาสที่จะเปลี่ยนแปลงหรือขยายการใช้งานโดยไม่ต้องปรับเปลี่ยนส่วนต่อประสาน การเพิ่มเกณฑ์การค้นหาอื่นไม่จำเป็นต้องสะท้อนให้เห็นในการกำหนดบริการ

แม้ว่าจะไม่มีคำถามในการออกแบบอินเทอร์เฟซกระชับและ expresse ที่ดีคุณจะต้องให้เอกสารบางอย่างเพิ่มเติม การเพิ่มขอบเขตคำจำกัดความสำหรับเกณฑ์การค้นหาที่ถูกต้องนั้นไม่ใช่ภาระ


1

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

API ที่ดี

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

API ที่ไม่ดี

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

หน้ารายละเอียดทั้งที่นี่และที่นี่มาพร้อมกับการสนทนาเชิงลึกของแต่ละประเด็น มันเป็นสิ่งที่ต้องอ่านสำหรับผู้ออกแบบ API ขอบคุณสนิมถ้าคุณเคยอ่านเรื่องนี้


0

ในคำพูดของคนธรรมดา:

  • วิธีนามธรรมมีข้อดีของการอนุญาตให้สร้างวิธีการที่เป็นรูปธรรมรอบ ๆ
  • วิธีอื่น ๆ ไม่เป็นความจริง

UDP มีข้อได้เปรียบในการสร้างสตรีมที่เชื่อถือได้ของคุณเอง เหตุใดเกือบทุกคนจึงใช้ TCP
svick

นอกจากนี้ยังมีการพิจารณากรณีการใช้งานส่วนใหญ่ บางกรณีอาจมีความจำเป็นบ่อยครั้งซึ่งเป็นไปได้ที่จะทำให้กรณีเหล่านั้นเป็นพิเศษ
Roman Susi

0

ถ้าคุณขยายSearchCriteriaความคิดนิด ๆ หน่อย ๆ ก็สามารถให้คุณมีความยืดหยุ่นเช่นการสร้างAND, ORฯลฯ เกณฑ์ หากคุณต้องการฟังก์ชั่นดังกล่าวนี่จะเป็นแนวทางที่ดีกว่า

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


0

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

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

ไม่ใช่ทุกระบบที่จะต้องมีความยืดหยุ่นเป็นพิเศษพยายามทำทุกอย่างเพื่อให้เป็น Astronauting Architecture ธนูยิงธนูแบบยืดหยุ่น ดาบที่ยืดหยุ่นมีประโยชน์เหมือนกับไก่ยาง

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