HATEOAS ให้ความสำคัญกับลูกค้าเป็นอย่างไร


35

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

GET /account/12345 HTTP/1.1 HTTP/1.1 200 OK 
<?xml version="1.0"?> 
<account> 
    <account_number>12345</account_number> 
    <balance currency="usd">100.00</balance> 
    <link rel="deposit" href="/account/12345/deposit" /> 
    <link rel="withdraw" href="/account/12345/withdraw" /> 
    <link rel="transfer" href="/account/12345/transfer" /> 
    <link rel="close" href="/account/12345/close" /> 
</account>

ร่วมกับข้อมูลมีลิงค์บอกสิ่งที่สามารถทำได้ต่อไป หากยอดคงเหลือเป็นลบเรามี

GET /account/12345 HTTP/1.1 HTTP/1.1 200 OK 
<?xml version="1.0"?> 
<account> 
    <account_number>12345</account_number> 
    <balance currency="usd">-25.00</balance> 
    <link rel="deposit" href="/account/12345/deposit" /> 
</account>

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

อย่างไรก็ตามประเด็นก็คือเมื่อเราสร้างลูกค้าเช่นสปาที่มี Javascript หรือแอพ Android หรือสิ่งอื่น ๆ อีกมากมายฉันไม่สามารถเห็นได้ว่า HATEOAS มีความเกี่ยวข้องกันอย่างไร สิ่งที่ฉันหมายถึงมีดังต่อไปนี้: เมื่อฉันเขียนรหัส SPA ใน javascript ฉันต้องรู้สิ่งที่สามารถทำได้ใน API เพื่อที่จะเขียนโค้ด

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

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

ดังนั้น HATEOAS มีความสำคัญต่อลูกค้าอย่างไร ทำไมเราถึงรำคาญกับ HATEOAS ล่ะ?


1
คุณพูดถูก แต่นั่นไม่ใช่ประเด็น HATEOAS ช่วยให้คุณไม่ต้องสร้าง URIs สำหรับลิงก์ในหน้าของลูกค้า
James McLeod

คำตอบ:


24

แอพที่เรากำลังสร้างจะไม่เพียงแค่ดูลิงก์จากนั้นแสดง UI ที่ถูกต้องและทำการโทร ajax ที่ถูกต้อง

ในความเป็นจริงนี้เป็นว่าสิ่งที่ HATEOAS จะให้การ UI ไม่ใช่สิ่งที่เป็นไปได้ แต่เมื่อเป็นไปได้ HATEOAS ที่เป็นทางการเช่นHALในฐานะคำถามจะให้ลิงก์ที่บ่งบอกถึงสิ่งที่เป็นไปได้ แต่เมื่อลิงค์เหล่านั้นปรากฏขึ้นขึ้นอยู่กับสถานะของแอปพลิเคชัน ดังนั้นลิงก์สามารถเปลี่ยนแปลงทรัพยากรเมื่อเวลาผ่านไป (ขึ้นอยู่กับการกระทำที่ได้ทำไปแล้ว)

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


2
ดังนั้นเมื่อสร้าง UI เรายังจำเป็นต้องรู้ทุกอย่างที่ API เสนอแล้วมองไปที่ลิงก์เหล่านั้นเราสามารถทราบสถานะของข้อมูลบนเซิร์ฟเวอร์ได้หรือไม่ ตัวอย่างเช่น UI รู้ว่ามีความเป็นไปได้ที่จะฝากถอนถอนหรือปิด (รู้ rels ที่เป็นไปได้) จากนั้นตรวจสอบสิ่งที่กลับมาเพื่อดูสถานะหรือไม่
user1620696

1
ใช่มันทำได้ อีกครั้งขึ้นอยู่กับว่าไดนามิกที่คุณต้องการใช้ ดังที่คนอื่น ๆ ได้กล่าวถึงความสามารถในการเปลี่ยนลิงค์บนเซิร์ฟเวอร์ (และไม่ทำลายลูกค้า) เป็นข้อได้เปรียบอีกประการหนึ่ง และนี่กลายเป็นสิ่งที่น่าสนใจมากเมื่อ API ของคุณมีลูกค้า iPhone, Android, Windows Phone, เว็บบนมือถือและเว็บที่ใช้งานทั้งหมด
Davin Tryon

