RESTful API มีแนวโน้มที่จะสนับสนุนโมเดลโดเมนโลหิตจางหรือไม่


34

ฉันกำลังทำงานในโครงการที่เราพยายามใช้ทั้งการออกแบบที่ขับเคลื่อนด้วยโดเมนและ REST กับสถาปัตยกรรมที่มุ่งเน้นบริการ เราไม่กังวลเกี่ยวกับการปฏิบัติตาม REST 100% อาจเป็นการดีกว่าถ้าจะบอกว่าเรากำลังพยายามสร้าง HTTP API ที่เน้นการใช้ทรัพยากร (~ ระดับ 2ของแบบจำลองวุฒิภาวะ REST ของ Richardson) แต่เรากำลังพยายามที่จะอยู่ห่างจากการใช้ RPC-รูปแบบของการร้องขอ HTTP เช่นเราพยายามที่จะดำเนินการของเรา HTTP กริยาตามRFC2616มากกว่าที่จะใช้POSTในการทำIsPostalAddressValid(...)เช่น

อย่างไรก็ตามการเน้นเรื่องนี้ดูเหมือนว่าจะเป็นค่าใช้จ่ายของความพยายามของเราที่จะใช้การออกแบบที่ขับเคลื่อนด้วยโดเมน มีเพียงGET, POST, PUT, DELETEและไม่กี่วิธีที่ไม่ค่อยได้ใช้อื่น ๆ ที่เรามีแนวโน้มที่จะสร้างบริการ cruddy และบริการ cruddy มีแนวโน้มที่จะมีรูปแบบโดเมนโรคโลหิตจาง

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

REST และ DDD มีความตึงเครียดในบางระดับหรือไม่? (หรือฉันเข้าใจผิดบางอย่างที่นี่เราอาจทำผิดอย่างอื่นหรือไม่) เป็นไปได้ไหมที่จะสร้างโมเดลโดเมนที่แข็งแกร่งในสถาปัตยกรรมเชิงบริการขณะที่หลีกเลี่ยงการโทร HTTP สไตล์ RPC?


1
POST ได้รับการออกแบบมาโดยจงใจให้เป็น"เจตนาที่คลุมเครือ;" ผลลัพธ์ของ POST คือการนำไปปฏิบัติโดยเฉพาะ อะไรทำให้คุณไม่สามารถทำสิ่งที่ Twitter และผู้ออกแบบ API อื่นทำและกำหนดแต่ละวิธีของ POST ในส่วนที่ไม่ใช่ CRUD ของ API ของคุณตามข้อกำหนดเฉพาะของคุณเอง
Robert Harvey

@RobertHarvey เราได้ตีความ POST เป็นการสร้าง มองไปที่มาตรฐานอีกครั้งบางทีนั่นอาจจะง่ายเกินไป ตัวอย่างเช่นคุณคิดว่า POST จะทำสิ่งIsPostalAddressValid(...)ใดให้สอดคล้องกับ "การให้บล็อกข้อมูลเช่นผลลัพธ์ของการส่งแบบฟอร์มไปยังกระบวนการจัดการข้อมูล" หรือไม่?
Kazark

นั่นเป็นเพราะไม่มีคำกริยา CREATE (และไม่มีกริยา UPDATE สำหรับเรื่องนั้น) ฉันยืนยันว่าคำกริยาเหล่านั้นหายไปจากมาตรฐาน (ไม่ว่าด้วยเหตุผลใดก็ตาม) ซึ่งเป็นเหตุผลว่าทำไมคุณต้องเลือก POST สำหรับ "ทุกอย่าง" "กระบวนการจัดการข้อมูล" ของคุณในกรณีนี้คือกระบวนการที่ตรวจสอบที่อยู่ทางไปรษณีย์และส่งกลับค่าที่สอดคล้องกับผลลัพธ์ของการวิเคราะห์นั้น
Robert Harvey

1
@ RobertHarvey: ฉันเชื่อว่า POST และ PUT / PATCH เป็นเพียงกริยา CREATE และ UPDATE ที่คุณต้องการ มันมีชื่อแตกต่างกันเพื่อให้คำกริยายังคงทำให้รู้สึกบางอย่างแม้ในการออกแบบที่ไม่สงบ
Lie Ryan

@LieRyan: ฉันจะให้คุณที่ ฉันแค่คิดว่า CRUD หมายถึงรูปแบบข้อมูลโลหิตจางตามคำนิยาม คุณสามารถดำเนินการตามพฤติกรรมบางอย่างถ้าพูดว่าคุณอยู่ใน M ของ MVC แต่ไม่แน่นอนในระบบที่แตกต่างกัน สำหรับทุกอย่างอื่นนอกจาก CRUD คุณต้องมี POST
Robert Harvey

คำตอบ:


38

