Konsekuensi dari tidak melakukan REST API dengan cara yang "benar"?

8

Saya akan mengajukan pertanyaan ini dengan cara ini - apa masalah rekayasa perangkat lunak untuk tidak mengimplementasikan REST API saya dengan cara yang "benar"?

Apa maksud Anda dengan cara yang "benar"? Baiklah, izinkan saya untuk menjelaskan persepsi saya tentang cara yang benar, maka saya akan memberitahu Anda bagaimana saya melakukannya (juga, anggap saya berbicara tentang API SISA JSON).

Jalan yang benar

  1. Kewarganegaraan. Ini adalah bagian yang saya dapatkan. Klien mempertahankan negara selalu 100% waktu selamanya. Itu bukan pekerjaan server, itu adalah klien.

  2. Tindakan dan respons yang diharapkan untuk setiap kata kerja:

    • DAPATKAN - Mendapat sumber daya yang ditentukan secara penuh penuh, hanya dibatasi oleh otorisasi dalam permintaan atau parameter kueri. Ini tidak menjamin modifikasi sumber daya apa pun dalam proses.
    • POST - Diberikan seluruh deskripsi sumber daya (seperti objek JSON), membuat sumber daya, lalu mengembalikan sumber daya itu, dengan properti sisi server apa pun juga dibuat, seperti tanggal atau ID.
    • HAPUS - Menghapus sumber daya yang ditentukan, hanya memberikan semacam 200 OK sebagai tanggapan
    • PUT - Diberikan seluruh deklarasi objek sebagai input, memperbarui sumber daya di lokasi tertentu, memperbarui semua bidang sumber daya untuk setiap bidang yang diberikan dalam input. Agar jelas, ini mengharapkan seluruh objek untuk diteruskan sebagai input. Seluruh sumber daya yang diperbarui dikembalikan, dengan semua bidang (sesuai dengan otorisasi atau tanda input lainnya).
    • PATCH - Hanya diberikan bidang yang ingin dimodifikasi untuk sumber daya, memperbarui hanya bidang dalam sumber daya tertentu yang diberikan sebagai input. (Di sinilah saya tidak jelas): Seluruh sumber daya dikembalikan? (Atau hanya bidang yang diperbarui? Entahlah. Tidak peduli.)
  3. Jalur sumber daya. Mengingat hubungan sumber daya satu sama lain, jalur sumber daya mungkin terlihat seperti salah satu dari:
    • / parentresource /: id
    • / parentresource /: id / childresource
    • / parentresource /: id / childresource /: childId
    • / parentresource /: id / childresource /: childId / subresource /: subresourceId (Dalam contoh ini, sub-sumber daya adalah milik sumber daya anak, yang termasuk dalam sumber daya induk).

Cara saya ingin melakukannya

Di atas adalah pemahaman saya tentang bagaimana seharusnya REST API berfungsi. Sekarang izinkan saya mendaftar beberapa variasi saya di atas:

  1. PUT / PATCH - Apa gunanya melewati seluruh sumber daya untuk modifikasi? Saya hanya menggunakan PUT untuk memodifikasi sumber daya, dan saya hanya meneruskan bidang yang ingin saya perbarui. Akibatnya, saya tidak perlu menggunakan PATCH
  2. Resource Paths - Saya menggunakan GUID dalam aplikasi saya. Akibatnya, mereka akan menjadi unik secara global. Mengapa saya memerlukan jalur sumber daya penuh, termasuk sumber daya induk, jika saya bisa merujuk sumber daya secara unik saja? Seperti:
     
    / subresource /: subresourceId
     
    Jika saya harus melakukannya dengan "benar", mencoba untuk referensi subresource akan memerlukan path lengkap seperti:
     
    / parentresource /: id / childresource /: childId / subresource /: subresourceId
     
    Apakah semua yang diperlukan ? Karena sekarang saya harus memiliki penanganan kesalahan tambahan jika jalur saya berisi: subresourceId yang sebenarnya tidak dimiliki oleh yang diberikan: childId, dan ditto untuk: childId tidak dimiliki oleh induk: id. Sisi server saya mengurus otorisasi sumber daya. Tidak bisakah saya hanya merujuk sumber daya itu sendiri, daripada path lengkap?

  3. Respon balik. Katakanlah, misalnya, bahwa struktur data saya adalah hierarki pohon, tanpa batas praktis pada kedalaman pohon. Sumber daya terletak pada tingkat yang berbeda di bawah pohon, secara hierarkis.

    • GET jelas. Jika saya mendapatkan seluruh pohon ini, saya mengharapkan seluruh pohon sebagai tanggapan, dengan sumber daya yang terkandung dalam sumber daya.
    • Jika saya POST untuk membuat sumber daya baru, PUT untuk memperbarui, atau HAPUS untuk menghapus, saya ingin melihat delta di pohon, daripada hanya melihat sumber daya yang saya buat / perbarui / hapus. Saya tidak ingin harus lagi memanggil GET dari pohon induk setelah setiap POST, PUT, atau DELETE, terutama jika ada sedikit perubahan pada pohon dan saya hanya ingin melihat delta.

