Dalam artikel ini penulis mengklaim hal itu
Terkadang, diperlukan untuk mengekspos operasi di API yang secara inheren tidak TETAP.
dan itu
Jika API memiliki terlalu banyak tindakan, maka itu merupakan indikasi bahwa API dirancang dengan sudut pandang RPC daripada menggunakan prinsip RESTful, atau bahwa API yang dipermasalahkan secara alami lebih cocok untuk model tipe RPC.
Ini mencerminkan apa yang telah saya baca dan dengar di tempat lain juga.
Namun saya merasa ini cukup membingungkan dan saya ingin mendapatkan pemahaman yang lebih baik tentang masalah ini.
Contoh I: Mematikan VM melalui antarmuka REST
Ada, saya pikir, dua cara yang berbeda secara mendasar untuk memodelkan penutupan VM. Setiap cara mungkin memiliki beberapa variasi, tetapi mari kita berkonsentrasi pada perbedaan paling mendasar untuk saat ini.
1. Patch properti negara sumber daya itu
PATCH /api/virtualmachines/42
Content-Type:application/json
{ "state": "shutting down" }
(Atau, PUT
pada sub-sumber daya /api/virtualmachines/42/state
.)
VM akan dimatikan di latar belakang dan pada suatu saat tergantung waktu apakah pemadaman akan berhasil atau tidak keadaan mungkin diperbarui secara internal dengan "matikan".
2. PUT atau POST di properti tindakan sumber daya
PUT /api/virtualmachines/42/actions
Content-Type:application/json
{ "type": "shutdown" }
Hasilnya persis sama seperti pada contoh pertama. Negara akan diperbarui untuk "mematikan" segera dan mungkin pada akhirnya untuk "mematikan".
Apakah keduanya desain TETAP?
Desain mana yang lebih baik?
Contoh II: CQRS
Bagaimana jika kita memiliki domain CQRS dengan banyak "tindakan" (alias perintah) yang berpotensi menyebabkan pembaruan beberapa agregat atau tidak dapat dipetakan ke operasi CRUD pada sumber daya dan sub-sumber daya yang konkret?
Haruskah kita mencoba memodelkan sebanyak mungkin perintah yang dibuat atau memperbarui sumber daya konkret, di mana dimungkinkan (mengikuti pendekatan pertama dari contoh I) dan menggunakan "titik akhir tindakan" untuk sisanya?
Atau haruskah kita memetakan semua perintah untuk bertindak titik akhir (seperti pada pendekatan kedua contoh I)?
Di mana kita harus menggambar garis? Kapan desain menjadi kurang tenang?
Apakah model CQRS lebih cocok untuk RPC seperti API?
Menurut teks yang dikutip di atas itu, seperti yang saya mengerti.
Seperti yang dapat Anda lihat dari banyak pertanyaan saya, saya sedikit bingung tentang topik ini. Bisakah Anda membantu saya mendapatkan pemahaman yang lebih baik tentang hal itu?
sumber
Jawaban:
Dalam kasus pertama (shut-down VMs), saya menganggap tidak ada alternatif OP yang tenang. Memang, jika Anda menggunakan model jatuh tempo Richardson sebagai tolok ukur, mereka berdua leve 2 API karena mereka menggunakan sumber daya dan kata kerja.
Namun, tidak satu pun dari mereka yang menggunakan kontrol hypermedia, dan menurut saya, itulah satu-satunya jenis REST yang membedakan desain RESTful API dari RPC. Dengan kata lain, tetap dengan level 1 dan 2, dan Anda akan memiliki API gaya RPC dalam banyak kasus.
Untuk memodelkan dua cara berbeda mematikan VM, saya akan mengekspos VM itu sendiri sebagai sumber daya yang (di antaranya) berisi tautan:
Jika klien ingin mematikan
Ploeh
VM, ia harus mengikuti tautan denganshut-down
tipe hubungan. (Biasanya, sebagaimana diuraikan dalam RESTful Web Services Cookbook , Anda akan menggunakan IRI atau skema identifikasi yang lebih rumit untuk tipe hubungan, tapi saya memilih untuk menjaga contoh sesederhana mungkin.)Dalam hal ini, ada sedikit informasi lain untuk diberikan dengan tindakan, sehingga klien harus membuat POST kosong terhadap URL di
href
:(Karena permintaan ini tidak memiliki badan, akan tergoda untuk memodelkan ini sebagai permintaan GET, tetapi permintaan GET seharusnya tidak memiliki efek samping yang dapat diamati, sehingga POST lebih benar.)
Demikian juga, jika klien ingin mematikan VM, itu akan mengikuti
power-off
tautan.Dengan kata lain, jenis hubungan dari link memberikan affordances yang menunjukkan niat. Setiap tipe hubungan memiliki signifikansi semantik tertentu. Inilah alasan mengapa kita kadang-kadang berbicara tentang web semantik .
Untuk menjaga agar contoh sejelas mungkin, saya sengaja mengaburkan URL di setiap tautan. Ketika server hosting menerima permintaan yang masuk, itu akan tahu itu
fdaIX
berarti mematikan , danCHTY91
berarti mematikan .Biasanya, saya hanya menyandikan tindakan dalam URL itu sendiri, sehingga URL akan
/vms/1234/shut-down
dan/vms/1234/power-off
, tetapi ketika mengajar, itu mengaburkan perbedaan antara jenis hubungan (semantik) dan URL (detail implementasi).Bergantung pada klien yang Anda miliki, Anda dapat mempertimbangkan untuk membuat RESTful URLs non-hackable .
CQRS
Ketika berbicara tentang CQRS, salah satu dari beberapa hal yang disetujui Greg Young dan Udi Dahan adalah bahwa CQRS bukan arsitektur tingkat atas . Jadi, saya akan berhati-hati membuat API RESTful terlalu mirip CQRS, karena itu berarti bahwa klien menjadi bagian dari arsitektur Anda.
Seringkali, kekuatan pendorong di belakang API RESTful (level 3) yang nyata adalah bahwa Anda ingin dapat mengembangkan API Anda tanpa menghancurkan klien, dan tanpa memiliki kendali terhadap klien. Jika itu motivasi Anda, maka CQRS tidak akan menjadi pilihan pertama saya.
sumber
DELETE
tampaknya aneh bagi saya karena setelah mematikan vm akan tetap ada, hanya dalam keadaan "matikan" (atau sth. seperti itu).Mematikan VM melalui antarmuka REST
Ini sebenarnya adalah contoh yang agak terkenal, diajukan oleh Tim Bray pada tahun 2009 .
Roy Fielding, membahas masalah, berbagi pengamatan ini :
Singkatnya, Anda memiliki satu sumber informasi yang mengembalikan representasi saat ini dari keadaan yang dipantau; representasi yang mungkin menyertakan tautan hypermedia ke formulir yang meminta perubahan ke negara itu, dan formulir memiliki tautan lain ke sumber daya untuk menangani (setiap) permintaan perubahan.
Seth Ladd memiliki wawasan utama dalam masalah tersebut
Pemrograman yang tenang adalah birokrasi Vogon pada skala web. Bagaimana Anda melakukan sesuatu dengan tenang? Ciptakan dokumen baru untuk itu, dan digitalkan dokumen itu.
Dalam bahasa yang agak lebih menarik, yang Anda lakukan adalah mendefinisikan protokol aplikasi domain untuk "mematikan VM", dan mengidentifikasi sumber daya yang Anda perlukan untuk mengekspos / mengimplementasikan protokol itu
Lihat contoh Anda sendiri
Tidak apa-apa; Anda tidak benar-benar memperlakukan permintaan itu sendiri sebagai sumber informasi terpisah, tetapi Anda masih bisa mengaturnya.
Anda telah sedikit ketinggalan dalam representasi perubahan Anda.
Misalnya, tipe media JSON Patch memformat instruksi seolah-olah Anda secara langsung memodifikasi dokumen JSON
Dalam alternatif Anda, idenya dekat, tetapi tidak jelas benar.
PUT
adalah penggantian lengkap status sumber daya di URL target , jadi Anda mungkin tidak akan memilih ejaan yang terlihat seperti koleksi sebagai target representasi entitas tunggal .Konsisten dengan fiksi bahwa kami menambahkan tindakan ke antrian
Konsisten dengan fiksi bahwa kami membuat pembaruan ke item ekor dalam antrian; agak aneh melakukannya dengan cara ini. Prinsip kejutan paling tidak merekomendasikan memberikan setiap PUT itu pengidentifikasi unik sendiri, daripada menempatkan mereka semua di satu tempat dan memodifikasi beberapa sumber daya pada saat yang sama.
Perhatikan bahwa, sejauh kita membahas ejaan URI - REST tidak peduli;
/cc719e3a-c772-48ee-b0e6-09b4e7abbf8b
adalah URI cromulen sempurna sejauh REST yang bersangkutan. Keterbacaan, seperti halnya nama variabel, merupakan masalah tersendiri. Menggunakan ejaan yang konsisten dengan RFC 3986 akan membuat orang jauh lebih bahagia.CQRS
Greg Young di CQRS
Mengingat Anda berbicara tentang CQRS dalam konteks HTTP / REST, tampaknya masuk akal untuk menganggap Anda bekerja dalam konteks yang terakhir ini, jadi mari kita mulai dengan itu.
Yang ini, secara mengejutkan, bahkan lebih mudah daripada contoh Anda sebelumnya. Alasannya sederhana: perintah adalah pesan .
Jim Webber menggambarkan HTTP sebagai protokol aplikasi kantor tahun 1950-an; pekerjaan dilakukan dengan mengambil pesan dan memasukkannya ke dalam kotak masuk. Gagasan yang sama berlaku - kami mendapatkan salinan kosong formulir, mengisinya dengan spesifikasi yang kami tahu, mengirimkannya. Ta da
Ya, sejauh "sumber daya konkret" adalah pesan, bukan entitas dalam model domain.
Gagasan utama: API REST Anda masih merupakan antarmuka ; Anda harus dapat mengubah model yang mendasarinya tanpa klien perlu mengubah pesan. Saat Anda merilis model baru, Anda merilis versi baru titik akhir web Anda yang tahu cara mengambil protokol domain Anda dan menerapkannya ke model baru.
Tidak juga - khususnya, cache web adalah contoh yang bagus dari "model baca yang akhirnya konsisten". Membuat setiap tampilan Anda dapat diatasi secara independen, masing-masing dengan aturan caching mereka sendiri, memberi Anda banyak penskalaan secara gratis. Ada sedikit daya tarik untuk pendekatan RPC eksklusif untuk membaca.
Untuk menulis, ini adalah pertanyaan penipu: mengirim semua perintah ke penangan tunggal pada titik akhir tunggal, atau satu keluarga titik akhir, tentu lebih mudah . REST benar-benar lebih tentang bagaimana Anda menemukan komunikasi di mana titik akhir adalah untuk klien.
Memperlakukan pesan sebagai sumber dayanya yang unik memiliki keuntungan bahwa Anda dapat menggunakan PUT, mengingatkan komponen perantara terhadap fakta bahwa penanganan pesan idempoten, sehingga mereka dapat berpartisipasi dalam kasus-kasus penanganan kesalahan tertentu, adalah hal yang baik untuk dimiliki . (Catatan: bahwa dari sudut pandang klien, jika sumber daya memiliki URI yang berbeda, maka mereka adalah sumber daya yang berbeda; fakta bahwa mereka semua mungkin memiliki kode penangan permintaan yang sama pada server asal adalah detail implementasi yang disembunyikan oleh seragam antarmuka).
Fielding (2008)
sumber
Anda bisa memanfaatkan 5 level jenis media untuk menentukan perintah di bidang header tipe konten dari permintaan.
Dalam contoh VM, itu akan menjadi sesuatu di sepanjang garis ini
Kemudian
Atau
Lihat https://www.infoq.com/articles/rest-api-on-cqrs
sumber
Contoh dalam artikel tertaut didasarkan pada gagasan bahwa memulai mesin dan mematikannya harus diarahkan oleh perintah alih-alih oleh perubahan dalam keadaan sumber daya yang dimodelkan. Yang terakhir adalah apa yang REST hidup dan bernafas. Pemodelan VM yang lebih baik membutuhkan cara kerja rekan di dunia nyata dan bagaimana Anda, sebagai manusia, akan berinteraksi dengannya. Ini bertele-tele, tapi saya pikir itu memberikan wawasan yang baik tentang jenis pemikiran yang diperlukan untuk melakukan pemodelan yang baik.
Ada dua cara untuk mengontrol status daya komputer di meja saya:
Untuk VM, keduanya dapat dimodelkan sebagai nilai Boolean baca / tulis:
power
- Ketika diubah menjaditrue
, tidak ada yang terjadi selain catatan yang dibuat bahwa saklar telah ditempatkan ke keadaan ini. Ketika diubah menjadifalse
, VM diperintahkan untuk segera dimatikan. Demi kelengkapan, jika nilainya tidak berubah setelah menulis, tidak ada yang terjadi.onoff
- Ketika berubah menjaditrue
, tidak ada yang terjadi jikapower
adalahfalse
, jika VM diperintahkan untuk memulai. Ketika berubah menjadifalse
, tidak ada yang terjadi jikapower
yangfalse
, jika tidak, VM diperintahkan untuk memberitahu perangkat lunak untuk melakukan shutdown teratur, yang akan melakukan dan kemudian memberitahu VM yang bisa masuk ke power-off negara. Sekali lagi, untuk kelengkapan, tulisan tanpa perubahan tidak melakukan apa-apa.Dengan semua ini muncul kesadaran bahwa ada satu situasi ketika keadaan mesin tidak mencerminkan keadaan sakelar, dan itu selama shutdown.
power
masih akantrue
danonoff
akan tetapfalse
, tetapi prosesor masih menjalankan shutdown, dan untuk itu kita perlu menambahkan sumber daya lain sehingga kita dapat mengetahui apa yang sebenarnya dilakukan mesin:running
- Nilai hanya bacatrue
saat itulah VM berjalan danfalse
ketika tidak, ditentukan dengan menanyakan hypervisor untuk kondisinya.Hasilnya adalah bahwa jika Anda ingin memulai VM, Anda harus memastikan
power
danonoff
sumber daya telah ditetapkantrue
. (Anda bisa membiarkanpower
langkah dilewati dengan membuatnya mengatur ulang sendiri, sehingga jika diatur kefalse
, menjaditrue
setelah VM telah benar-benar dihentikan. Apakah itu hal yang benar-benar murni untuk dilakukan adalah makanan untuk diskusi lain.) Jika Anda ingin melakukan shutdown teratur, Anda mengaturonoff
untukfalse
dan kembali lagi nanti untuk melihat apakah mesin benar-benar berhenti, pengaturanpower
untukfalse
jika tidak.Seperti dunia nyata, Anda masih memiliki masalah diarahkan untuk memulai VM setelah
onoff
diubah menjadifalse
tetapi masihrunning
karena itu di tengah-tengah shutdown. Bagaimana Anda mengatasinya adalah keputusan kebijakan.sumber
Jadi jika Anda ingin berpikir dengan tenang maka lupakan perintah. Klien tidak memberi tahu server untuk mematikan VM. Klien "show dow" (secara kiasan) salinan perwakilan sumber daya mereka dengan memperbarui statusnya dan kemudian PUT representasi itu kembali ke server. Server menerima bahwa representasi negara baru dan sebagai efek samping dari ini, sebenarnya mematikan VM. Aspek efek samping diserahkan ke server.
Itu kurang dari
Hai server, klien di sini, maukah Anda mematikan VM
dan lebih banyak lagi
Hai server, klien di sini, saya memperbarui status sumber daya VM 42 ke dalam kondisi mati, perbarui salinan sumber daya ini dan kemudian lakukan apa yang menurut Anda sesuai
Sebagai efek samping dari server yang menerima keadaan baru ini, ia dapat memeriksa tindakan apa yang sebenarnya harus dilakukan (seperti mematikan VM 42 secara fisik), tetapi ini transparan bagi klien. Klien tidak peduli dengan tindakan apa pun yang harus dilakukan server untuk menjadi konsisten dengan keadaan baru ini
Jadi lupakan perintah. Satu-satunya perintah adalah kata kerja dalam HTTP untuk transfer negara. Klien tidak tahu, juga tidak peduli, bagaimana server akan mendapatkan VM fisik ke keadaan mati. Klien tidak mengeluarkan perintah ke server untuk mencapai ini, ia hanya mengatakan Ini adalah keadaan baru, cari tahu .
Kekuatan ini adalah bahwa ia memisahkan klien dari server dalam hal kontrol aliran. Jika nanti server mengubah cara kerjanya dengan VM, klien tidak peduli. Tidak ada titik akhir perintah untuk memperbarui. Di RPC jika Anda mengubah titik akhir API dari
shutdown
keshut-down
Anda telah menghancurkan semua klien Anda karena mereka sekarang tidak tahu perintah untuk memanggil di server.REST mirip dengan pemrograman deklaratif, di mana alih-alih mendaftar sekumpulan instruksi untuk mengubah sesuatu, Anda hanya menyatakan seperti apa yang Anda inginkan dan membiarkan lingkungan pemrograman mengetahuinya.
sumber
POST /api/virtualmachines/42/shutdown
daripada memiliki "efek samping". API harus dapat dimengerti oleh pengguna, bagaimana saya tahu bahwa misalnyaDELETE /api/virtualmachines/42
akan mematikan VM? Efek samping bagi saya adalah bug, kita harus mendesain API kita agar bisa dimengerti dan deskriptif sendiri