กฎข้อที่หนึ่งของ Martin Fowler เกี่ยวกับระบบกระจาย: "อย่าแจกจ่ายสิ่งของของคุณ!" อินเทอร์เฟซระยะไกลควรหยาบเม็ดเล็กและอินเทอร์เฟซภายในแบบละเอียด บ่อยครั้งที่อุดมไปด้วยรูปแบบโดเมนใช้เฉพาะภายในบริบทล้อมรอบ

REST API แยกบริบทที่แตกต่างกันสองแบบทั้งสองมีแบบจำลองภายในของตนเอง บริบทสื่อสารผ่านอินเทอร์เฟซแบบหยาบ (REST API) โดยใช้ "anemic" objects (DTO)

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


1
ฟาวเลอร์มีความคิดที่ดีมากมาย แต่อย่าลืมว่าหายนะที่ข้อมูลจำเพาะและการใช้งาน EJB ดั้งเดิมนั้นเป็นอย่างไร หลังจากนั้นพวกเขาก็พบว่าเมธอดระดับต่ำเรียกร้องให้การดำเนินการเล็กน้อยเช่น getName () เป็นฝันร้ายของเครือข่าย / โหลด อินเทอร์เฟซแบบหยาบกลายเป็นหนทางไปและด้วยแนวคิดว่าเอนทิตีกราฟ / ข้อความทั้งหมดถูกส่งและรับในบริบทกริยา + คำนาม
Darrell Teague

9

โพสต์ได้รับการออกแบบโดยเจตนาที่จะ"คลุมเครือจงใจ;" ผลลัพธ์ของ POST คือการนำไปปฏิบัติโดยเฉพาะ อะไรทำให้คุณไม่สามารถทำสิ่งที่ Twitter และผู้ออกแบบ API อื่นทำและกำหนดแต่ละวิธีของ POST ในส่วนที่ไม่ใช่ CRUD ของ API ของคุณตามข้อกำหนดเฉพาะของคุณเอง POST เป็นคำกริยา catchall ใช้มันเมื่อไม่มีคำกริยาอื่นใดที่เหมาะสมกับการใช้งานที่คุณต้องการ

เพื่อให้เป็นไปในอีกทางหนึ่งคำถามของคุณอาจถูกวางอย่างเท่าเทียมกันในฐานะ"วัตถุ" ฉลาด "สนับสนุนการออกแบบสไตล์ RPC หรือไม่" แม้แต่ Martin Fowler (ซึ่งเป็นคนบัญญัติศัพท์คำว่า "Anemic Domain Model") ยอมรับว่า DTO นั้นมีประโยชน์:

การวางพฤติกรรมลงในวัตถุโดเมนไม่ควรขัดแย้งกับแนวทางที่มั่นคงในการใช้การฝังเลเยอร์เพื่อแยกลอจิกโดเมนจากสิ่งต่างๆเช่นความคงทน ตรรกะที่ควรอยู่ในวัตถุโดเมนคือตรรกะโดเมน - การตรวจสอบการคำนวณกฎธุรกิจ - สิ่งที่คุณต้องการเรียก

เกี่ยวกับรูปแบบการครบกำหนดอายุของริชาร์ดสันคุณสามารถไปถึงระดับ 3 ได้โดยไม่ต้องกังวลเกี่ยวกับ "Anemic Domain Models" จำไว้ว่าคุณจะไม่ถ่ายโอนพฤติกรรมไปยังเบราว์เซอร์ (ยกเว้นว่าคุณวางแผนที่จะฉีด Javascript ผ่านโมเดลของคุณ)

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

ดูเพิ่มเติม
ฉันต้องการคำกริยาเพิ่มเติม


ฉันคิดว่าจะตอบคำถาม RFC2616 อย่างแน่นอน สิ่งที่เกี่ยวกับความจริงที่ว่าเรากำลังพยายามที่จะมุ่งเน้นทรัพยากรคืออย่างน้อยพยายามที่จะบรรลุระดับ 2 ในรูปแบบวุฒิภาวะของริชาร์ดสันสำหรับ REST?
Kazark

1
ผมอ่านผ่านmartinfowler.com/articles/richardsonMaturityModel.html คุณสามารถไปถึงระดับ 3 ได้โดยไม่เกี่ยวข้องกับตัวคุณเกี่ยวกับ "Anemic Domain Models" จำไว้ว่าคุณจะไม่ถ่ายโอนพฤติกรรมไปยังเบราว์เซอร์ (ยกเว้นว่าคุณวางแผนที่จะฉีด Javascript ผ่านโมเดลของคุณ)
Robert Harvey

4

REST API เป็นเลเยอร์การนำเสนอเพียงประเภทเดียว ไม่มีส่วนเกี่ยวข้องกับรูปแบบโดเมน