Semoga pertanyaan saya jelas.

Jika Anda melihat implementasi REST seperti yang saya jelaskan, akankah Anda melihatnya dan memberi tahu saya tentang masalah rekayasa perangkat lunak Anda? Jika demikian, apa jadinya mereka?

Michael Plautz
sumber
4
Anehnya, tidak ada masalah Anda yang melibatkan kendala arsitektur REST. Pertanyaan Anda terikat dengan semantik WEB dan HTTP. Sepertinya Anda tidak nyaman dengan yang terakhir ini, apa yang membuat saya berpikir, Mengapa membuat antarmuka web sama sekali? Di sisi lain, tidak ada yang namanya "jalan yang benar" atau "jalan yang salah". Hanya implementasi yang sesuai dengan kebutuhan Anda. Apa yang Anda sebut "benar" itu hanya lebih "ramah web" dan "ramah pengembang". Semakin "ramah web", semakin banyak manfaat yang didapat dari arsitektur WWW. Itu akan menjadi titik melakukan "hal" web.
Laiv
Risiko menyimpang dari REST adalah seseorang yang mengharapkan antarmuka RESTful akan bingung dengan perilaku aplikasi web Anda. Namun, apa yang Anda sarankan tampaknya tidak menyimpang terlalu banyak sehingga menyebabkan kebingungan total, jadi saya berpendapat bahwa apa yang Anda sarankan baik-baik saja. Cukup tambahkan dokumentasi!
Neil
@ Longv, Anda mengajukan pertanyaan yang bagus - mengapa membuat antarmuka web? Karena saya tidak terbiasa dengan arsitektur lain yang mendukung kerangka kerja sisi klien seperti React atau Vue, daripada memiliki antarmuka web yang mengirimkan data yang saya butuhkan. Agar lebih jelas, saya tidak ingin rendering sisi server, karena alasan fleksibilitas dan kinerja. Saya juga tahu bahwa GraphQL adalah sebuah opsi, tetapi saya sangat tidak terbiasa dengannya.
Michael Plautz
GraphQL bukan gaya arsitektur hanyalah satu lagi bahasa query dengan banyak kode boiler-plate di bawah kap. Anda dapat mengambil keuntungan dari WWW tanpa REST. Belum ada WebSockets atau ProtocolBuffers. jika aplikasi Anda tidak sepenuhnya mewakili transfer stat, maka REST tidak melayani Anda.
Laiv

Jawaban:

3

Jawaban umum yang mendasari di sini adalah bahwa ide-ide Anda dapat bekerja pada tingkat teknis, tetapi itu tidak berarti mereka sesuai dengan konvensi standar REST.


  1. PUT / PATCH - Apa gunanya melewati seluruh sumber daya untuk modifikasi? Saya hanya menggunakan PUT untuk memodifikasi sumber daya, dan saya hanya meneruskan bidang yang ingin saya perbarui. Akibatnya, saya tidak perlu menggunakan PATCH

