URL REST ที่ซ้อนกันและรหัสหลักซึ่งมีการออกแบบที่ดีกว่า


20

เอาล่ะเรามีสองทรัพยากร: และAlbum Songนี่คือ API:

GET,POST /albums
GET,POST /albums/:albumId
GET,POST /albums/:albumId/songs
GET,POST /albums/:albumId/songs/:songId

เรารู้ว่าเราเกลียดบางเพลงมันถูกเรียกSusyเช่น เราควรsearchลงมือทำที่ไหน?

คำถามอื่น โอเคตอนนี้มันเป็นของจริงมากขึ้น เราเปิดอัลบั้มที่ 1 และโหลดเพลงทั้งหมด เราสร้างวัตถุ JS removeแต่ละเก็บข้อมูลเพลงและมีวิธีการบางอย่างเพื่อให้: update,

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

ดังนั้นฉันเห็นวิธีแก้ปัญหาเล็กน้อย แต่ฉันไม่แน่ใจจริงๆ

  1. ทำให้ id หลักเป็นตัวเลือก - ตามที่ได้รับพารามิเตอร์ ฉันใช้วิธีนี้ในปัจจุบัน แต่ฉันรู้สึกว่ามันน่าเกลียด

    List,Create /songs?album=albumId
    Update,Delete /songs/:songId
    Get /songs/?name=susy # also, solution for first question
    
  2. เป็นลูกผสม ตอนนี้มีประโยชน์เพราะเราต้องการรหัสอัลบั้มเพื่อทำการOPTIONSสืบค้นเพื่อรับข้อมูลเมตา

    List,Create /album/:albumId/songs
    Update,Delete /songs/:songId
    POST /songs/search # also, solution for first question
    
  3. ส่งคืน URL แบบเต็มกับแต่ละอินสแตนซ์ของทรัพยากร API เหมือนกัน แต่เราจะได้รับเพลงเช่นนี้:

    id: 5
    name: 'Elegy'
    url: /albums/2/songs/5
    

    ฉันได้ยินว่าวิธีการนี้เรียกว่า HATEOAS

  4. ดังนั้น ... เพื่อให้ ID ผู้ปกครอง

    id: 5
    name: 'Elegy'
    albumId: 2
    

ไหนดีกว่ากัน หรือบางทีฉันอาจเป็นคนโง่? โยนคำแนะนำพวก!

คำตอบ:


31

เราควรทำการค้นหาที่ไหน?

ในGET /search/:text. นี่จะส่งคืนอาร์เรย์ JSON ที่มีการจับคู่ทุกการแข่งขันที่มีอัลบั้มที่เป็นของมัน เรื่องนี้สมเหตุสมผลเพราะลูกค้าอาจไม่สนใจในตัวแทร็ก แต่ทั้งอัลบั้ม (ลองนึกภาพว่าคุณกำลังค้นหาเพลงที่คุณเชื่อว่าอยู่ในอัลบั้มเดียวกับที่คุณจำชื่อ)

มันจะไม่ดีที่จะส่งกลับรหัสผู้ปกครองด้วยกัน ฉันผิดหรือเปล่า?

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

ไหนดีกว่ากัน

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

หรือบางทีฉันอาจเป็นคนโง่?

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

สิ่งที่อาจเป็นปัญหาคือวิธีที่คุณจัดระเบียบข้อมูลภายในเช่นการใช้งานของลำดับชั้น จากความคิดเห็นของคุณคุณกำลังสงสัยในสิ่งที่ควรมีคำตอบGET /artist/1/album/10/song/3/comment/23ซึ่งแสดงวิสัยทัศน์ที่มุ่งเน้นต้นไม้ สิ่งนี้สามารถนำไปสู่ปัญหาเล็กน้อยเมื่อขยายระบบในภายหลัง ตัวอย่างเช่น

  • จะทำอย่างไรถ้าเพลงไม่มีอัลบั้ม
  • เกิดอะไรขึ้นถ้าอัลบั้มมีศิลปินหลายคน
  • ถ้าคุณต้องการเพิ่มคุณสมบัติที่ทำให้สามารถแสดงความคิดเห็นอัลบั้มได้
  • เกิดอะไรขึ้นถ้าควรมีความคิดเห็นของความคิดเห็น?
  • เป็นต้น

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