คำถามที่คุณโพสต์นั้นมาจากความสับสนที่คุณต้องปรับตัวเข้าหากัน คุณทำไม่ได้

คุณแมปโมเดลโดเมนของคุณกับ REST API ของคุณเช่นเดียวกับที่คุณแมปโมเดลโดเมนของคุณกับ RDBMS ผ่าน ORM - จะต้องมีเลเยอร์การแมปนี้

โดเมน← ORM →
โดเมนRDBMS ←การจับคู่ REST → REST API


3

IMHO ฉันไม่คิดว่าพวกเขามีแนวโน้มที่จะส่งเสริมโมเดลโดเมนโลหิตจาง (ADM) แต่พวกเขาต้องการให้คุณใช้เวลาและคิดในเรื่องต่างๆ

ก่อนอื่นฉันคิดว่าคุณสมบัติหลักของ ADMs คือพวกเขาไม่มีพฤติกรรมใด ๆ เลย ไม่ได้หมายความว่าระบบไม่มีพฤติกรรม แต่โดยปกติจะอยู่ในประเภท Service class (ดูที่http://vimeo.com/43598193 )

และแน่นอนถ้าพฤติกรรมนั้นไม่มีอยู่ใน ADM แล้วจะเกิดอะไรขึ้น? คำตอบที่แน่นอนคือข้อมูล แล้วแผนที่นี้ไปยัง REST API อย่างไร น่าจะเป็นข้อมูลแผนที่แมปกับเนื้อหาของทรัพยากรและพฤติกรรมแมปกับกริยา HTTP

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

ฉันคิดว่าที่คนมักจะพบปัญหาคือพวกเขามีช่วงเวลาที่ยากลำบากในการดูว่าคำกริยา HTTP จับคู่กับพฤติกรรมโดเมนของพวกเขาอย่างไรเมื่อพฤติกรรมนั้นเกิน CRUD อย่างง่ายเช่นเมื่อมีผลข้างเคียงในส่วนอื่น ๆ ของโดเมน ทรัพยากรที่ถูกแก้ไขโดยการร้องขอ HTTP วิธีหนึ่งในการแก้ไขปัญหานั้นคือเหตุการณ์โดเมน ( http://www.udidahan.com/2009/06/14/domain-events-salvation/ )


3

นี้บทความค่อนข้างเกี่ยวข้องกับเรื่องและผมเชื่อว่าตอบคำถามของคุณ

แนวคิดหลักที่ฉันคิดว่าตอบคำถามของคุณได้ดีสรุปในย่อหน้าต่อไปนี้จากบทความที่กล่าวถึง:

"มันสำคัญมากที่จะต้องแยกแยะความแตกต่างระหว่างทรัพยากรใน REST API และเอนทิตีโดเมนในการออกแบบที่ขับเคลื่อนด้วยโดเมนการออกแบบที่ขับเคลื่อนด้วยโดเมนจะใช้กับการดำเนินการด้านต่าง ๆ (รวมถึงการใช้ API) ในขณะที่ทรัพยากรใน REST API การเลือกไม่ควรขึ้นอยู่กับรายละเอียดการติดตั้งโดเมนพื้นฐาน "


1

การใช้งานที่ประสบความสำเร็จอย่างสมเหตุสมผลหลายครั้งที่ฉันได้เห็น / สร้างตอบคำถามในวิธีที่พวกเขาผสมคำกริยาคำนาม + คำนามโดยใช้วิธีการ 'ธุรกิจที่เป็นมิตร' หยาบหยาบที่ทำหน้าที่ในหน่วยงาน

ดังนั้นแทนที่จะใช้getName()วิธี / บริการ(ถึงวาระ) เปิดเผยgetPerson()ผ่านสิ่งต่าง ๆ เช่น identifier-type / ID เพื่อส่งคืนPersonเอนทิตีทั้งหมด

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

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

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

สิ่งนี้ทำให้เกิดPersonโรคโลหิตจางหรือไม่? ฉันไม่คิดอย่างนั้น

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

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


คะแนนที่ดี --- นี่นำมุมมองใหม่ ๆ มาให้ซึ่งคำตอบอื่น ๆ ยังไม่มี
Kazark

0

ปัญหาของคุณที่คุณพยายามยัดเยียดแบบจำลองของคุณเป็นชุดคำกริยาพื้นฐานโดยใช้ POST ให้มากที่สุดหรือไม่?

ไม่จำเป็น - ฉันรู้ว่าสำหรับคนส่วนใหญ่ REST หมายถึง POST, GET, PUT และ DELETE แต่ http rfc พูดว่า:

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

และระบบต่าง ๆ เช่น SMTP ใช้วิธีการกริยาที่ใช้สไตล์เดียวกัน แต่มีชุดที่แตกต่างกันโดยสิ้นเชิง

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

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

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