Ide Anda bekerja pada level teknis, tetapi itu bukan bagaimana REST telah dijelaskan. Perlu diingat bahwa setiap diskusi tentang kode kerja (yaitu tidak ada kesalahan kompilasi atau runtime) selalu akan menjadi masalah konvensi , belum tentu keunggulan teknis yang jelas.


  1. Resource Paths - Saya menggunakan GUID dalam aplikasi saya. Akibatnya, mereka akan menjadi unik secara global. Mengapa saya memerlukan jalur sumber daya penuh, termasuk sumber daya induk, jika saya bisa merujuk ke sumber daya secara unik saja?

Ada banyak nuansa bagaimana kita mendefinisikan entitas "anak / orang tua". Paling umum, ini merujuk untuk hubungan satu-ke-banyak (orangtua-ke-anak).

Namun saya curiga bahwa untuk REST, bagian dari apa yang menjadikan seorang anak anak adalah bahwa ada harapan hanya bisa mengaksesnya melalui orang tua, bahwa mereka tidak membawa pengenal mereka yang unik secara global (dan dikenal secara eksternal).
Saya menduga ini mengikuti filosofi yang sama (tetapi tidak harus karena alasan yang sama) dengan agregat (dan akarnya) dalam Pengembangan Domain Driven .

Agregat DDD adalah sekelompok objek domain yang dapat diperlakukan sebagai satu unit. Agregat akan memiliki salah satu objek komponennya menjadi akar agregat. Referensi apa pun dari luar agregat hanya boleh pergi ke akar agregat .

Dalam kasus Anda, apa yang Anda sebut "induk" berfungsi sebagai akar agregat. Satu titik kontak (jika Anda mau) untuk penelepon luar.

Anda mungkin ingin menyimpulkan dari sini bahwa anak Anda sebenarnya agregat yang berbeda. Mungkin itu masalahnya, tapi saya ingin mengeluarkan peringatan dengan keputusan itu. Anda tidak harus mendasarkan arsitektur Anda pada jenis bidang tertentu. Anda tidak memiliki cara untuk mengetahui apakah Anda akan selalu tetap menggunakan ID unik global untuk semua entitas Anda. Jika itu pernah berubah, untuk alasan apa pun, Anda akan membahayakan kelayakan arsitektur REST Anda; karena Anda mungkin berakhir dalam situasi di mana anak tidak lagi dapat diidentifikasi secara unik dan karenanya perlu dirujuk melalui orang tuanya.


  1. Jika saya POST untuk membuat sumber daya baru, PUT untuk memperbarui, atau HAPUS untuk menghapus, saya ingin melihat delta di pohon, daripada hanya melihat sumber daya yang saya buat / perbarui / hapus.

Anda melanggar urutan operasi desain. API REST secara khusus dimaksudkan sebagai agnostik konsumen. API tidak boleh dibangun sesuai dengan spesifikasi salah satu konsumennya.

Ketika Anda mengatakan "Saya ingin melihat delta di pohon", apa yang sebenarnya Anda katakan adalah "aplikasi pemakai hanya perlu melihat delta di pohon". Tapi itu tidak terlalu penting bagi api REST. Ini hanya menyediakan pendekatan standar.

Ini adalah sifat dari pendekatan standar untuk sering kali tidak memiliki alat yang sangat dapat dikustomisasi , dan sebagai gantinya mendukung alat yang paling umum digunakan .


Bisakah Anda menyimpang dari jalan? Ya, itu akan bekerja pada level teknis. Tapi itu tidak akan menjadi SISA murni lagi. Ini adalah sesuatu yang sangat kontekstual dan Anda perlu mempertimbangkan pilihan.

  • Jika Anda membuat API yang diharapkan dapat melayani banyak konsumen yang beragam, maka saya sarankan tetap berpegang pada REST sebaik mungkin.
  • Jika Anda sedang membangun API yang hanya akan memiliki satu konsumen yang juga dikembangkan oleh Anda; maka tidak ada kebutuhan nyata untuk tetap pada REST murni.
  • Menyimpang dari jalur berarti Anda harus mendokumentasikan bagaimana Anda menyimpang sehingga pengembang lain masih bisa memahaminya. Jika Anda tetap pada REST murni, Anda tidak harus menulis dokumentasi dan pengembang lain tidak perlu menghabiskan waktu dan upaya untuk mencari tahu pendekatan yang Anda sesuaikan.
