Saya mencoba merangkul kepala saya di sekitar cara terbaik untuk mengatasi konsep dalam API berbasis REST. Sumber daya datar yang tidak mengandung sumber daya lain tidak masalah. Tempat saya mengalami masalah adalah sumber daya yang kompleks.
Misalnya, saya punya sumber daya untuk buku komik. ComicBook
memiliki segala macam properti pada rasanya author
, issue number
, date
, dll
Buku komik juga memiliki daftar 1..n
sampul. Penutup ini adalah benda yang kompleks. Mereka berisi banyak informasi tentang sampul: artis, tanggal, dan bahkan gambar dasar 64 yang disandikan dari sampul.
Untuk GET
di ComicBook
saya hanya bisa mengembalikan komik, dan semua selimut termasuk gambar mereka base64'ed. Itu mungkin bukan masalah besar untuk mendapatkan komik tunggal. Tapi misalkan saya sedang membangun aplikasi klien yang ingin membuat daftar semua komik dalam sistem dalam sebuah tabel.
Tabel akan berisi beberapa properti dari ComicBook
sumber daya, tetapi kami tentu tidak ingin menampilkan semua sampul dalam tabel. Mengembalikan 1000 buku komik, masing-masing dengan beberapa sampul akan menghasilkan data dalam jumlah sangat besar yang datang dari kawat, data yang tidak perlu bagi pengguna akhir dalam kasus itu.
Naluriku adalah membuat Cover
sumber daya dan memiliki ComicBook
sampul. Jadi sekarang Cover
adalah URI. GET
pada buku komik berfungsi sekarang, alih-alih Cover
sumber daya besar yang kami kirim kembali URI untuk setiap sampul dan klien dapat mengambil sumber daya Sampul saat mereka membutuhkannya.
Sekarang saya punya masalah dengan membuat komik baru. Tentunya saya akan ingin membuat setidaknya satu sampul ketika saya membuat Comic
, pada kenyataannya itu mungkin aturan bisnis.
Jadi sekarang aku terjebak, aku baik memaksa klien untuk menegakkan aturan bisnis dengan terlebih dahulu mengirimkan Cover
, mendapatkan URI untuk menutupi itu, maka POST
ing ComicBook
dengan yang URI dalam daftar, atau saya POST
di ComicBook
mengambil di sumber daya tampak berbeda dari yang meludah di luar. Sumber daya yang masuk untuk POST
dan GET
merupakan salinan yang dalam, di mana yang keluar GET
berisi referensi ke sumber daya yang tergantung.
Sumber Cover
daya mungkin diperlukan dalam hal apa pun karena saya yakin sebagai klien saya ingin membahas arah sampul dalam beberapa kasus. Jadi masalahnya ada dalam bentuk umum terlepas dari ukuran sumber daya dependen. Secara umum bagaimana Anda menangani sumber daya yang kompleks tanpa memaksa klien untuk hanya "tahu" bagaimana sumber daya itu disusun?
sumber
Jawaban:
@ray, diskusi yang bagus
@ jgerman, jangan lupa hanya karena itu ISTIRAHAT, tidak berarti sumber daya harus diatur dari POST.
Apa yang Anda pilih untuk dimasukkan ke dalam representasi sumber daya apa pun terserah Anda.
Kasus sampul yang dirujuk secara terpisah hanyalah ciptaan sumber daya orang tua (buku komik) yang sumber dayanya (sampul) dapat dirujuk silang. Misalnya, Anda mungkin juga ingin memberikan referensi kepada penulis, penerbit, karakter, atau kategori secara terpisah. Anda mungkin ingin membuat sumber daya ini secara terpisah atau sebelum buku komik yang merujuknya sebagai sumber daya anak. Atau, Anda mungkin ingin membuat sumber daya anak baru setelah membuat sumber daya induk.
Kasus spesifik Anda dari sampul sedikit lebih kompleks karena sampul benar-benar membutuhkan buku komik, dan sebaliknya.
Namun, jika Anda menganggap pesan email sebagai sumber daya, dan alamat dari sebagai sumber daya anak, Anda masih dapat merujuk alamat dari secara terpisah. Misalnya, dapatkan semua dari alamat. Atau, buat pesan baru dengan alamat sebelumnya dari. Jika email REST, Anda dapat dengan mudah melihat bahwa banyak sumber daya rujukan silang dapat tersedia: / pesan-diterima, / konsep-pesan, / dari-alamat, / ke-alamat, / alamat, / subjek, / lampiran, / folder , / tag, / kategori, / label, dkk.
Tutorial ini memberikan contoh yang bagus dari sumber referensi silang. http://www.peej.co.uk/articles/restfully-delicious.html
Ini adalah pola paling umum untuk data yang dihasilkan secara otomatis. Misalnya, Anda tidak memposting URI, ID, atau tanggal pembuatan untuk sumber daya baru, karena ini dihasilkan oleh server. Namun, Anda dapat mengambil URI, ID, atau tanggal pembuatan ketika Anda mendapatkan kembali sumber daya baru.
Contoh dalam kasus data biner Anda. Misalnya, Anda ingin memposting data biner sebagai sumber daya anak. Ketika Anda mendapatkan sumber daya induk, Anda dapat mewakili sumber daya anak tersebut sebagai data biner yang sama, atau sebagai URI yang mewakili data biner.
Bentuk & parameter sudah berbeda dari representasi HTML dari sumber daya. Posting parameter biner / file yang menghasilkan URL bukan peregangan.
Ketika Anda mendapatkan formulir untuk sumber daya baru (/ buku komik / baru), atau mendapatkan formulir untuk mengedit sumber daya (/ buku komik / 0 / edit), Anda meminta representasi spesifik formulir dari sumber daya. Jika Anda mempostingnya ke kumpulan sumber daya dengan tipe konten "application / x-www-form-urlencoded" atau "multipart / form-data", Anda meminta server untuk menyimpan representasi tipe itu. Server dapat merespons dengan representasi HTML yang disimpan, atau apa pun.
Anda mungkin juga ingin memperbolehkan representasi HTML, XML, atau JSON untuk diposkan ke koleksi sumber daya, untuk tujuan API atau sejenisnya.
Dimungkinkan juga untuk mewakili sumber daya dan alur kerja Anda seperti yang Anda gambarkan, dengan memperhitungkan sampul akun yang dipasang setelah buku komik, tetapi membutuhkan buku komik untuk memiliki sampul. Contohnya sebagai berikut.
DAPATKAN / buku komik
=> 200 OK, Dapatkan semua buku komik.
DAPATKAN / buku komik / 0
=> 200 OK, Dapatkan buku komik (id: 0) dengan sampul (/ sampul / 1, / sampul / 2).
DAPATKAN / buku komik / 0 / sampul
=> 200 OK, Dapatkan sampul untuk buku komik (id: 0).
DAPATKAN / mencakup
=> 200 OK, Dapatkan semua penutup.
DAPATKAN / mencakup / 1
=> 200 OK, Dapatkan sampul (id: 1) dengan buku komik (/ buku komik / 0).
DAPATKAN / buku komik / baru
=> 200 OK, Dapatkan formulir untuk membuat buku komik (formulir: POST / draft-buku komik).
POST / draft-komik-buku
judul = foo
penulis = boo
penerbit = goo
diterbitkan = 2011-01-01
=> 302 Ditemukan, Lokasi: / draft-komik-buku / 3, Redirect ke draft buku komik (id: 3) dengan meliputi (biner).
DAPATKAN / draft-komik-buku / 3
=> 200 OK, Dapatkan draft komik buku (id: 3) dengan sampul.
DAPATKAN / draft-komik-buku / 3 / sampul
=> 200 OK, Dapatkan sampul untuk buku komik (/ draft-komik-buku / 3).
DAPATKAN / draft-komik-buku / 3 / sampul / baru
=> 200 OK, Dapatkan formulir untuk membuat sampul untuk draft buku komik (/ draft-komik-buku / 3) (form: POST / draft-komik-buku / 3 / meliputi).
POST / draft-komik-buku / 3 / sampul
cover_type = sampul
depan_data = (biner)
=> 302 Ditemukan, Lokasi: / draft-komik-buku / 3 / sampul, Redirect ke sampul baru untuk buku komik draft (/ draft-komik) -buku / 3 / sampul / 1).
DAPATKAN / draft-komik-buku / 3 / publish
=> 200 OK, Dapatkan formulir untuk menerbitkan draft buku komik (id: 3) (bentuk: POST / buku-komik-terbitan).
POST / publikasi-komik-
judul buku = foo
penulis = boo
penerbit = goo
diterbitkan = 2011-01-01
cover_type = depan
cover_data = (biner)
=> 302 Ditemukan, Lokasi: / komik-buku / 3, Redirect ke buku komik yang diterbitkan (id: 3) dengan sampul.
sumber
Memperlakukan tutup sebagai sumber daya jelas dalam semangat REST, terutama HATEOAS. Jadi ya,
GET
permintaan untukhttp://example.com/comic-books/1
memberi Anda representasi buku 1, dengan properti termasuk seperangkat URI untuk sampul. Sejauh ini baik.Pertanyaan Anda adalah bagaimana menangani pembuatan buku komik. Jika aturan bisnis Anda adalah bahwa sebuah buku akan memiliki 0 atau lebih sampul, maka Anda tidak memiliki masalah:
dengan data buku komik tanpa penutup akan membuat buku komik baru dan mengembalikan server yang dihasilkan id (katakanlah kembali menjadi 8), dan sekarang Anda dapat menambahkan sampul seperti:
dengan penutup di badan entitas.
Sekarang Anda memiliki pertanyaan yang bagus, apa yang terjadi jika aturan bisnis Anda mengatakan harus selalu ada setidaknya satu penutup. Berikut adalah beberapa pilihan, yang pertama kali Anda identifikasi dalam pertanyaan Anda:
Dorong pembuatan sampul terlebih dahulu, sekarang pada dasarnya menjadikan sampul sebagai sumber daya yang tidak bergantung, atau Anda menempatkan sampul awal di badan entitas POST yang membuat buku komik. Ini seperti yang Anda katakan berarti bahwa representasi yang Anda POST buat akan berbeda dari representasi yang Anda GET.
Definisikan gagasan tentang penutup utama, atau awal, atau lebih disukai, atau yang ditunjuk lain. Ini kemungkinan merupakan hack pemodelan, dan jika Anda melakukan itu akan seperti mengubah model objek Anda (model konsep atau bisnis Anda) agar sesuai dengan teknologi. Bukan ide yang bagus.
Anda harus mempertimbangkan dua pilihan ini dengan hanya membiarkan komik tanpa penutup.
Manakah dari tiga pilihan yang harus Anda ambil? Tidak tahu terlalu banyak tentang situasi Anda, tetapi jawablah pertanyaan umum 1..N yang tidak tergantung pada sumber daya, saya akan mengatakan:
Jika Anda bisa menggunakan 0..N untuk lapisan layanan RESTful Anda, bagus. Mungkin lapisan antara SOA RESTful Anda dapat menangani kendala bisnis lebih lanjut jika setidaknya diperlukan. (Tidak yakin bagaimana kelihatannya tetapi mungkin perlu ditelusuri .... pengguna akhir biasanya tidak melihat SOA.)
Jika Anda hanya harus memodelkan kendala 1..N, tanyakan pada diri Anda apakah sampul mungkin hanya sumber daya yang dapat dibagi, dengan kata lain, mereka mungkin ada pada hal-hal lain selain buku komik. Sekarang mereka bukan sumber daya yang tergantung dan Anda dapat membuatnya terlebih dahulu dan memasok URI di POST Anda yang membuat buku komik.
Jika Anda membutuhkan 1..N dan penutup tetap tergantung, cukup relakskan insting Anda untuk menjaga agar representasi di POST dan DAPATKAN sama, atau buat sama.
Item terakhir dijelaskan seperti ini:
Ketika Anda POST, Anda mengizinkan uris yang ada jika Anda memilikinya (meminjam dari buku lain) tetapi juga memasukkan satu atau lebih gambar awal. Jika Anda membuat buku dan entitas Anda tidak memiliki gambar sampul awal, kembalikan respons 409 atau serupa. Pada GET Anda dapat mengembalikan URI ..
Jadi pada dasarnya Anda membiarkan representasi POST dan GET menjadi "sama" tetapi Anda hanya memilih untuk tidak "menggunakan" gambar sampul pada GET atau menutupi POST. Harapan itu masuk akal.
sumber