ทำไม REST Api ไม่ทำตามรูปแบบการออกแบบ Facade


9

ในการเปรียบเทียบ REST [api] โครงสร้างกับโมเดล OO ฉันเห็นความคล้ายคลึงกันเหล่านี้:

ทั้งสอง:

  • กำลังมุ่งเน้นข้อมูล

    • REST = ทรัพยากร
    • OO = วัตถุ
  • ล้อมรอบการดำเนินงานรอบข้อมูล

    • REST = ล้อมรอบ VERBS (รับ, โพสต์, ... ) รอบ ๆ แหล่งข้อมูล
    • OO = ส่งเสริมการดำเนินการรอบ ๆ วัตถุโดยห่อหุ้ม

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

ความสัมพันธ์ของวัตถุอย่างง่ายระหว่าง 2 แนวคิด

คล้ายคลึงกันระหว่าง OO และ REST

ในทางตรงกันข้าม REST ส่งเสริมการเผยแพร่ทรัพยากรของความสัมพันธ์ทั้งหมดกับทรัพยากรและอื่น ๆ ในรูปแบบอย่างน้อยสองรูปแบบ:

  1. ผ่านความสัมพันธ์ลำดับชั้นของทรัพยากร (ผู้ติดต่อของ id 43 ประกอบด้วยที่อยู่ 453): /api/contacts/43/addresses/453

  2. ผ่านลิงก์ในการตอบสนอง REST json:

>> GET /api/contacts/43
<< HTTP Response {
   id: 43, ...
   addresses: [{
      id: 453, ...
   }],
   links: [{
      favoriteAddress: {
          id: 453
      }
   }]
}

ความซับซ้อนพื้นฐานถูกซ่อนโดย objectA

กลับมาที่ OO รูปแบบการออกแบบซุ้มเคารพLow Couplingระหว่างobjectAและ ' objectB client ' และHigh CohesionสำหรับobjectAนี้และการประกอบวัตถุภายใน ( objectC , objectD ) ด้วยอินเตอร์เฟสobjectAสิ่งนี้อนุญาตให้ผู้พัฒนา จำกัด ผลกระทบต่อobjectBของการเปลี่ยนแปลงภายในobjectA (ในobjectCและobjectD ) ตราบใดที่objectA api (การทำงาน) ยังคงได้รับการเคารพ

ใน REST ข้อมูล (ทรัพยากร) ความสัมพันธ์ (ลิงก์) และพฤติกรรม (คำกริยา) จะถูกกระจายในองค์ประกอบต่าง ๆ และพร้อมใช้งานบนเว็บ

เล่นกับ REST ฉันมักจะมีผลกระทบต่อการเปลี่ยนแปลงรหัสระหว่างไคลเอนต์และเซิร์ฟเวอร์ของฉัน: เนื่องจากฉันมีHigh Couplingระหว่างBackbone.jsคำขอและLow Cohesionระหว่างทรัพยากร

ฉันไม่เคยคิดวิธีที่จะให้Backbone.js javascript applicationข้อตกลงของฉันกับการค้นพบ " ทรัพยากรและคุณสมบัติ REST " ที่ได้รับการโปรโมตโดยลิงก์ REST ฉันเข้าใจว่า WWW นั้นให้บริการโดยเซิร์ฟเวอร์หลายเครื่องและองค์ประกอบ OO จะต้องถูกระเบิดเพื่อให้บริการโดยโฮสต์หลายแห่งในนั้น แต่สำหรับสถานการณ์แบบง่าย ๆ เช่น "บันทึก" หน้าที่แสดงรายชื่อที่อยู่ ท้ายที่สุดฉัน:

GET /api/contacts/43?embed=(addresses)
[save button pressed]
PUT /api/contacts/43
PUT /api/contacts/43/addresses/453

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

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


1
ให้ฉันเข้าใจ คุณกำลังบอกว่าคุณต้องอัปเดตผู้ติดต่อด้วยที่อยู่ที่เชื่อมโยง "ฝังตัว" (การแต่งเพลง) โดยใช้การเรียกใช้ REST สองครั้งหนึ่งที่อยู่ติดต่อและอีกอันสำหรับที่อยู่ คุณมีซุ้มเพื่อจัดการการอัปเดตผู้ติดต่อ ปัญหาที่เกิดขึ้นกับการPUT /api/contacts/43เรียงซ้อนการปรับปรุงสำหรับวัตถุภายในคืออะไร? ฉันมี API จำนวนมากที่ได้รับการออกแบบเช่นนี้ (URL หลักอ่าน / สร้าง / อัปเดต "ทั้ง" และ URL ย่อยอัปเดตชิ้นส่วน) เพียงตรวจสอบให้แน่ใจว่าคุณไม่ได้อัปเดตที่อยู่เมื่อไม่ต้องการการเปลี่ยนแปลง (สำหรับเหตุผลด้านประสิทธิภาพ)
Anthony Accioly

@AnthonyAccioly คุณเข้าใจถูกต้อง ฉันพยายามชี้แจงคำถามของฉันโดยเพิ่มรูปภาพบางรูป ข้อเสนอแนะของคุณนั้นดีและนั่นก็เป็นข้อสรุปที่ฉันได้รับ: การควบคุมคำขอของฉันด้วยตนเองและใช้วัตถุฝังตัวเพื่อส่งคำขอเพียงครั้งเดียวเพื่อให้การอัปเดตอะตอมมิกของฉันดำเนินต่อไป ยัง: ทำไมทุกอย่างในส่วนที่เหลือผลักฉันออกไปจากคุณภาพ OO หรือการบังคับใช้ (encapsulation, ... ) โดยแบนแบบจำลองของฉัน (หมายถึงตัวควบคุมจำนวนมาก) การใช้โซลูชันของคุณให้การอัปเดตอะตอมมิก 1 ครั้ง การไม่ใช้โซลูชันของคุณจะทำให้นักพัฒนามีความรับผิดชอบใหม่และไม่มีกฎระเบียบเกี่ยวกับ API เพื่อป้องกันไม่ให้เขาทำเช่นนั้น
Alain