Flater
sumber
9

apa masalah rekayasa perangkat lunak untuk tidak mengimplementasikan REST API saya dengan cara yang "benar"?

Yang utama, menurut saya, adalah kemampuan untuk mendelegasikan pekerjaan ke komponen generik yang hanya mengetahui standar, bukan kasus bisnis spesifik Anda.

Jika Anda mengikuti antarmuka yang seragam, maka lebih mudah bagi pihak lain untuk membangun komponen yang terintegrasi dengan baik dengan Anda.

Ini tulisan Fielding pada 2008

REST ditujukan untuk aplikasi berbasis jaringan berumur panjang yang menjangkau banyak organisasi.

Salah satu cara kami mengelola "berumur panjang" adalah dengan memiliki standar yang jelas menggambarkan semantik pesan yang kami sampaikan. Jika semua orang setuju apa PUTartinya, maka konsumen dan produsen permintaan tersebut dapat dikembangkan secara independen, dan komponen perantara di antara keduanya dapat mengambil tindakan yang masuk akal tanpa perlu mengetahui detail pesan dalam konteks spesifik Anda.

PUT / PATCH - Apa gunanya melewati seluruh sumber daya untuk modifikasi? Saya hanya menggunakan PUT untuk memodifikasi sumber daya, dan saya hanya meneruskan bidang yang ingin saya perbarui. Akibatnya, saya tidak perlu menggunakan PATCH

Apa gunanya menggunakan PUTitu?

PURPLE /014d8c83-604d-4cf0-a6ba-e1f7ef8c4898 HTTP/1.1
...

Itu adalah baris permintaan yang valid untuk pesan HTTP, dan perubahan dalam semantik tidak akan membingungkan siapa pun.

Setara

POST /014d8c83-604d-4cf0-a6ba-e1f7ef8c4898 HTTP/1.1
...

Yang cukup banyak memiliki semantik yang tidak dibatasi; server dapat mengimplementasikan penanganan permintaan itu dengan cara apa pun yang diinginkan.

anggap saya berbicara tentang API SISA JSON

Keengganan Anda untuk menggunakan PATCH sangat aneh dalam kasus ini, karena sudah ada standar yang diusulkan untuk JSON Patch dan JSON Merge Patch - pekerjaan standardisasi format dokumen patch mungkin sudah dilakukan untuk Anda.

Alternatif lain yang valid adalah memperlakukan dokumen tambalan sebagai sumber daya terpisah. Semantik, Anda mungkin membayangkan sesuatu seperti

PUT /014d8c83-604d-4cf0-a6ba-e1f7ef8c4898/patches/5c42c414-03c0-4ac5-af14-2b1165ac98b3 HTTP/1.1

Itu membuat Anda jujur, seragam, semantik pesan, mengorbankan invalidasi cache standar .

Dalam pengaturan tinjauan kode, saya akan menolak perubahan yang diajukan yang mencoba mendefinisikan ulang semantik PUT.

HTTP tidak berusaha meminta agar hasil GET aman. Apa yang dilakukannya adalah mengharuskan semantik operasi aman, dan oleh karena itu kesalahan implementasi, bukan antarmuka atau pengguna antarmuka itu, jika sesuatu terjadi sebagai akibat yang menyebabkan hilangnya properti (uang, BTW, dianggap milik demi definisi ini). - Fielding, 2002 .

Pertimbangan yang sama berlaku PUTjuga; jika implementasi PUT Anda menyimpang dari semantik standar, maka implementasi Anda bertanggung jawab atas kerusakan yang terjadi.