@ user1620696 คุณควรรู้ทั้งหมดนี้ต่อไปผ่านทางไคลเอนต์และเซิร์ฟเวอร์ที่มีเนื้อหาประเภทที่เข้าใจหากการดำเนินการต่อ ประเภทเนื้อหามีมากกว่า dumb xml หรือ Json มาก คุณควรมีเนื้อหาประเภท "เงินฝากธนาคาร" ที่ลูกค้าเข้าใจวิธีการทำงานกับ
Cormac Mulhall

1
@Nik ดูที่HALเพื่อดูตัวอย่างวิธีการเชื่อมโยงที่ให้ไว้ในการตอบกลับ
Davin Tryon

1
ใช่คุณยังมีข้อกังวลเกี่ยวกับความเข้ากันได้ย้อนหลัง สิ่งนี้สามารถแก้ไขได้โดยรวมส่วนหัวของรุ่นหรือรุ่นใน URL แต่ฉันจะบอกว่าคุณเข้าใจถูกต้อง
Davin Tryon

3

ในขณะที่ฉันเข้าใจว่า HATEOAS นั้นเกี่ยวกับการส่งลิงก์ตอบกลับแต่ละลิงก์พร้อมด้วยข้อมูลเกี่ยวกับสิ่งที่ต้องทำต่อไป

HATEOAS เป็นมากกว่าการเชื่อมโยง มันคือ "สื่อไฮเปอร์" เป็นเครื่องมือของรัฐแอพลิเคชัน

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

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

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

สิ่งนี้จะเก็บไว้แม้ว่า "ผู้ใช้" เป็นโปรแกรมคอมพิวเตอร์อื่น สื่อไฮเปอร์เองควรกำหนดบริบทของการนำทาง


1
นี่ไม่ได้หมายความว่าคุณจะต้องสร้างไคลเอนต์ที่ซับซ้อน (และมีแนวโน้มที่จะเกิดข้อผิดพลาด) เป็นเบราว์เซอร์หรือไม่? ความยืดหยุ่นมักมาพร้อมกับความซับซ้อนเป็นค่าใช้จ่าย ...
Andres F.

@AndresF ไม่ได้หมายความว่าคุณต้องหรือควรทำเช่นนั้นเพียงให้ตัวเลือกในการทำแบบไดนามิกหากคุณต้องการหรือต้องการ
Peteris

2
@ นิคแน่นอน ด้านบนของหัวของฉันคิดว่าคุณมีบริการที่ให้ข้อมูลบรรพบุรุษผ่าน API พักผ่อน คุณมีประเภทเนื้อหาที่กำหนดรูปแบบของทรัพยากร 'บุคคล' ที่มีข้อมูลต่าง ๆ เกี่ยวกับพวกเขา แต่ยังกำหนดความสัมพันธ์ที่มีลักษณะเช่นพูดว่า 'พี่ชาย' หรือ 'น้องสาว' หรือ 'แม่' เป็นต้นเพราะนี่คือสื่อสิ่งพิมพ์ มี URI ให้กับทรัพยากรบุคคลอื่น ไคลเอนต์ที่ค่อนข้างง่ายโดยใช้คำกริยา HTTP และทำความเข้าใจกับประเภทเนื้อหา 'บุคคล' นี้สามารถนำทางผ่าน API นี้ สมมติว่าคุณต้องการค้นหาผู้สืบทอดโดยตรงทั้งหมดของบุคคลใดบุคคลหนึ่ง
Cormac Mulhall

2
@nik ไคลเอนต์นี้ต้องเข้าใจเพียงแค่ประเภทเนื้อหาของทรัพยากรที่มีการเข้าถึงและกริยา HTTP (GET, PUT, DELETE ฯลฯ ) และคุณสามารถนำทางผ่าน API การดึงและอัปเดตทรัพยากรนี้ และที่สำคัญกว่านั้นไคลเอนต์ที่เข้าใจประเภทเนื้อหาสามารถข้ามผ่าน URI ไปยังเซิร์ฟเวอร์อื่นทั้งหมดและดำเนินการต่อเหมือนเดิม พวกเขาไม่สนใจเซิร์ฟเวอร์ที่พวกเขากำลังพูดถึงพวกเขาสนใจเฉพาะประเภทเนื้อหาของทรัพยากรพวกเขาเข้าใจหรือไม่
Cormac Mulhall

