REST HATEOAS (ระดับวุฒิภาวะ 3) มีประโยชน์ / สำคัญอย่างไร?


110

ฉันกำลังมีส่วนร่วมในโครงการที่สมาชิกในทีมอาวุโสบางคนเชื่อว่า REST API ต้องเป็นไปตามมาตรฐาน HATEOAS และใช้ระดับวุฒิภาวะทั้งหมดของ Richardson ( http://martinfowler.com/articles/richardsonMaturityModel.html )!

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

คุณคิดอย่างไร? คุณเคยมีประสบการณ์กับ HATEOAS ในโครงการจริงหรือไม่?


นี่คือบทความดีๆเกี่ยวกับเรื่อง: medium.com/@andreasreiser94/…โดยทั่วไปแล้ววิธีการใช้งาน "REST" คือ RPC ...
masterxilo

คำตอบ:


213

ไม่มีใครในชุมชน REST พูดว่า REST เป็นเรื่องง่าย HATEOAS เป็นเพียงหนึ่งในแง่มุมที่เพิ่มความยากให้กับสถาปัตยกรรม REST

ผู้คนไม่ได้ทำ HATEOAS ด้วยเหตุผลทั้งหมดที่คุณแนะนำ: มันยาก เพิ่มความซับซ้อนให้กับทั้งฝั่งเซิร์ฟเวอร์และไคลเอนต์ (หากคุณต้องการได้รับประโยชน์จากมันจริงๆ)

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

คุณรู้หรือไม่ว่าใส่ใจ? ใครก็ตามที่เขียนหน้าจอคัดลอกไคลเอนต์อัตโนมัติของ Amazon ผู้ที่มีแนวโน้มที่จะสูดดมปริมาณการใช้งานเว็บอย่างระมัดระวังอ่านหน้า HTML ฯลฯ เพื่อค้นหาลิงก์ที่จะโทรหาเมื่อใดและกับสิ่งที่จ่าย

และทันทีที่ Amazon เปลี่ยนกระบวนการภายในและโครงสร้าง URL ไคลเอนต์ฮาร์ดโค้ดเหล่านั้นก็ล้มเหลวเพราะลิงก์พัง

แต่นักท่องเว็บทั่วไปสามารถจับจ่ายซื้อของได้ตลอดทั้งวันโดยแทบจะไม่สะดุด

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

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

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

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

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

ไคลเอนต์ที่มอบหมายเวิร์กโฟลว์ส่วนใหญ่ไปยังเซิร์ฟเวอร์และดำเนินการตามผลลัพธ์จะมีประสิทธิภาพในการเปลี่ยนแปลงเซิร์ฟเวอร์มากกว่าไคลเอนต์ที่ไม่

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

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

REST ส่วนใหญ่ล้มเหลวในสัญลักษณ์แสดงหัวข้อย่อย "คุณไม่จำเป็นต้องใช้" จนกว่าจะถึงวันนั้นแน่นอน

ถ้าคุณต้องการก็ใช้และใช้ตามที่วางไว้ REST ไม่ได้ดึงข้อมูลไปมาผ่าน HTTP ไม่เคยมีมาก่อนระดับสูงกว่านั้นมาก

แต่เมื่อคุณต้องการ REST และคุณใช้ REST ดังนั้น HATEOAS ก็เป็นสิ่งจำเป็น เป็นส่วนหนึ่งของแพ็กเกจและเป็นกุญแจสำคัญในการทำงาน


11
ฉันรู้สึกว่าคุณควรมีคนชอบมากกว่าหนึ่งพันคนสำหรับคำตอบนี้ จริงๆแล้วฉันต้องจินตนาการว่า: คำถาม REST 'ของจริง' มีความสำคัญเพียงใด นรกฉันกำลังทำ googling ด้วยเหตุผลแค่นั้นสำหรับกระสุนที่จะใช้ในการประชุมที่กำลังจะมาถึงเมื่อฉันพบหัวข้อนี้
nograde

2
ขอบคุณพระเจ้า (หรือรหัส) มีคนพูดถึงข้อเสียของ HATEOAS เช่นกัน!
IlliakaillI

6
มีข้อดีอื่น ๆ ที่สามารถเปลี่ยน URL ได้อย่างง่ายดายหรือไม่? คุณไม่สามารถเพิ่มตัวเลือกใหม่ ๆ ได้เนื่องจากโปรแกรมไม่สามารถทำงานกับสิ่งใหม่ ๆ ได้ นอกจากนี้คุณยังเปลี่ยนจากการสร้างรู้ URL มาเป็นการรู้ชื่อของการกระทำ
Jimmy T.

หากผู้ใช้ API ไม่ทราบสิ่งใดก็สามารถมอบหมายการกระทำของผู้ใช้ได้ 1: 1 เท่านั้น
Jimmy T.

2
เกี่ยวกับการเปลี่ยนแปลง URL อย่าลืมว่าไคลเอนต์ของคุณอาจใช้แคชดังนั้นคุณต้องรักษาพฤติกรรมบนเซิร์ฟเวอร์เพื่อจัดการกับ URL ก่อนหน้าเช่นกัน (หรือเพียงแค่ทำการเปลี่ยนเส้นทาง) ในฐานะที่เป็นกลยุทธ์ใด ๆ ในการพัฒนา API คุณต้องทำให้พฤติกรรมเก่า ๆ ของคุณใช้งานได้ HATEOAS ไม่ได้ช่วยอะไรมากนัก
Bruno Costa

21

ใช่ฉันมีประสบการณ์เกี่ยวกับไฮเปอร์มีเดียใน API มาบ้างแล้ว นี่คือประโยชน์บางประการ:

  1. Explorable API: อาจฟังดูไม่สำคัญ แต่อย่าดูถูกพลังของ API ที่สามารถสำรวจได้ ความสามารถในการเรียกดูข้อมูลรอบ ๆ ทำให้นักพัฒนาไคลเอนต์สามารถสร้างแบบจำลองทางจิตใจของ API และโครงสร้างข้อมูลได้ง่ายขึ้นมาก

  2. เอกสารแบบอินไลน์: การใช้ URL เป็นความสัมพันธ์ของลิงก์สามารถชี้ให้นักพัฒนาไคลเอ็นต์ไปที่เอกสาร

  3. ตรรกะของไคลเอ็นต์อย่างง่าย: ไคลเอนต์ที่ติดตาม URL แทนที่จะสร้างขึ้นเองควรใช้งานและบำรุงรักษาได้ง่ายกว่า

  4. เซิร์ฟเวอร์เป็นเจ้าของโครงสร้าง URL: การใช้ไฮเปอร์มีเดียจะลบความรู้ฮาร์ดโค้ดของไคลเอ็นต์เกี่ยวกับโครงสร้าง URL ที่เซิร์ฟเวอร์ใช้

  5. ปิดการโหลดเนื้อหาไปยังบริการอื่น ๆ : Hypermedia เป็นสิ่งจำเป็นเมื่อปิดการโหลดเนื้อหาไปยังเซิร์ฟเวอร์อื่น (เช่น CDN)

  6. การกำหนดเวอร์ชันด้วยลิงก์: Hypermedia ช่วยในการกำหนดเวอร์ชันของ API

  7. การใช้งานบริการ / API เดียวกันหลายรายการ: Hypermedia เป็นสิ่งจำเป็นเมื่อมีการใช้งานบริการ / API เดียวกันหลายรายการ ตัวอย่างเช่นบริการอาจเป็นบล็อก API ที่มีแหล่งข้อมูลสำหรับเพิ่มโพสต์และความคิดเห็น หากบริการถูกระบุในแง่ของความสัมพันธ์ของลิงก์แทนที่จะเป็น URL แบบฮาร์ดโค้ดบริการเดียวกันอาจถูกสร้างอินสแตนซ์หลายครั้งที่ URL ที่แตกต่างกันซึ่งโฮสต์โดย บริษัท ต่างๆ แต่ยังคงสามารถเข้าถึงได้ผ่านชุดลิงก์ที่กำหนดไว้อย่างดีโดยไคลเอนต์เดียว

คุณสามารถดูคำอธิบายเชิงลึกของสัญลักษณ์แสดงหัวข้อย่อยเหล่านี้ได้ที่นี่: http://soabits.blogspot.no/2013/12/selling-benefits-of-hypermedia.html

(มีคำถามคล้าย ๆ กันที่นี่: /software/149124/what-is-the-benefit-of-hypermedia-hateoasซึ่งฉันได้ให้คำอธิบายเดียวกัน)


การใช้บริการเดียวกันหลายรายการ: คุณสามารถอธิบายเพิ่มเติมได้หรือไม่? ฉันไม่เห็นว่ามันช่วยได้อย่างไร
Abbadon

ฉันได้พยายามอธิบายเป็นข้อความแล้ว มันช่วย?
Jørn Wildt

11

วุฒิภาวะระดับ 3 ของริชาร์ดสันมีค่าและควรนำไปใช้ Jørn Wildt ได้สรุปข้อดีและคำตอบอื่น ๆ ไว้แล้วโดย Wilt ช่วยเติมเต็มสิ่งนี้ได้เป็นอย่างดี

อย่างไรก็ตามวุฒิภาวะระดับ 3 ของริชาร์ดสันไม่เหมือนกับ HATEOAS ของ Fielding วุฒิภาวะของ Richardson ระดับ 3 เป็นเพียงการออกแบบ API เท่านั้น HATEOAS ของ Fielding นั้นเกี่ยวกับการออกแบบ API เช่นกัน แต่ยังกำหนดด้วยว่าซอฟต์แวร์ไคลเอ็นต์ไม่ควรคิดว่าทรัพยากรมีโครงสร้างเฉพาะนอกเหนือจากโครงสร้างที่กำหนดโดยประเภทสื่อ สิ่งนี้ต้องใช้ไคลเอนต์ทั่วไปเช่นเว็บเบราว์เซอร์ซึ่งไม่มีความรู้เกี่ยวกับเว็บไซต์เฉพาะ เนื่องจาก Roy Fielding ได้บัญญัติศัพท์คำว่า REST และได้ตั้ง HATEOAS เป็นข้อกำหนดสำหรับการปฏิบัติตาม REST คำถามคือเราต้องการใช้ HATEOAS หรือไม่หากไม่สามารถเรียก API RESTful ได้หรือไม่ ฉันคิดว่าเราทำได้ ให้ฉันอธิบาย

สมมติว่าเราประสบความสำเร็จ HATEOAS ขณะนี้แอปพลิเคชันฝั่งไคลเอ็นต์เป็นแบบทั่วไป แต่ส่วนใหญ่แล้วประสบการณ์ของผู้ใช้จะไม่ดีเนื่องจากหากไม่มีความรู้เกี่ยวกับความหมายของทรัพยากรใด ๆ จึงไม่สามารถนำเสนอทรัพยากรให้เหมาะกับความหมายเหล่านั้นได้ หากทรัพยากร "รถ" และ "บ้าน" ของทรัพยากรมีประเภทสื่อเดียวกัน (เช่น application / json) ทรัพยากรเหล่านี้จะถูกนำเสนอต่อผู้ใช้ในลักษณะเดียวกันตัวอย่างเช่นเป็นตารางคุณสมบัติ (คู่ชื่อ / ค่า)

แต่โอเค API ของเราน่าอยู่จริงๆ

ตอนนี้สมมติว่าเราสร้างแอปพลิเคชันไคลเอนต์ตัวที่สองที่ด้านบนของ API นี้ ไคลเอนต์รายที่สองนี้ละเมิดแนวคิด HATEOAS และมีข้อมูลที่เข้ารหัสเกี่ยวกับทรัพยากร จะแสดงรถและบ้านในรูปแบบต่างๆ

API ยังสามารถเรียกว่า RESTful ได้หรือไม่ ฉันคิดอย่างนั้น ไม่ใช่ความผิดของ API ที่ลูกค้ารายใดรายหนึ่งละเมิด HATEOAS

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

ผมได้รวมส่วนที่เกี่ยวกับ HATEOAS ในรูปแบบการดำเนินงานส่วนที่เหลือของฉันเรียกว่าJAREST


9

เรากำลังสร้าง REST ระดับ 3 API โดยคำตอบของเราอยู่ใน HAL-Json HATEOAS เหมาะสำหรับทั้งด้านหน้าและด้านหลัง แต่มันมาพร้อมกับความท้าทาย เราได้ทำการปรับแต่ง / เพิ่มเติมบางอย่างสำหรับการจัดการ ACL ภายในการตอบสนอง HAL-Json (ซึ่งไม่ทำลายมาตรฐาน HAL-Json)

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

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

ข้อดีอีกประการของการใช้ HAL-Json คือมีความชัดเจนว่ารูปแบบการตอบสนองควรมีลักษณะอย่างไรเนื่องจากมีเอกสารมาตรฐานที่ควรปฏิบัติตาม

หนึ่งของการปรับแต่งของเราคือการที่เราเพิ่มการกระทำของวัตถุภายในวัตถุการเชื่อมโยงตัวเองที่ exposes ไปยังส่วนหน้าซึ่งการกระทำหรือการดำเนินการ CRUD ผู้ใช้รับรองความถูกต้องได้รับอนุญาตให้ดำเนินการเกี่ยวกับทรัพยากรที่เกี่ยวข้อง ( create:POST, read:GET, update:PUT, edit:PATCH, delete:DELETE) เช่นนี้ ACL ฟรอนต์เอนด์ของเราถูกกำหนดโดยการตอบสนอง REST API ของเราโดยย้ายความรับผิดชอบนี้ไปยังโมเดลแบ็คเอนด์อย่างเต็มที่

ดังนั้นเพื่อให้เป็นตัวอย่างสั้น ๆ คุณสามารถมีวัตถุโพสต์ใน HAL-Json ที่มีลักษณะดังนี้:

{
    "_links": {
        "self": {
            "href": "https://hostname/api/v1/posts/1",
            "actions": {
                "read": "GET",
                "update": "PUT",
                "delete": "DELETE"
            }
        }
    },
    "_embedded": {
        "owner": {
            "id": 1,
            "name": "John Doe",
            "email": "john.doe@example.com",
            "_links": {
                "self": {
                    "href": "https://hostname/api/v1/users/1",
                    "actions": {
                        "read": "GET"
                    }
                }
            }
        }
    },
    "subject": "Post subject",
    "body": "Post message body"
}

ตอนนี้สิ่งที่เราต้องทำในส่วนหน้าคือสร้างAclServiceด้วยisAllowedวิธีการที่ตรวจสอบว่าการกระทำที่เราต้องการดำเนินการอยู่ในวัตถุการดำเนินการหรือไม่

ขณะนี้อยู่ในส่วนหน้าดูเหมือนง่ายเหมือน: post.isAllowed('delete');

ฉันคิดว่า REST ระดับ 3 ดีมาก แต่อาจทำให้ปวดหัวได้ คุณจะต้องมีความเข้าใจอย่างดีเยี่ยมเกี่ยวกับ REST และหากคุณต้องการทำงานกับ REST ระดับ 3 ฉันขอแนะนำให้ปฏิบัติตามแนวคิด REST อย่างเคร่งครัดมิฉะนั้นคุณจะหลงทางได้ง่ายเมื่อนำไปใช้

ในกรณีของเราเรามีข้อได้เปรียบที่เราสร้างทั้งส่วนหน้าและส่วนหลัง แต่โดยหลักการแล้วไม่ควรสร้างความแตกต่าง แต่ข้อผิดพลาดทั่วไปที่ฉันพบในทีมของเราคือนักพัฒนาบางรายพยายามแก้ไขปัญหาส่วนหน้า (สถาปัตยกรรม) โดยการเปลี่ยนโมเดลแบ็กเอนด์เพื่อให้ "เหมาะกับ" ความต้องการของส่วนหน้า


1
ตอบได้ดีมาก. ฉันคิดว่าตัวอย่างที่ใช้ได้จริงคือสิ่งที่ผู้ถามเดิมกำลังมองหา
www.admiraalit.nl

2

ฉันใช้ HATEOAS ในโครงการจริงบางโครงการ แต่มีการตีความที่แตกต่างจาก Richardson ถ้านั่นคือสิ่งที่เจ้านายของคุณต้องการฉันเดาว่าคุณควรทำมัน ฉันใช้ HATEOAS เพื่อหมายความว่าทรัพยากรของคุณควรมีประเภท HTML การเชื่อมโยงหลายมิติไปยังทรัพยากรที่เกี่ยวข้องและรูปแบบ HTML เพื่อแสดงฟังก์ชันการทำงานของคำกริยาอื่นที่ไม่ใช่ GET (นี่คือเมื่อประเภทการยอมรับคือข้อความ / html - เนื้อหาประเภทอื่น ๆ ไม่ต้องการสิ่งพิเศษเหล่านี้) ฉันไม่รู้ว่าความเชื่อที่ว่าทรัพยากร REST ทั้งหมดในแอปพลิเคชันทั้งหมดของคุณต้องติดกาวเข้าด้วยกันนั้นมาจากไหน แอปพลิเคชันเครือข่ายควรมีทรัพยากรหลายอย่างที่อาจเกี่ยวข้องโดยตรงหรือไม่ก็ได้ หรือทำไมจึงเชื่อว่า XML, JSON และประเภทอื่น ๆ ต้องเป็นไปตามนี้ (HATEOAS เป็น HTML โดยเฉพาะ)

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