Resource Paths - Saya menggunakan GUID dalam aplikasi saya. Akibatnya, mereka akan menjadi unik secara global. Mengapa saya memerlukan jalur sumber daya penuh, termasuk sumber daya induk, jika saya bisa merujuk ke sumber daya secara unik saja?

Tidak apa-apa. REST tidak peduli ejaan apa yang Anda gunakan untuk pengidentifikasi sumber daya Anda.

Pertimbangkan halaman arahan google. Apakah Anda perlu memperhatikan ejaan URI untuk coretan hari ini? atau di mana formulir pencarian dikirim? Tidak, tentu saja tidak. Payload HTML menyertakan URI di dalamnya, dan klien hanya menggunakan pengidentifikasi yang disediakan, dengan cara standar, tanpa perlu menganalisis pengidentifikasi tersebut.

Informasi yang dikodekan ke dalam URI adalah kebijaksanaan server asal, untuk keperluannya sendiri.

Saya tidak ingin menggunakan URI sebagai titik masuk API Anda. https://www.example.org/df8f5f87-15ff-4212-8fb8-4fbca2c7efcfsedikit canggung untuk konsumsi manusia. URI yang dapat dibaca manusia yang mengalihkan ke sumber daya UUID akan baik-baik saja, URI yang dapat dibaca manusia yang mengembalikan konten sumber daya UUID akan lebih baik.

Jika saya POST untuk membuat sumber daya baru, PUT untuk memperbarui, atau HAPUS untuk menghapus, saya ingin melihat delta di pohon, daripada hanya melihat sumber daya yang saya buat / perbarui / hapus

Tidak apa-apa - sekali lagi, lihat standarnya .

Muatan yang dikirim dalam respons 200 tergantung pada metode permintaan. Untuk metode yang ditentukan oleh spesifikasi ini, makna muatan yang dimaksudkan dapat diringkas sebagai

POST representasi status, atau hasil yang diperoleh dari, tindakan

TETAPKAN, HAPUS representasi status tindakan

Dalam beberapa kasus, masuk akal untuk mengirim representasi baru dari sumber daya sebagai bagian dari respons (untuk menghindarkan klien dari latensi permintaan / respons GET).

VoiceOfUnreason
sumber
2
What's the point in using PUT then?-- Memang. POST akan bekerja dengan baik.
Robert Harvey
@RobertHarvey Atau mengapa tidak digunakan PATCH? Definisi ini lebih cocok.
Solomon Ucko
@SolomonUcko: Membuat segala sesuatu POST memiliki sifat kesederhanaan.
Robert Harvey
3

REST adalah gaya arsitektur untuk memanipulasi sumber daya dalam keadaan tanpa kewarganegaraan (di mana kewarganegaraan berarti bahwa setiap manipulasi berdiri sendiri dan tidak bergantung pada manipulasi lain yang mungkin telah terjadi).

Penggunaan kata kerja PUT / PATCH / POST / GET / DELETE berasal dari penggunaan umum protokol HTTP yang digunakan untuk mentransfer dan memanipulasi sumber daya. Arti kata kerja tersebut didefinisikan oleh standar internet ( RFC7231 ).

Mengingat latar belakang itu, penggunaan PUT Anda tidak standar dan dapat membingungkan pengembang lain yang ingin menggunakan API Anda.

Mengenai jalur sumber daya, hampir tidak ada yang peduli tentang ejaan mereka yang tepat (termasuk jika sumber daya anak terdaftar sebagai anak). Yang dipedulikan orang adalah bahwa setiap sumber daya diidentifikasi secara unik. Sistem /parent/:pid/child/:cidini sering digunakan ketika id anak hanya unik dalam satu orangtua untuk tetap memiliki jalur unik global untuk sumber daya.