1
@ นิกดังนั้นในสถานการณ์เช่นนี้คุณมีเซิร์ฟเวอร์ที่เข้าใจประเภทเนื้อหาดั้งเดิม (พูดบุคคล v1) และประเภทเนื้อหาใหม่ (บุคคล v2) ลูกค้าเข้าใจบุคคล v1 เท่านั้น ลูกค้าบอกเซิร์ฟเวอร์ว่าประเภทเนื้อหานั้นเข้าใจผ่านทางส่วนหัวยอมรับใน HTTP การใช้การเจรจาต่อรองเนื้อหาเซิร์ฟเวอร์จะพิจารณาว่าจะส่งสิ่งที่ลูกค้าสนับสนุนหรือไม่ซึ่งในกรณีนี้จะส่งคืนทรัพยากรโดยใช้ประเภทเนื้อหา Person v1 ตอนนี้คุณอาจต้องการหยุดการสนับสนุนประเภทเนื้อหาเก่านี้และสามารถส่งข้อผิดพลาด 406 ให้ลูกค้าได้ มันเป็นการดีกว่าที่จะลองและสนับสนุนเท่าที่คุณสามารถ
Cormac Mulhall

2

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

การใช้เลย์เอาต์แบบไดนามิกสามารถทำได้ง่ายๆ btw:

links.forEach(function(link) {

  switch(link.rel) {

    case 'deposit':
      showDepositButton();
      break;

    case 'withdraw':
      loadWithdrawForm(link.href);
      showWithdrawButton();
      break;
  }

});

มันช่วยให้คุณประหยัดในรหัสลูกค้าของคุณเช่น:

if (balance <= 0 && negativeBalanceAllowed === false) {
  showWithdrawButton();
}

คุณสามารถใช้ตำแหน่งเชิงลบที่ได้รับอนุญาต (โดยการยืมเงินตัวอย่าง) โดยไม่ต้องเปลี่ยนลูกค้าของคุณ


เป็นตัวอย่างที่แข็งแกร่งขึ้นเล็กน้อยธนาคารสามารถเสนอวงเงินเบิกเกินบัญชีผันแปรในบัญชีของตนได้โดยไม่ต้องแจ้งให้ลูกค้าทราบว่าวงเงินนั้นมีอยู่ในแต่ละบัญชีเท่าใด
Bart van Ingen Schenau

ถูกต้องคุณสามารถตัดสินใจเกี่ยวกับการ จำกัด ยอดคงเหลือที่ซับซ้อนตามที่คุณต้องการและยังคงไม่ต้องทำการเปลี่ยนแปลงกับลูกค้า หากคุณใช้ส่วนนี้เพิ่มเติมกับส่วนที่เหลือเช่นประเภทเนื้อหาคุณสามารถแสดงมุมมองที่แตกต่าง ตัวอย่างเช่นบัญชีมีลักษณะแตกต่างจากการทำธุรกรรม ที่น่าสนใจคือรหัสตามความต้องการ (แม้ว่าจะมีการใช้งานไม่มาก) ที่สามารถใช้เป็นตัวอย่างสำหรับตัวประมาณการยืม สามารถให้ฟังก์ชั่นเครื่องคิดเลขอย่างง่ายของอินเตอร์เฟสได้ดังนั้นลูกค้าจะต้องใช้อินพุตสำหรับการคำนวณเท่านั้น มันจะอยู่ up-to-date จาก back-end
Luc Franken

2
แต่มักจะเป็นความต้องการของลูกค้าที่จะรู้ว่าทำไมมันไม่สามารถถอนตัวดังนั้นเราจึงยังคงต้องส่ง ENUM reasonหรือสตริงในสาขาที่แยกต่างหากเพื่อลูกค้าที่มี และถ้าเรายังต้องการมันทำไมไม่เพียงส่งฟิลด์บูลีนอื่นให้เขาcanWithdrawแทนลิงก์ไปยังแอ็คชั่น ข้อดีอีกประการคือความสามารถในการเปลี่ยน URL ของการกระทำโดยไม่ต้องแตะไคลเอ็นต์ แต่ .. เหตุผลอะไรที่ต้องเปลี่ยน URL? ในกรณีส่วนใหญ่มันยังเปลี่ยนแปลงบางอย่างในความหมายหรือพารามิเตอร์หรือรูปร่างคำขอ / ตอบกลับดังนั้นเราจึงจำเป็นต้องเปลี่ยนลูกค้า ดังนั้นฉันยังไม่เข้าใจ - ประเด็นของ HATEOAS
Ruslan Stelmachenko
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.