Kompatibilitas

Halaman ini memberikan penjelasan yang lebih mendetail untuk daftar perubahan yang dapat menyebabkan gangguan dan tidak menyebabkan gangguan yang diberikan di bagian Pembuatan Versi.

Tidak selalu benar-benar jelas apa yang dianggap sebagai perubahan yang dapat menyebabkan gangguan (tidak kompatibel). Panduan di sini harus diperlakukan sebagai indikatif, bukan daftar lengkap dari setiap kemungkinan perubahan.

Aturan yang tercantum di sini hanya berkaitan dengan kompatibilitas klien. Produsen API diharapkan mengetahui persyaratan mereka sendiri sehubungan dengan deployment, termasuk perubahan detail implementasi.

Tujuan umumnya adalah klien tidak boleh dirusak oleh layanan yang diupdate ke versi minor atau patch baru. Jenis kerusakan yang sedang dipertimbangkan adalah:

  • Kompatibilitas sumber: kode yang ditulis terhadap versi 1.0 gagal dikompilasi dengan versi 1.1
  • Kompatibilitas biner: kode yang dikompilasi terhadap versi 1.0, gagal ditautkan/dijalankan terhadap library klien 1.1. (Detail persisnya bergantung pada platform klien; terdapat varian dalam situasi yang berbeda.)
  • Kompatibilitas kabel: aplikasi yang dibangun dengan versi 1.0 dan gagal berkomunikasi dengan server 1.1
  • Kompatibilitas semantik: semuanya berjalan, tetapi memberikan hasil yang tidak diinginkan atau mengejutkan

Dengan kata lain: klien lama harus dapat bekerja dengan server yang lebih baru dalam nomor versi utama yang sama, dan ketika klien ingin melakukan update ke versi minor yang baru (misalnya, untuk memanfaatkan fitur baru), klien tersebut harus dapat melakukannya dengan mudah.

Catatan: Saat merujuk pada nomor versi seperti v1.1 dan v1.0, kami merujuk pada nomor versi logis yang tidak pernah dibuat konkret. Hal ini sebenarnya dilakukan untuk memudahkan Anda menggambarkan perubahan.

Selain pertimbangan teoritis berbasis protokol, ada pertimbangan praktis karena adanya library klien yang melibatkan kode yang dihasilkan dan kode yang ditulis tangan. Jika memungkinkan, uji perubahan yang Anda pertimbangkan dengan membuat versi baru library klien dan memastikan pengujiannya tetap lulus.

Diskusi di bawah ini membagi pesan proto ke dalam tiga kategori:

  • Pesan permintaan (seperti GetBookRequest)
  • Pesan respons (seperti ListBooksResponse)
  • Pesan resource (seperti Book, dan termasuk pesan yang digunakan dalam pesan resource lainnya)

Kategori ini memiliki aturan yang berbeda. Hal ini karena pesan permintaan hanya dikirim dari klien ke server, pesan respons hanya dikirim dari server ke klien, tetapi biasanya pesan resource dikirim dengan kedua cara tersebut. Secara khusus, resource yang dapat diupdate harus dipertimbangkan dalam hal siklus baca/modifikasi/tulis.

Perubahan yang kompatibel dengan versi lama (tidak menyebabkan gangguan)

Menambahkan antarmuka API ke definisi layanan API

Dari perspektif protokol, ini selalu aman. Satu-satunya peringatan adalah bahwa library klien mungkin telah menggunakan nama antarmuka API baru Anda dalam kode yang ditulis tangan. Jika antarmuka baru Anda sepenuhnya ortogonal dengan antarmuka yang sudah ada, hal ini tidak mungkin; jika merupakan versi sederhana dari antarmuka yang sudah ada, kemungkinan besar akan menyebabkan konflik.

Menambahkan metode ke antarmuka API

Tidak masalah, kecuali jika Anda menambahkan metode yang bertentangan dengan metode yang sudah dibuat di library klien.