Bart van Ingen Schenau
sumber
2
Selain jawaban Bart. Ingat saja bahwa satu-satunya yang harus membaca dan memahami URI adalah Klien HTTP, dan tidak peduli tentang hierarki sumber daya. Jadi apakah URI menyatakan hierarki, hubungan atau jenis hubungan lainnya hanya bermakna bagi makhluk hidup miskin yang perlu membacanya
Laiv
1
  1. PUT / PATCH - Apa gunanya melewati seluruh sumber daya untuk modifikasi? Saya hanya menggunakan PUT untuk memodifikasi sumber daya, dan saya hanya meneruskan bidang yang ingin saya perbarui. Akibatnya, saya tidak perlu menggunakan PATCH

Menurut saya Anda benar-benar harus menggunakan PATCH sebagai semantik di sini.

  • PUT menjelaskan kondisi yang tepat yang diinginkan. Ini berguna ketika sumber daya mungkin sering berubah, dan perubahan yang diinginkan perlu terjadi dalam konteks tertentu.

  • PATCH menjelaskan delta yang diinginkan untuk apa pun yang ada di sana. Ini berguna ketika perubahan tidak mempedulikan konteksnya, atau konteks yang relevan jauh lebih kecil dari keseluruhan sumber daya.

Sebuah gambar adalah contoh yang baik jika masuk akal untuk mengunggah semuanya. Penting bahwa seluruh sumber daya dikomunikasikan untuk memastikan konteks yang relevan.

Sebaliknya, memperbarui jumlah pemutaran pada daftar putar musik mungkin lebih baik menjadi delta. Bukan karena ini adalah perubahan kecil, tetapi karena mengirimkan kembali seluruh daftar dapat dengan mudah membatalkan perubahan pada isi daftar.

  1. Resource Paths - Saya menggunakan GUID dalam aplikasi saya. Akibatnya, mereka akan menjadi unik secara global. Mengapa saya memerlukan jalur sumber daya penuh, termasuk sumber daya induk, jika saya bisa merujuk ke sumber daya secara unik saja?

...menggunting...

Apakah semua itu perlu? Karena sekarang saya harus memiliki penanganan kesalahan tambahan jika jalur saya berisi: subresourceId yang sebenarnya tidak dimiliki oleh yang diberikan: childId, dan ditto untuk: childId tidak dimiliki oleh orang tua: id. Sisi server saya mengurus otorisasi sumber daya. Tidak bisakah saya hanya merujuk sumber daya itu sendiri, daripada path lengkap?

Tidak, Anda benar-benar tidak perlu menggunakan jalur - sebelumnya. Katakanlah apakah Anda menyimpan semua file Anda di desktop? Tidak? Kenapa tidak?

Mungkin ada hubungannya dengan membuatnya lebih mudah dilihat, masalah yang sama di sini. GUID tidak memberi tahu Anda apa yang Anda tangani saat Anda mengatur ini, men-debug-nya, atau menjalankannya.

Jadi bagaimana rasanya mendukung sistem ini? atau berinteraksi dengannya? Jika Anda belum memikirkannya, perlu waktu dan pertimbangkan pekerjaan yang Anda lakukan.

Memiliki informasi jalur yang jelas berfungsi untuk membantu memvalidasi permintaan. Ini juga membantu untuk membedakan informasi yang cukup yang mendukung dan pengembang sistem hilir dapat mendekati url ini dan menggunakannya.

  1. Respon balik. Katakanlah, misalnya, bahwa struktur data saya adalah hierarki pohon, tanpa batas praktis pada kedalaman pohon. Sumber daya terletak pada tingkat yang berbeda di bawah pohon, secara hierarkis.

    Sebuah. GET jelas. Jika saya mendapatkan seluruh pohon ini, saya mengharapkan seluruh pohon sebagai tanggapan, dengan sumber daya yang terkandung dalam sumber daya.

Anda mungkin ingin menerapkan batas kedalaman, hanya agar beberapa anak pintar tidak hanya mendapatkan root dari situs Anda untuk setiap operasi yang dapat mereka pikirkan.

