Bagaimana mencegah perubahan pada API internal agar tidak merusak proyek lain?

8

Kami memiliki 20 - 30 modul / solusi independen. Masing-masing memiliki sekitar 7 - 10 proyek dengan kelas yang berbeda, komponen, dll. Ini semua digunakan secara internal untuk perusahaan kami.

Masalah kita adalah ketika kita membuat perubahan dalam satu modul, kita kemudian perlu memastikan untuk memperbarui semua modul lain yang mengakses kode ini. Ini sulit diketahui karena berada dalam basis kode yang berbeda.

Bagaimana kita bisa mendokumentasikan di mana semua penggunaan eksternal API? Atau sebaliknya mencegah perubahan kecil dari melanggar modul lain?

Matematika
sumber
6
Bagaimana mencegah perubahan API dari melanggar kode? Umm ... jangan ubah API. Sungguh, jawaban apa yang bisa ada selain itu?
@ dan1111 bagaimana jika kita harus membuat perubahan pada API dan kita tidak tahu modul apa yang akan kita hancurkan, bagaimana ini bisa dicegah, atm saya mendapatkan nama metode dan mencari file basis kode kita pada harddisk, tidak begitu efisien melakukannya
Matematika
Apa yang salah dengan mencari basis kode untuk panggilan metode? Jika Anda tidak memiliki dokumentasi tentang apa yang menggunakan apa, ini adalah cara yang cukup baik untuk melakukannya. Anda dapat dengan mudah menulis skrip kecil yang mencari semua kode Anda untuk semua panggilan API dan laporan tentang ini.
1
dapatkah Anda memberi kami detail lebih lanjut? bahasa pemrograman apa? apakah kompatibilitas kode sumber ok atau apakah Anda memerlukan kompatibilitas biner? Apakah "tidak mengubah tanda tangan api yang ada" tetapi hanya menambahkan tanda tangan metode baru yang menyelesaikan masalah Anda? Apakah bahasa Anda mendukung "parameter standar"
k3b

Jawaban:

13

Solusi paling sederhana, IMO, adalah memiliki sejumlah tes otomatis yang layak untuk setiap produk. Saat Anda memperbarui perpustakaan, Anda menjalankan ruang uji untuk setiap produk. Jika tes gagal, maka Anda akan tahu produk mana yang perlu diperbarui.

Bryan Oakley
sumber
5

Saya akan menyarankan untuk tidak mencoba mendokumentasikan ini (setidaknya secara manual) karena jika Anda meminta orang untuk memperbaruinya, itu akan membutuhkan tingkat akurasi yang tinggi untuk bekerja dengan benar. Tetapi Anda tidak akan pernah mendapatkan tingkat akurasi seperti itu karena menambahkan dokumentasi semacam ini akan ... tidak menyenangkan dan tidak ada yang akan melakukannya.

Beberapa opsi yang lebih baik:

  • Memiliki skrip yang menghasilkan daftar semua panggilan metode yang dapat digunakan di semua modul lain, berdasarkan kriteria pencarian. Sederhana, kasar, tetapi mungkin efektif.
  • Semacam sistem versi di mana Anda tidak merusak kompatibilitas kecuali pada nomor versi utama. Jadi, jika Anda mengubah metode foo dari versi 2.1 ke 2.2, semua kode referensi versi 2.X akan tetap berfungsi. Ketika Anda perlu memutakhirkan kompatibilitas ini, perbarui nomor versi utama (jadi dalam hal ini, 3.0) dan umumkan ini kepada semua pemilik proyek yang bertanggung jawab atas modul lain. Bergantung pada bagaimana proses rilis Anda bekerja, ini mungkin sederhana - atau sangat rumit - untuk diterapkan.
  • Memiliki pengujian otomatis atau proses pembuatan CI di mana setiap kali Anda mendorong kode, sebuah build menjalankan beberapa jenis pengujian. Ini akan memungkinkan Anda untuk mengidentifikasi di mana masalah terjadi. Dugaan saya adalah dengan apa yang Anda gambarkan sebagai masalah yang belum Anda miliki di tempat ini ..
  • Semacam sistem dokumentasi otomatis untuk semua modul / repositori Anda

Anda juga mungkin mempertimbangkan untuk secara perlahan refactoring API tidak terlalu rapuh, tapi saya berharap itu di luar ruang lingkup apa yang dapat Anda capai secara wajar jika Anda seorang individu dan memiliki 20+ modul skala besar untuk bekerja dengannya.

enderland
sumber
1
+1 untuk versi, plus tautan ke Semantic Versioning
xpy
2

Pertama-tama, API dengan penggunaan eksternal tidak boleh berubah.

