Misalkan Anda memiliki proyek besar yang didukung oleh basis API. Proyek ini juga mengirimkan API publik yang dapat digunakan pengguna (ish).
Terkadang Anda perlu membuat perubahan pada basis API yang mendukung proyek Anda. Misalnya, Anda perlu menambahkan fitur yang memerlukan perubahan API, metode baru, atau membutuhkan perubahan salah satu objek, atau format salah satu objek tersebut, diteruskan ke atau dari API.
Dengan asumsi bahwa Anda juga menggunakan objek-objek ini di API publik Anda, objek-objek publik juga akan berubah setiap kali Anda melakukan ini, yang tidak diinginkan karena klien Anda dapat mengandalkan objek API yang tetap identik agar kode parsingnya berfungsi. (klien C + + WSDL batuk ...)
Jadi salah satu solusi potensial adalah dengan versi API. Tetapi ketika kita mengatakan "versi" API, sepertinya ini juga harus berarti versi objek API serta memberikan panggilan metode duplikat untuk setiap tanda tangan metode yang diubah. Jadi saya kemudian akan memiliki objek CLR tua polos untuk setiap versi api saya, yang lagi-lagi tampaknya tidak diinginkan. Dan bahkan jika saya melakukan ini, saya pasti tidak akan membangun setiap objek dari awal karena akan berakhir dengan sejumlah besar kode duplikat. Alih-alih, API kemungkinan akan memperpanjang objek pribadi yang kami gunakan untuk API dasar kami, tetapi kemudian kami mengalami masalah yang sama karena properti yang ditambahkan juga akan tersedia di API publik ketika seharusnya tidak demikian.
Jadi, apakah kewarasan yang biasanya diterapkan pada situasi ini? Saya tahu banyak layanan publik seperti Git untuk Windows mengelola API versi, tetapi saya mengalami kesulitan membayangkan arsitektur yang mendukung ini tanpa banyak kode duplikat yang mencakup berbagai metode versi dan objek input / output.
Saya menyadari bahwa proses seperti upaya versi semantik untuk menempatkan kewarasan ketika API publik rusak harus terjadi. Masalahnya lebih karena sepertinya banyak atau sebagian besar perubahan memerlukan pemutusan API publik jika objek tidak lebih terpisah, tapi saya tidak melihat cara yang baik untuk melakukannya tanpa kode duplikat.
sumber
I don't see a good way to do that without duplicating code
- API baru Anda selalu dapat memanggil metode di API lama Anda, atau sebaliknya.Jawaban:
Saat mempertahankan API yang digunakan oleh pihak ketiga, tidak dapat dihindari bahwa Anda perlu melakukan perubahan. Tingkat kerumitan akan tergantung pada jenis perubahan yang terjadi. Ini adalah skenario utama yang muncul:
Fungsi Baru Menambahkan Ke API Yang Ada
Ini adalah skenario paling mudah untuk didukung. Menambahkan metode baru ke API seharusnya tidak memerlukan perubahan apa pun pada klien yang ada. Ini aman untuk digunakan untuk klien yang membutuhkan fungsionalitas baru karena tidak ada pembaruan untuk klien yang ada.
Fungsi Lama Dihentikan Dari API
Dalam skenario ini, Anda harus berkomunikasi dengan konsumen API Anda yang sudah ada bahwa fungsinya tidak akan didukung dalam jangka panjang. Sampai Anda menjatuhkan dukungan untuk fungsionalitas lama (atau sampai semua klien meningkatkan ke fungsionalitas baru), Anda harus menjaga fungsionalitas API lama dan baru pada saat yang sama. Jika perpustakaan yang disediakan sebagian besar bahasa memiliki cara untuk menandai metode lama sebagai usang / usang. Jika ini adalah layanan pihak ketiga dari jenis tertentu, biasanya yang terbaik adalah memiliki titik akhir yang berbeda untuk fungsi lama / baru.
Fungsi Yang Ada Dalam Mengubah API Dalam Beberapa Cara
Skenario ini akan tergantung pada jenis perubahan. Jika parameter input tidak lagi perlu digunakan maka Anda dapat memperbarui layanan / pustaka untuk mengabaikan data tambahan sekarang. Di perpustakaan itu akan memiliki metode kelebihan beban memanggil metode baru secara internal yang membutuhkan lebih sedikit parameter. Di layanan yang dihosting Anda memiliki titik akhir mengabaikan data tambahan dan dapat melayani kedua jenis klien dan menjalankan logika yang sama.
Jika fungsi yang ada perlu menambahkan elemen yang diperlukan baru maka Anda harus memiliki dua titik akhir / metode untuk layanan / perpustakaan Anda. Hingga klien memperbarui, Anda perlu mendukung kedua versi.
Pikiran Lainnya
Rather, the API is likely to extend the private objects we are using for our base API, but then we run into the same problem because added properties would also be available in the public API when they are not supposed to be.
Jangan memaparkan objek pribadi internal melalui perpustakaan / layanan Anda. Buat jenis Anda sendiri dan petakan implementasi internal. Ini akan memungkinkan Anda melakukan perubahan internal dan meminimalkan jumlah pembaruan yang perlu dilakukan klien eksternal.
The problem is more that it seems like many or most changes require breaking the public API if the objects aren't more separated, but I don't see a good way to do that without duplicating code.
API apakah itu layanan atau pustaka harus stabil pada titik integrasi dengan klien. Semakin banyak waktu yang Anda ambil untuk mengidentifikasi apa input dan output seharusnya dan menyimpannya sebagai entitas yang terpisah akan menghemat banyak sakit kepala di jalan. Jadikan kontrak API entitas terpisah dan petakan ke kelas yang menyediakan karya nyata. Waktu yang dihemat saat implementasi internal berubah harus lebih dari yang mengimbangi waktu ekstra yang diperlukan untuk mendefinisikan antarmuka ekstra.
Jangan melihat langkah ini sebagai "kode duplikat". Meskipun serupa, mereka adalah entitas terpisah yang layak untuk dibuat. Meskipun perubahan API eksternal hampir selalu membutuhkan perubahan terkait dengan implementasi internal, perubahan implementasi internal tidak selalu mengubah API eksternal.
Contoh
Misalkan Anda menyediakan solusi pemrosesan pembayaran. Anda menggunakan PaymentProviderA untuk melakukan transaksi kartu kredit. Kemudian, Anda mendapatkan nilai yang lebih baik melalui pemroses pembayaran PaymentProviderB. Jika API Anda mengekspos bidang Kartu Kredit / Alamat Bill dari jenis Anda alih-alih representasi PaymentProviderA maka perubahan API adalah 0 karena antarmuka tetap sama (semoga saja, jika PaymentProviderB membutuhkan data yang tidak diperlukan oleh PaymentProviderA maka Anda harus memilih salah satu dari keduanya) mendukung keduanya atau mempertahankan tingkat yang lebih buruk dengan PaymentProviderA).
sumber