b. Jika saya POST untuk membuat sumber daya baru, PUT untuk memperbarui, atau HAPUS untuk menghapus, saya ingin melihat delta di pohon, daripada hanya melihat sumber daya yang saya buat / perbarui / hapus. Saya tidak ingin harus lagi memanggil GET dari pohon induk setelah setiap POST, PUT, atau DELETE, terutama jika ada sedikit perubahan pada pohon dan saya hanya ingin melihat delta.

Jika memperbarui sumber daya memengaruhi induknya dengan cara yang tidak sepele dan dapat diprediksi, Anda memiliki masalah lain ... Anda benar-benar perlu melihat model negara bagian dan mencari tahu mengapa informasi tersebut melompat-lompat.

Jika Anda hanya ingin mengembalikan daftar delta terperinci, mengapa tidak? Mengapa tidak mendukung beberapa tampilan keluaran yang diubah oleh berbagai parameter? Jenkins mengembalikan respons API dalam pilihan xml, atau json dan memungkinkan Anda menentukan beberapa filter untuk mengekstraksi sub-pohon yang diinginkan.

Gunakan Sendiri

Terus terang, mundurlah dari apa yang Anda buat dan coba untuk mendukungnya, atau buat aplikasi lain untuk menggunakannya (bukan salah satu aplikasi yang sudah ada sebelumnya). Lakukan sesuatu yang serupa untuk API pihak ketiga sehingga Anda memiliki sedikit konteks latar belakang.

Kapan pun Anda merasa harus melakukan sesuatu yang tidak secara langsung menyelesaikan permintaan dukungan, atau secara langsung diperlukan untuk aplikasi klien maka API kurang dari ideal, dan Anda tahu mengapa itu kurang dari ideal yang bahkan lebih baik, karena Anda dapat memperbaikinya atau tidak melakukan kesalahan yang sama.

Misalnya, jika permintaan ke url yang diberikan selalu gagal, berapa banyak usaha yang harus Anda investasikan untuk menentukan apa yang gagal dan mengapa? Langkah apa yang Anda ambil, bisakah Anda menghindari salah satu dari langkah-langkah itu dengan memiliki URI yang lebih baik, atau penebangan yang lebih baik, atau pemantauan yang lebih baik, atau lain-lain ...?

Demikian pula, jika Anda menulis klien baru, berapa kali Anda perlu merujuk ke dokumentasi, atau ke kode sumber API? Apa yang bisa Anda lakukan untuk mengurangi kebutuhan itu? Apa yang bisa Anda lakukan untuk berhenti melanggar harapan Anda sendiri? Apa yang bisa Anda lakukan yang menyederhanakan masalah aplikasi klien tanpa membuat server menjadi mimpi buruk untuk dipertahankan?

Cara yang benar

Terus terang jalan yang benar tidak langsung. REST adalah seperangkat praktik yang ditunjukkan untuk bekerja di sejumlah keadaan untuk sejumlah masalah. Jika masalah Anda tidak cocok, jangan membuatnya cocok, tetapi kemudian juga jangan mengklaim menggunakan praktik-praktik itu.

Kain0_0
sumber
-1

Sebagian besar fitur REST apis ada karena suatu alasan, tetapi itu mungkin bukan alasan yang relevan bagi Anda. Memberi seluruh sumber daya, seperti dalam PUT, misalnya relevan jika Anda memerlukan idempotensi, jika tidak, maka tidak diperlukan. (Meskipun saya pikir akan lebih baik bagi pengguna / kolega / apa pun untuk mengiklankan fakta bahwa titik akhir Anda tidak idempoten dengan menggunakan POST atau PATCH sebagai gantinya.)

Untuk jalan hal yang saya tidak pernah mendengar yang terkait dengan istirahat. /root/345dd4dc-e175-455f-b545-85b1b1ce3e82adalah bagian dari pohon sebanyak /foo/bar/baz. Mungkin sedikit kurang ramah pengguna tetapi tidak kurang tenang sejauh yang saya bisa lihat.