Seperti @BryanOakley sebutkan, menggunakan unit-test otomatis sangat penting dan menyelamatkan jiwa dalam situasi seperti itu. Di luar itu, beberapa saran yang mungkin (atau mungkin tidak, sesuai situasi) membantu Anda

  • Banyak bahasa (seperti Java dan C #) menawarkan Function/Method Overriding. Bahasa seperti Python menawarkan Anda untuk memberikan (jumlah tak terbatas) argumen dan argumen kata kunci ke suatu fungsi:

    Jawa:

    public void disp(char c)
    {
         System.out.println(c);
    }
    
    public void disp(char c, int num)  
    { 
         System.out.println(c + " " + num);
    }
    
    disp("A")
    disp("A", 3)

    Python

    def disp(c, *args):
        if args:
            num = args[0]
            print("%s %f" % (c, num))
        else:
            print("%s" % c)
    
    disp("A")
    disp("A", 3)
  • Banyak bahasa menawarkan public, privatedan protectedmetode. Anda dapat menangani panggilan fungsi dalam suatu publicfungsi dan melakukan pekerjaan dalam private/protectedfungsi.

    Dalam python, tidak ada definisi publik / pribadi untuk metode dan fungsi, tetapi garis bawah terkemuka ( _) mengatakan bahwa suatu metode bersifat pribadi dan tidak boleh digunakan secara eksternal. Panggilan API eksternal diserahkan oleh metode yang terbuka untuk dunia luar dan semua tugas dilakukan dalam fungsi lokal :

    def format_input(a, b, *args, **kwargs):
        # This function is open to anyone. so use *args and **kwargs to get
        # all possible available arguments. Do not change this function
        # definition and function parameters
        a = _evaluate_input(a)
        b  =_evaluate_input(b)
        # c is not used by all APIs and may not documented in all external
        # API docs. So chech if it was sent as a keyword argument. If yes
        # evalaute it too
        if "c" in kwargs:
            c  =_evaluate_input(kwargs.get("c"))
        _check_extra_arguments(args)
        _check_extra_keyward_arguments(kwargs)
    
    def _evaluate_input(value):
        # This is a private method thus should not be called from the
        # outside world. You can change this method and parameter structure 
        # to fit your needs and do not care for outside world since no
        # outer API should use this function directly.
        ...
    
    def _check_extra_arguments(value):
        # We will check if any extra argument is passed and handle them accordingly
        ...

Seperti yang saya katakan, definisi API yang (juga) digunakan oleh aplikasi eksternal tidak boleh terlalu banyak berubah. Anda dapat mencari cara untuk membuat fungsi luar Anda lebih fleksibel sehingga Anda dapat mengubah cara kerja API tanpa melanggar keadaan saat ini.

FallenAngel
sumber
1

Masalah kita adalah ketika kita membuat perubahan dalam satu modul, kita kemudian perlu memastikan untuk memperbarui semua modul lain yang mengakses kode ini. Ini sulit diketahui karena berada dalam basis kode yang berbeda.

Saya akan menyarankan bahwa ini tidak mungkin diketahui.

Anda bertanggung jawab atas Komponen dan Antarmuka mereka.
Anda tidak bertanggung jawab atas apa pun dan segala sesuatu yang mungkin memanfaatkannya.

Bagaimana kita bisa mendokumentasikan di mana semua penggunaan eksternal API? Atau sebaliknya mencegah perubahan kecil dari melanggar modul lain?

Jawaban singkat? Tes.

Tulis Tes yang menggunakan Antarmuka yang diterbitkan. Jalankan kembali setiap kali Anda melakukan perubahan. Selama tes "Lulus", Anda belum merusak apa pun. Ketika tes rusak (dan itu akan) baik (a) menemukan dan memperbaiki masalah atau (b) jika Anda dapat membenarkan perubahan sebagai sah, maka tulis ulang tes untuk mengakomodasi itu.

Phill W.
sumber
0

Saya telah melihat dan memberi kode API dengan nomor versi di jalur fungsi dan / atau nama.

Dengan cara ini Anda dapat memiliki versi API yang berbeda tersedia - lengkap API dan versi fungsi yang berbeda dalam API.

Ini menempatkan pekerjaan menjaga semua versi API dalam kode untuk API - tidak ada kode aplikasi lain yang perlu diubah selain dari yang di mana fasilitas API baru diproduksi.

Saya pikir ini sangat penting saat menulis API yang akan digunakan oleh aplikasi di luar organisasi Anda.

Sebagai contoh, berikut adalah contoh kode untuk mengirim SMS menggunakan api bulksms:

http://developer.bulksms.com/eapi/code-samples/csharp/send_sms/

dari sana ada garis:

string url = ".../submission/send_sms/2/2.0";

di mana 2 dan 2.0 adalah nomor versi API.

Karena API ini dimaksudkan untuk digunakan oleh banyak pelanggan SMS Massal, perubahan pada API ini akan berpotensi menghancurkan banyak aplikasi dan membuat telepon dukungan berdering.

Mike Vincent
sumber