จะเกิดอะไรขึ้นถ้าคุณทำลายลำดับชั้น? มาดูกัน.

  1. GET /albums/:albumIdส่งคืน JSON ที่มีข้อมูลเมตาเกี่ยวกับอัลบั้ม (เช่นปีที่เผยแพร่หรือ URI ของ JPEG ที่แสดงปกอัลบั้ม) และอาร์เรย์ของแทร็ก ตัวอย่างเช่น:

    GET /albums/151
    {
        "id": 151,
        "gid": "dbd3cec7-b927-423f-894b-742c4c7b54ce",
        "name": "Yellow Submarine",
        "year": 1969,
        "genre": "Psychedelic rock",
        "artists": ["John Lennon", "Paul McCartney", ...],
        "tracks": [
            {
                "id": 90224,
                "title": "Yellow Submarine",
                "length": "2:40"
            },
            {
                "id": 83192,
                "title": "Only a Northern Song",
                "length": "3:24"
            }
            ...
        ]
    }

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

  2. GET /tracks/:trackIdส่งคืนข้อมูลเกี่ยวกับแทร็กเฉพาะ เนื่องจากไม่มีลำดับชั้นอีกต่อไปคุณไม่จำเป็นต้องเดาอัลบั้มหรือศิลปิน: สิ่งเดียวที่คุณต้องรู้ก็คือตัวระบุของแทร็กเอง

    หรืออาจจะไม่? ถ้าคุณสามารถระบุชื่อด้วยGET /tracks/:trackName?

    GET /tracks/Only%20a%20Northern%20Song
    {
        "id": 83192,
        "gid": "8d9c4311-9d7b-40a4-8aeb-4fe96247fe2b",
        "title": "Only a Northern Song",
        "writers": ["George Harrison"],
        "artists": ["John Lennon", "Paul McCartney", "Ringo Starr"],
        "length": "3:24",
        "record-date": 1967,
        "albums": [151, 164],
        "soundtrack": {
            "uri": "http://audio.example.com/tracks/static/83192.mp3",
            "alias": "Beatles - Only a Northern Song.mp3",
            "length-bytes": 3524667,
            "allow-streaming": true,
            "allow-download": false
        }
    }

    มองใกล้albumsๆ คุณเห็นอะไร? ใช่ไม่ใช่หนึ่ง แต่สองอัลบั้ม หากคุณมีลำดับชั้นคุณไม่สามารถทำเช่นนั้นได้ (เว้นแต่คุณจะทำซ้ำบันทึก)

  3. GET /comments/:objectGid. คุณอาจเห็น GUID ที่น่าเกลียดในการตอบกลับ GUID เหล่านั้นทำให้สามารถระบุเอนทิตีข้ามฐานข้อมูลเพื่อดำเนินงานที่สามารถนำไปใช้กับอัลบั้มหรือศิลปินหรือแทร็กได้ เช่นการแสดงความคิดเห็น

    GET /comments/8d9c4311-9d7b-40a4-8aeb-4fe96247fe2b
    [
        {
            "author": {
                "id": 509931,
                "display-name": "Arseni Mourzenko"
            },
            "text": "What a great song! (And I'm proud of the usefulness of my comment)",
            "concerned-object": "/tracks/83192"
        }
    ]

    ความคิดเห็นอ้างอิงถึงวัตถุที่เกี่ยวข้องทำให้เป็นไปได้เมื่อเข้าถึงความคิดเห็นนอกบริบท (ตัวอย่างเช่นเมื่อทำการกลั่นกรองความคิดเห็นล่าสุดผ่านGET /comments/latest)

โปรดทราบว่านี่ไม่ได้หมายความว่าคุณควรหลีกเลี่ยงรูปแบบลำดับชั้นใน API ของคุณ มีหลายกรณีที่มันสมเหตุสมผล ตามกฎของหัวแม่มือ:

  • หากทรัพยากรไม่มีเหตุผลนอกบริบทของทรัพยากรหลักให้ใช้ลำดับชั้น

  • หากทรัพยากรสามารถมีชีวิตอยู่ (1) เพียงอย่างเดียวหรือ (2) ในบริบทของทรัพยากรหลักประเภทต่าง ๆ หรือ (3) มีผู้ปกครองหลายคนไม่ควรใช้ลำดับชั้น