Jika Anda ingin alasan yang lebih terperinci tentang mengapa REST dirancang sebagaimana adanya, saya pikir Anda harus membaca disertasi aslinya: https://www.ics.uci.edu/~fielding/pubs/dissertation/fielding_dissertation.pdf

Membaca bahwa Anda mungkin menemukan bahwa itu sangat berbeda dari bagaimana REST direpresentasikan dalam percakapan atau digunakan dalam API hari ini. Jelas banyak orang telah menemukan alasan, baik atau buruk, untuk menyimpang darinya.

Saya sangat suka kutipan ini yang mungkin Anda temukan relevan:

HTTP tidak dirancang untuk menjadi protokol transport. Ini adalah protokol transfer di mana pesan mencerminkan semantik arsitektur Web dengan melakukan tindakan pada sumber daya melalui transfer dan manipulasi representasi dari sumber daya tersebut. Dimungkinkan untuk mencapai berbagai fungsionalitas menggunakan antarmuka yang sangat sederhana ini, tetapi mengikuti antarmuka diperlukan agar semantik HTTP tetap terlihat oleh perantara. Itulah sebabnya HTTP melewati firewall. Sebagian besar ekstensi yang baru-baru ini diajukan ke HTTP, selain dari WebDAV [60], hanya menggunakan HTTP sebagai cara untuk memindahkan protokol aplikasi lain melalui firewall, yang merupakan ide yang secara fundamental salah arah. Tidak hanya itu mengalahkan tujuan memiliki firewall, tetapi itu tidak akan berfungsi untuk jangka panjang karena vendor firewall hanya perlu melakukan penyaringan protokol tambahan. Karenanya tidak masuk akal untuk melakukan ekstensi tersebut di atas HTTP, karena satu-satunya hal yang dicapai HTTP dalam situasi itu adalah menambahkan overhead dari sintaks yang lama. Aplikasi HTTP yang sebenarnya memetakan tindakan pengguna protokol terhadap sesuatu yang dapat diekspresikan menggunakan semantik HTTP, sehingga menciptakan API berbasis jaringan untuk layanan yang dapat dipahami oleh agen dan perantara tanpa sepengetahuan aplikasi tersebut.

monocell
sumber
2
"Meskipun saya pikir akan lebih baik bagi pengguna / kolega / apa pun untuk mengiklankan fakta bahwa titik akhir Anda tidak idempoten dengan menggunakan POST atau PATCH sebagai gantinya." - Ini bukan masalah kebaikan. Metode HTTP telah secara tepat mendefinisikan semantik, dan seluruh infrastruktur web di seluruh dunia bergantung pada semantik tersebut. Misalnya, proxy dapat mencoba ulang PUTpermintaan beberapa kali tanpa Anda sadari, dan mereka diizinkan untuk melakukan itu karena spec HTTP mengatakan bahwa PUTidempoten . Jika Anda PUTtidak idempoten, maka ini akan merusak layanan Anda .
Jörg W Mittag
2
Untuk sementara waktu, "akselerator web" sangat populer, dan pada kenyataannya, mereka membuat comeback untuk perangkat mobile. Akselerator itu melakukan pre-fetching dan men-cache sumber daya, dan mereka diizinkan untuk melakukan itu, karena spec HTTP menjamin hal itu GETdan HEADmurni serta bebas efek samping. Beberapa orang kehilangan data, karena mereka menggunakan aplikasi web yang dirancang dengan buruk, di mana penghapusan konten dilakukan dengan GETpermintaan, dan akselerator web dengan senang hati mengirim GETpermintaan ke semua URI yang dapat ditemukannya.
Jörg W Mittag
Anda tentu saja benar. Saya tidak bisa lagi bersemangat tentang web yang berfungsi dengan baik lagi. Rasanya seperti pertempuran yang hilang bagi saya, tetapi mungkin Anda berada di lingkungan yang lebih baik di mana hal-hal seperti ini benar-benar berfungsi. Di mana saya http hanyalah transportasi dengan tambahan bahwa itu dapat di-debug dari browser, bukan netcat, dan itu saja.
monocell