(Contoh jika error tersebut dapat terjadi: jika Anda memiliki metode GetFoo, generator kode C# akan membuat metode GetFoo dan GetFooAsync. Oleh karena itu, menambahkan metode GetFooAsync di antarmuka API Anda akan menjadi perubahan yang dapat menyebabkan gangguan dari perspektif library klien.)

Menambahkan binding HTTP ke metode

Dengan asumsi bahwa binding tidak menimbulkan ambiguitas, membuat server merespons URL yang sebelumnya telah ditolak adalah tindakan aman. Tindakan ini dapat dilakukan saat membuat operasi yang ada diterapkan ke pola nama resource baru.

Menambahkan kolom ke pesan permintaan

Penambahan kolom permintaan tidak dapat menyebabkan gangguan, asalkan klien yang tidak menentukan kolom akan diperlakukan sama di versi baru seperti di versi lama.

Contoh paling jelas tempat hal ini dapat dilakukan dengan tidak benar adalah dengan penomoran halaman: jika API v1.0 tidak menyertakan penomoran halaman untuk koleksi, koleksi tersebut tidak dapat ditambahkan dalam v1.1 kecuali page_size default diperlakukan sebagai tak terbatas (yang secara umum merupakan ide buruk). Jika tidak, klien v1.0 yang berharap mendapatkan hasil lengkap dari satu permintaan dapat menerima hasil yang terpotong, tanpa mengetahui bahwa koleksi tersebut berisi lebih banyak resource.

Menambahkan kolom ke pesan respons

Pesan respons yang bukan resource (misalnya, ListBooksResponse) dapat diperluas tanpa memutus klien, selama hal ini tidak mengubah perilaku kolom respons lainnya. Setiap kolom yang sebelumnya diisi dalam respons harus terus diisi dengan semantik yang sama, meskipun hal ini menyebabkan redundansi.

Misalnya, respons kueri dalam versi 1.0 mungkin memiliki kolom boolean contained_duplicates yang menunjukkan bahwa beberapa hasil dihilangkan karena adanya duplikasi. Pada versi 1.1, kami mungkin memberikan informasi yang lebih mendetail di kolom duplicate_count. Meskipun redundan dari perspektif 1.1, kolom contained_duplicates harus tetap diisi.

Menambahkan nilai ke enum

Enum yang hanya digunakan dalam pesan permintaan dapat diperluas secara bebas untuk menyertakan elemen baru. Misalnya, dengan menggunakan pola Resource View, tampilan baru dapat ditambahkan dalam versi minor baru. Klien tidak perlu menerima enum ini, sehingga mereka tidak harus mengetahui nilai yang tidak penting bagi mereka.

Untuk pesan resource dan pesan respons, asumsi defaultnya adalah klien harus menangani nilai enum yang tidak mereka ketahui. Namun, produsen API harus menyadari bahwa menulis aplikasi untuk menangani elemen enum baru dengan benar mungkin akan sulit. Pemilik API harus mendokumentasikan perilaku klien yang diharapkan saat menemukan nilai enum yang tidak diketahui.

Proto3 memungkinkan klien menerima nilai yang tidak mereka ketahui dan melakukan serial ulang pesan dengan mempertahankan nilai yang sama, sehingga tidak merusak siklus baca/ubah/tulis. Format JSON memungkinkan pengiriman nilai numerik, tetapi "name" untuk nilainya tidak diketahui. Namun, server biasanya tidak akan tahu apakah klien benar-benar tahu tentang nilai tertentu atau tidak. Oleh karena itu, klien JSON mungkin menyadari bahwa mereka telah menerima nilai yang sebelumnya tidak mereka ketahui, tetapi mereka hanya akan melihat nama atau angka - mereka tidak akan mengetahui keduanya. Menampilkan kembali nilai yang sama ke server dalam siklus baca/ubah/tulis tidak boleh mengubah kolom tersebut, karena server harus memahami kedua formulir.

Menambahkan kolom resource khusus output

Kolom dalam entity resource yang hanya disediakan oleh server dapat ditambahkan. Server mungkin memvalidasi bahwa setiap nilai yang disediakan klien dalam permintaan valid, tetapi tidak boleh gagal jika nilai tersebut dihilangkan.

Perubahan yang tidak kompatibel dengan versi lama (yang dapat menyebabkan gangguan)

Menghapus atau mengganti nama layanan, kolom, metode, atau nilai enum

Pada dasarnya, jika kode klien dapat merujuk ke sesuatu, menghapus atau mengganti namanya merupakan perubahan yang dapat menyebabkan gangguan dan harus menghasilkan peningkatan versi utama. Kode yang merujuk ke nama lama akan menyebabkan kegagalan pada waktu kompilasi untuk beberapa bahasa (seperti C# dan Java) dan dapat menyebabkan kegagalan waktu eksekusi atau kehilangan data dalam bahasa lain. Kompatibilitas format kabel tidak relevan di sini.

Mengubah binding HTTP

"Ubah" di sini secara efektif adalah "hapus dan tambahkan". Misalnya, jika memutuskan bahwa Anda benar-benar ingin mendukung PATCH, tetapi versi yang dipublikasikan mendukung PUT, atau Anda telah menggunakan nama kata kerja kustom yang salah, Anda dapat menambahkan binding baru, tetapi Anda tidak boleh menghapus binding lama karena semua alasan yang sama seperti menghapus metode layanan adalah perubahan yang dapat menyebabkan gangguan.

Mengubah jenis kolom

Meskipun jenis baru kompatibel dengan format berkabel, hal ini dapat mengubah kode yang dihasilkan untuk library klien sehingga harus menghasilkan peningkatan versi yang besar. Untuk bahasa yang dikompilasi dan diketik secara statis, hal ini dapat dengan mudah menyebabkan error waktu kompilasi.

Mengubah format nama resource

Resource tidak boleh mengubah namanya - yang berarti nama koleksi tidak dapat diubah.

Tidak seperti kebanyakan perubahan yang dapat menyebabkan gangguan, hal ini juga memengaruhi versi utama: jika klien akan menggunakan akses v2.0 ke resource yang dibuat di v1.0 atau sebaliknya, nama resource yang sama harus digunakan di kedua versi.

Lebih jelasnya, kumpulan nama resource yang valid tidak boleh berubah, karena alasan berikut:

  • Jika permintaan menjadi lebih ketat, permintaan yang sebelumnya berhasil kini akan gagal.
  • Jika batas tersebut tidak terlalu ketat dari yang didokumentasikan sebelumnya, klien yang membuat asumsi berdasarkan dokumentasi sebelumnya mungkin tidak akan berfungsi. Klien sangat mungkin menyimpan nama resource di tempat lain, dengan cara yang mungkin sensitif terhadap kumpulan karakter yang diizinkan dan panjang namanya. Atau, klien mungkin melakukan validasi nama resource mereka sendiri untuk mengikuti dokumentasinya. (Misalnya, Amazon memberikan banyak peringatan kepada pelanggan dan mengalami periode migrasi saat mereka mulai mengizinkan ID resource EC2 yang lebih panjang.)

Perhatikan bahwa perubahan tersebut mungkin hanya terlihat dalam dokumentasi proto. Oleh karena itu, saat meninjau CL untuk kerusakan, meninjau perubahan non-komentar tidaklah cukup.

Mengubah perilaku yang terlihat dari permintaan yang ada

Klien akan sering bergantung pada perilaku dan semantik API, bahkan saat perilaku tersebut tidak didukung atau didokumentasikan secara eksplisit. Oleh karena itu, dalam sebagian besar kasus, perubahan perilaku atau semantik data API akan dipandang sebagai gangguan oleh konsumen. Jika perilaku tidak disembunyikan secara kriptografis, Anda seharusnya berasumsi bahwa pengguna telah menemukannya dan akan bergantung padanya.

Sebaiknya enkripsi token penomoran halaman karena alasan ini (meskipun data tidak menarik) untuk mencegah pengguna membuat token mereka sendiri dan berpotensi rusak saat perilaku token berubah.

Mengubah format URL dalam definisi HTTP

Ada dua jenis perubahan yang perlu dipertimbangkan di sini, selain perubahan nama resource yang tercantum di atas:

  • Nama metode kustom: Meskipun bukan bagian dari nama resource, nama metode kustom adalah bagian dari URL yang diposting oleh klien REST. Mengubah nama metode kustom tidak boleh merusak klien gRPC, tetapi API publik harus mengasumsikan bahwa klien tersebut memiliki klien REST.
  • Nama parameter resource: Perubahan dari v1/shelves/{shelf}/books/{book} menjadi v1/shelves/{shelf_id}/books/{book_id} tidak memengaruhi nama resource pengganti, tetapi dapat memengaruhi pembuatan kode.

Menambahkan kolom baca/tulis ke pesan resource

Klien akan sering melakukan operasi baca/ubah/tulis. Sebagian besar klien tidak akan memberikan nilai untuk kolom yang tidak mereka ketahui, dan proto3 secara khusus tidak mendukung hal ini. Anda dapat menentukan bahwa kolom jenis pesan yang tidak ada (bukan jenis primitif) berarti update tidak diterapkan pada kolom tersebut, tetapi hal ini akan mempersulit penghapusan nilai kolom tersebut secara eksplisit dari entity. Jenis primitif (termasuk string dan bytes) tidak dapat ditangani dengan cara ini, karena tidak ada perbedaan di proto3 antara secara eksplisit menentukan kolom int32 sebagai 0 dan tidak menentukannya sama sekali.

Jika semua pembaruan dilakukan menggunakan mask kolom, hal ini tidak menjadi masalah karena klien tidak akan secara implisit menimpa kolom yang tidak diketahuinya. Namun, ini akan menjadi keputusan API yang tidak biasa: sebagian besar API memungkinkan update "seluruh resource".