ตัวอย่างเช่นบรรทัดของไฟล์ที่ไม่เหมาะสมนอกบริบทของไฟล์ดังนั้น:

GET /file/:fileId

และ:

GET /file/:fileId/line/:lineIndex

เป็นเรื่องปกติ


ใช่จากการค้นหาฉันสามารถส่งคืนข้อมูลอัลบั้มแบบเต็มได้เช่นกันมันจะเป็นแหล่งข้อมูลอื่นSongSearchResultๆ แต่ URL เกี่ยวกับอะไร ฉันควรให้parentIDกับแต่ละวัตถุและใช้เป็นพารามิเตอร์ GET หรือส่วนปกติของ URL หรือไม่ จะเป็นอย่างไรถ้าฉันมีความลึก> 2 /artist/1/album/10/song/3/comment/23- มันบ้าที่จะให้ id ศิลปินอัลบั้มและเพลงในcommentวัตถุทุกอย่าง แต่ฉันได้ยินว่ามันเป็นวิธีที่จะไป แต่ไม่ได้เป็น dsigusting!
dt0xff

@ dt0xff: ฉันแก้ไขคำตอบของฉัน ฉันคิดว่ามันควรจะให้ภาพที่ชัดเจนเกี่ยวกับวิธีการหลีกเลี่ยงความลึก
Arseni Mourzenko

ใช่แล้วตอนนี้มันชัดเจนแล้วว่ามันง่ายกว่าที่จะใช้จุดเริ่มต้นสำหรับแต่ละทรัพยากร (ยกเว้นบางอย่างเช่นบรรทัดหรือสิ่งอื่น ๆ ที่ทำงานได้) โดยไม่มีการเพิ่มลงใน parent โดย url ขอบคุณคุณทำให้ฉันเชื่อว่าตัวเลือกของฉันถูกต้องและ "วิธีการทั่วไป" (จริง ๆ แล้วสิ่งที่ซ้อนกันมากมาย .. restangularสร้างขึ้นบนนั้น) ไม่ดี
dt0xff

คำตอบที่ดี ฉันมีข้อโต้แย้งเล็กน้อย "จะเป็นอย่างไรถ้าอัลบั้มมีศิลปินหลายคน" URI ที่แตกต่างกันสามารถระบุทรัพยากรเดียวกันได้เนื่องจาก URI ความสัมพันธ์แบบไบนารี -> ทรัพยากรนั้นไม่ซ้ำกัน (หลายต่อหนึ่ง) ดังนั้น URI/artists/foo/albums/quxและ/artists/bar/albums/quxสามารถระบุทรัพยากรอัลบั้มเดียวกันได้อย่างสมบูรณ์แบบ กล่าวอีกนัยหนึ่งองค์ประกอบของเส้นทางใน URI แสดงถึงลำดับชั้นของกราฟไม่จำเป็นต้องเป็นลำดับชั้นของต้นไม้ซึ่งทำให้มันเหมาะสำหรับการแสดงไม่เพียง แต่หมวดหมู่ แต่ยังรวมถึงแท็ก
Maggyero

1
... "นี่เป็นหลัก ปัญหาที่ฉันอธิบายในบล็อกของฉัน : การแทนต้นไม้มีข้อ จำกัด มากมายเกินกว่าที่จะใช้ได้อย่างมีประสิทธิภาพในหลาย ๆ กรณี" ดังนั้นไม่ใช่นี่ไม่ใช่ปัญหา "จะทำอย่างไรถ้าคุณต้องการเพิ่มคุณสมบัติที่ทำให้สามารถแสดงความคิดเห็นอัลบั้มได้?" นั่นไม่ใช่ปัญหาอย่างใดอย่างหนึ่ง: /artists/foo/albums/qux/comments/7. "จะเกิดอะไรขึ้นถ้ามีความเห็นเกี่ยวกับความคิดเห็น?" เช่นเดียวกัน: /artists/foo/albums/qux/song/5/comments/2/comments/8.
Maggyero
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.