เพียงหมายเหตุ: "ความสัมพันธ์ลำดับชั้นของทรัพยากร" ที่คุณกล่าวถึงนั้นเป็นเรื่องของวิธีการที่อาจตัดสินใจเข้ารหัสข้อมูลความสัมพันธ์ในตัวระบุ (ในกรณีนี้คือ URL) ฉันไม่แน่ใจว่าการเปิดเผยข้อมูลนี้เป็นสิ่งที่เป็นส่วนหนึ่งของ REST หรือสิ่งที่ส่งเสริมเพียงแค่การตัดสินใจของเขาเองเมื่อมากับ URL ของระบบ หากคุณเชื่อเป็นอย่างอื่นคุณมีการอ้างอิงของ Roy Fielding ในการพูดคุยเรื่องนี้เป็นส่วนหนึ่งของ REST หรือไม่?
Thiago Silva

คำตอบ:


7

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

ขอให้เราอย่าสับสนPODS (ซึ่งน้อยกว่าโครงสร้าง) และวัตถุจริงที่มีพฤติกรรม (เช่นContactsชั้นเรียนในตัวอย่างของคุณ) 1 .

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

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

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

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

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

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

ตอนนี้ควรเห็นได้ชัดว่าการวิเคราะห์การออกแบบข้อมูลด้วยแนวคิด OOไม่ใช่วิธีที่เชื่อถือได้ในการวัด: มันเหมือนกับการเปรียบเทียบแอปเปิ้ลและส้ม!

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

ฉันหวังว่านี่จะตอบคำถามของคุณได้หลายแง่มุม :-)


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

2 http://en.wikipedia.org/wiki/Cohesion_(computer_science)


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

[ข้อความ 1] ฉันใช้คำว่า "data" เป็นนามธรรมจาก OO และ REST world คำใดที่คุณจะใช้กับคุณสมบัตินามธรรมใน OO และโครงสร้างข้อมูลใน REST
Alain

@ "data" เป็นสิ่งที่ดี แต่ประเด็นของฉันคือไม่ทำให้ PODS และวัตถุธุรกิจสับสน เมื่อเราพูดถึง OOD เรามักพูดถึงเรื่องที่สอง สิ่งแรกคือความสะดวกสบายและอาจเป็นความคิดที่ง่ายเหมือนพจนานุกรมหรือโครงสร้างหรือสิ่งอันดับ
Sklivvz

ใช่ฉันเห็นด้วยฉันใช้ Backbone.js ซึ่งการบันทึกโมเดลกำลังใช้โครงสร้าง json แบบง่าย นี่คือที่ข้อความสะท้อนให้เห็นถึงประสบการณ์การเข้ารหัสที่แท้จริงของฉัน
Alain

[ข้อความ 3] นี่เป็นเรื่องใหม่สำหรับฉัน ฉันคิดว่าการทำงานร่วมกันนั้นวัดจากจำนวนวิธีที่ใช้ความสัมพันธ์เฉพาะ ... ฉันชอบวิธีการดูของคุณมากกว่า
Alain

1

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

คำตอบของ "การพักสงบอยู่ที่ไหน" มีการวิเคราะห์และอธิบายอย่างละเอียดที่นี่: http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm

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

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


1

นั่นเป็นเพราะซุ้มเป็น 'kludge'; คุณควรดู 'api abstraction' และ 'api chaining' api เป็นการรวมกันของการทำงานสองชุด: I / O และการจัดการทรัพยากร ในพื้นที่ I / O นั้นใช้ได้ แต่ภายในสถาปัตยกรรมแบบกระจาย (เช่นพร็อกซี, api gate, คิวข้อความ ฯลฯ ) I / O นั้นจะถูกแชร์และทำให้ข้อมูลและการทำงานซ้ำซ้อนและเข้ากันได้ สิ่งนี้นำไปสู่ข้อกังวลข้ามสถาปัตยกรรม ภัยพิบัตินี้ apis ที่มีอยู่ทั้งหมด

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

http://www.slideshare.net/bobdobbes/api-abstraction-api-chaining


0

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

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

มันเป็นสิ่งที่ล้ำสมัยและเป็นที่ยอมรับกันอย่างกว้างขวางว่ามันเป็นความคิดที่ดีที่จะใส่ตรรกะบิซใด ๆ ลงในโค้ด UI แต่ UI ทุกตัวเป็นเพียงส่วนต่อประสาน (I in UI) เพื่อควบคุมตรรกะบิซหลัง ดังนั้นจึงเห็นได้ชัดว่าเป็นความคิดที่ดีที่จะนำตรรกะ biz ใด ๆ ลงในเลเยอร์บริการ REST หรือเลเยอร์ API อื่น ๆ

แนวคิดในการพูดมีความแตกต่างไม่มากนักระหว่าง UI และ API บริการ


ฉันเห็นด้วยกับความคิดของเลเยอร์ แต่คุณหมายถึงอะไรโดย "โปรแกรมควบคุมผ่านมัน"?
Alain

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