Rest APIs - ความท้าทายเฉพาะสำหรับมือถือ


25

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

API ที่ถูกออกแบบตามสไตล์ Rest ของการดำเนินการ URI และ CRUD ที่เน้นทรัพยากรเป็นศูนย์กลางจับคู่กับกริยา HTTP สิ่งที่ชอบ:

GET www.example.com/books
DELETE www.example.com/books/482094
POST www.example.com/users/6793

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

ไคลเอนต์มือถือมีข้อ จำกัด ที่ร้ายแรงเมื่อพูดถึงการเชื่อมต่อดังนั้นเราควรปฏิบัติตามกฎดังกล่าว:

1 หน้าจอ == 1 การเรียก API

1 บันทึก == 1 การเรียก API

มีหลายสถานการณ์ที่สิ่งนี้ทำให้คุณมีหลักสูตรการชนด้วยหลักการออกแบบ REST เช่น:

  • สมมติว่าแอปของคุณออฟไลน์อยู่หนึ่งวันและคุณจำเป็นต้องซิงค์กับฐานข้อมูลแบ็กเอนด์สี่ตารางและคุณต้องการโทรศัพท์เช่น www.example.com/sync_everything?since=2015-07-24
  • สมมติว่ามีหน้าจอที่ผู้ใช้สามารถแก้ไขวัตถุของเขาได้หลายอย่างเช่นการทำเครื่องหมายในรายการสิ่งที่ต้องทำ ควรมีวิธีแก้ไขเรกคอร์ดงานทั้งหมดในการเรียก API แบทช์เดียวแทนที่จะเรียก API หนึ่งครั้งต่อการแก้ไข
  • สมมติว่ามีหน้าจอที่ผสมข้อมูลจากตาราง ORDER, SALESMEN และ PRODUCT db ฉันควรรับข้อมูลนั้นในการโทรครั้งเดียวแทนที่จะเป็นสาม

ความเสี่ยงคือเราอาจท้ายด้วย Restful API ที่มีมากที่สุดและยังเป็นแอพมือถือที่ไม่ตอบสนองที่ไร้ประโยชน์มากที่สุด

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

หรือวิธีแก้ปัญหาสำหรับปัญหาทั่วไปนี้ ขอบคุณ!


3
ดูเหมือนว่าคำถามของคุณอาจเป็น "วิธีการที่ API สามารถส่งมอบคอลเลกชันของวัตถุและวัตถุฝังตัวเช่นหรือไม่เหมือนประเภทในขณะที่รักษาสไตล์ REST?" ฉันเข้าใจคำถามของคุณหรือไม่
joshp

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

1
ฉันคิดว่าการปรับ API ของคุณเป็นวิธีแก้ปัญหาที่ผิดเมื่อปัญหาคือการขาดคำขอแบบขนาน - 8 คำขอขนาดเล็กนั้นไม่ได้เลวร้ายยิ่งไปกว่าคำขอที่มีขนาดใหญ่เพียงคำขอเดียวเมื่อพวกเขาไม่ต้องรอซึ่งกันและกัน คุณสามารถเปลี่ยนเป็น HTTP / 2 ได้ไหม หรืออย่างน้อยก็ใช้ HTTP / 1.1 pipelining?
amon

ดูเพิ่มเติมที่: รูปแบบสำหรับการจัดการการทำงานเป็นกลุ่มในบริการเว็บ REST? . คีย์กำลังระบุชนิดของคำสั่ง (และภายใต้เงื่อนไขใดบ้าง) ที่สามารถแบตช์เข้าด้วยกันโดยไม่มีข้อขัดแย้งจากนั้นสร้างการแสดง JSON ของลำดับแบตช์แล้วส่งไป มันสูญเสียความน่าดึงดูดใจหลักสำหรับREST ซึ่งเป็นความสามารถในการแคชแต่ความสามารถในการแคชไม่ได้เกี่ยวข้องกับแอปพลิเคชันทุกประเภทเสมอไป โปรดทราบว่าชุด / การทำงานพร้อมกันไม่สามารถใช้งานได้หากมีการพึ่งพาตรรกะ
วง

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

คำตอบ:


27

API ที่ถูกออกแบบตามสไตล์ Rest ของการดำเนินการ URI และ CRUD ที่เน้นทรัพยากรเป็นศูนย์กลางจับคู่กับกริยา HTTP

นี่คือปัญหาของคุณที่นี่

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

ตัวอย่างเช่นอาจมี

www.example.com/books/482094
www.example.com/books/582045
www.example.com/books/427454
www.example.com/books/319343

ต้องโหลดทั้งหมดเพื่อให้ได้ห้องสมุดของฉัน

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

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

สิ่งที่คุณควรมีคืออะไรเช่นนี้

www.example.com/users/334/my_library

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

คุณอาจจะมี

www.example.com/users/334/favioured_books
www.example.com/users/334/books_ordered_last_week
www.example.com/users/334/wishlist

ไม่จำเป็นต้องมีอยู่ในรูปแบบในฐานข้อมูลหรือพื้นที่โดเมนของคุณ

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

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

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

นี่คือ Jim Webber ที่พูดถึงเรื่องนี้อย่างละเอียดยิ่งขึ้น (รวมไปถึงการขุดที่ Rails ด้วย!)

https://yow.eventer.com/yow-2011-1004/domain-driven-design-for-restful-systems-by-jim-webber-1047


สิ่งนี้น่าสนใจมากและฉันเห็นด้วยอย่างยิ่งกับเรื่องนี้ แต่น่าเสียดายที่ฉันไม่ใช่คนที่ทำ API และฉันมีวิธีเล็กน้อยที่จะมีอิทธิพลต่อมันถ้ามี หลายคนจะใช้ว่า "รูปแบบการต่อต้าน" ทั่ว (ด้วยเหตุผลหลายประการข้อ จำกัด กรอบเป็นหนึ่ง) และพวกเขาเพียงแค่ใช้คำจำกัดความ URI สำหรับการคิดอย่างชัดเจนเกี่ยวกับฐานข้อมูลของพวกเขา จุดสิ้นสุดของ API เป็นอีกวิธีหนึ่งในการแสดงภาพฐานข้อมูลของพวกเขา ... นอกจากนี้ในบางกรณีการสร้างทรัพยากรเช่นที่คุณอธิบายไว้นั้นยากเนื่องจากวัตถุที่แตกต่างกันจริง ๆ การตั้งชื่อพวกเขาจะทำให้เกิดข้อตกลงที่คลุมเครือ
MikaelW

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

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