Bagaimana Anda mendekati konflik ketergantungan transitif yang hanya diketahui saat run-time? [Tutup]

9

Bagaimana Anda biasanya mendekati masalah ketergantungan transitif yang terjadi pada saat dijalankan dalam proyek perangkat lunak besar?

Selama tiga minggu terakhir, saya telah mencoba untuk memulai komponen dari sebagian besar perangkat lunak dalam komponen lain dari perangkat lunak, tetapi sebentar-sebentar mati karena masalah ketergantungan transitif yang hanya diketahui pada saat run-time.

Dengan masalah dependensi transitif, maksud saya bahwa dependensi tertentu dari dependensi proyek tertentu bertabrakan dengan dependensi lain pada saat run-time, menyebabkan ketidakstabilan, atau kegagalan instan.

Ada ratusan, berdasarkan ratusan dependensi yang digunakan, dan ada sekitar 50 sub proyek yang terkait dengan alat yang dikerjakan secara terpisah oleh tim lain, di mana semua modul memiliki ketergantungan yang sangat bersarang antara satu sama lain. Tidak ada yang tahu untuk apa semua sub proyek digunakan, mengingat skala, dan kompleksitas proyek.

Dalam situasi ini, akankah Anda mencoba untuk menghasilkan representasi visual dari DAG untuk masing-masing dependensi komponen yang terpengaruh, dan berupaya menentukan di mana tabrakan dapat terjadi pada saat run-time? Saya tidak memiliki kendali atas bagaimana dependensi dikelola di sub-proyek lain, dan tidak dapat mengubah kode Java apa pun yang telah ditulis oleh pengembang lain

Solusi yang saya buat hanya bekerja selama satu jam, atau dua, dan kemudian mereka berhenti bekerja karena perubahan komponen hulu. Contoh dari komponen hulu adalah artefak yang bergantung pada proyek yang saya kerjakan yang dibangun pada tahap awal dalam pipa CI.


Atas permintaan orang lain , saya akan memasukkan informasi tentang teknologi apa yang digunakan, dengan risiko pertanyaan ditutup karena terlalu banyak memberikan informasi, atau tubuh terlalu lama:

  • Maven digunakan untuk manajemen ketergantungan; dan
  • Pegas digunakan sebagai wadah DI;
  • Sebagian besar masalah ketergantungan melibatkan tumpang tindih konteks kacang sebagai akibat dari konteks modul lain yang dimuat saat run-time
  • Produk ini bekerja dengan baik, dan ada banyak tes unit, dan tes integrasi untuk menghindari ketepatan fungsional program.

Secara umum, saya mencari pendekatan agnostik bahasa untuk mengidentifikasi cara menyelesaikan konflik ketergantungan tanpa menyebutkan semua kombinasi yang mungkin dari ketergantungan proyek yang diberikan.

Saya tidak dapat merancang ulang proyek, menambahkan gerbang kualitas tambahan, mendorong perubahan paradigma di seluruh perusahaan, atau beralih bahasa sebagai resolusi.

Tyler
sumber
Apakah Anda berbicara tentang sesuatu seperti wadah DI tidak diatur dengan benar untuk mengetahui bahwa untuk IFoo gunakan IFooImpl?
Andy
Tidak, ini lebih seperti paket (b) dalam proyek (b) adalah ketergantungan transitif dari paket (a) dalam proyek (A), tetapi (B) hanya diperkenalkan pada saat run-time. Perangkat lunak semua bekerja dari apa yang bisa saya katakan, tetapi saya hanya perlu set dependensi yang sesuai untuk memungkinkan semua dependensi transitif untuk diselesaikan dengan benar. Ada serangkaian dependensi yang akan memungkinkan produk untuk memulai dengan benar, tetapi, konfigurasi tersebut sangat rapuh. Sebagai dev junior. Saya tidak punya kendali atas ini.
Tyler
2
Ayo, "masalah ketergantungan" adalah istilah yang sangat umum, dan semua orang yang membaca ini mungkin membayangkan sesuatu yang berbeda. Untuk softare dunia nyata ini adalah ketergantungan teknologi, jadi tolong berikan contoh nyata untuk teknologi tertentu yang ada dalam pikiran Anda. Apakah masalah timbul karena komponen yang mereka butuhkan hilang? Atau karena versi yang salah disediakan? Mekanisme resolusi ketergantungan seperti apa yang sudah ada? Mohon klarifikasi.
Doc Brown
1
Di dunia .Net saya mengatasi masalah ini hanya menginstal paket ke proyek aplikasi utama saya. Meskipun tidak ada kode aplikasi yang benar-benar menggunakan pustaka plugin secara langsung, kompiler .Net memastikan DLL berada di tempat yang tepat selama pembuatan dan dengan demikian penyebaran.
Andy
2
"Saya tidak memiliki kendali atas bagaimana dependensi dikelola, dan tidak dapat mengubah kode apa pun" - apa yang sebenarnya dapat Anda ubah? Jika Anda tidak dapat mengubah apa pun, pertanyaan itu sepertinya tidak ada artinya.
Doc Brown

Jawaban:

6

Dimungkinkan untuk memecahkan masalah Anda menggunakan classloader khusus untuk memberikan setiap modul dalam aplikasi lingkungan eksekusi sendiri.

Pada dasarnya, Anda akan mendefinisikan lingkungan inti yang terdiri dari kernel kecil aplikasi, bersama dengan dependensi apa pun yang disetujui secara universal dan semua antarmuka yang diperlukan untuk modul untuk berkomunikasi satu sama lain. Kemudian, setiap modul yang Anda muat mendapatkan classloader sendiri yang dapat mengakses (1) kelas dari lingkungan runtime, (2) kelas dari inti aplikasi, dan (3) kelas dari modul itu dan dependensi langsungnya. Semua komunikasi antar modul melewati antarmuka yang ditentukan dalam inti sehingga tidak ada modul yang secara langsung bergantung pada yang lain.

Teknik ini digunakan di server aplikasi untuk memungkinkan aplikasi memiliki dependensi yang jika tidak akan berbenturan, sehingga Anda dapat melihat implementasi teknik yang berfungsi, misalnya, di Tomcat (dan, jika Anda beruntung, Anda mungkin dapat menggunakan Tomcat's implementasi dengan sedikit perubahan).

Jules
sumber
1
Saya tidak diizinkan merancang ulang proyek untuk menyelesaikan masalah ketergantungan. Beralih ke arsitektur mirip kernel akan menjadi agak keren.
Tyler
2
@ Tyler: namun saya pikir ini adalah jawaban yang baik dan umum untuk bagian umum dari pertanyaan.
Doc Brown
1
Kedengarannya agak mirip osgi.
SpaceTrucker
4

Saya tidak pernah bekerja dengan Maven atau Spring, tetapi untuk memberi Anda jawaban umum untuk pertanyaan umum: ketika sampai pada masalah ketergantungan, sistem Anda harus dirancang untuk mendeteksi mereka pada titik waktu yang paling awal , dan ketika masalah itu terdeteksi , mereka harus diberi sinyal segera, termasuk kemungkinan penyebabnya.

Idealnya, titik waktu ini bukan pada "waktu produksi berjalan". Titik waktu terbaik adalah "membangun waktu", tetapi itu tampaknya tidak mungkin dalam kasus Anda. Jadi pilihan terbaik kedua adalah tes waktu berjalan. Anda memberi tahu kami bahwa ada "tes integrasi", tetapi karena mereka tidak mendeteksi masalah ketergantungan, mereka tampaknya tidak lengkap, atau mereka tidak menguji tabrakan ketergantungan secara umum. Di situlah Anda harus mulai mencoba menyelesaikan masalah.

Selain itu, untuk membuat tes lebih efektif, komponen Anda harus "gagal cepat" ketika masalah ketergantungan muncul. Itu berarti, segera setelah ketergantungan diselesaikan dan komponen dimuat, potensi tabrakan ketergantungan harus diperiksa dan diberi sinyal segera. Jika sistem pertama kali berjalan selama satu jam sebelum tabrakan terdeteksi, menjadi sangat sulit untuk menemukan penyebab masalah. Saya tidak tahu apakah Maven / Spring sudah menyediakan Anda dengan strategi "gagal cepat", tetapi jika ini tidak terjadi, cobalah untuk berpikir ke arah itu.

Untuk mengurangi masalah dalam produksi, sistem Anda harus dirancang untuk tidak mati sepenuhnya ketika terjadi tabrakan ketergantungan dengan sub-komponen yang kurang penting. Kegagalan tidak harus ditutup, tentu saja, tetapi sistem idealnya harus menolak pemuatan komponen itu, mencatat dan / atau memberi sinyal masalah dan tetap dalam kondisi stabil. Ketika komponen dimuat terlebih dahulu, sistem menjadi tidak stabil dan Anda mendeteksi masalah hanya setelah itu, maka Anda mungkin harus mematikan dan memulai ulang sistem sepenuhnya, yang saya kira adalah sesuatu yang Anda ingin hindari.

Misalnya, jika sistem Anda adalah toko Web, dan submodul Anda untuk "berlangganan buletin" tidak dapat dimuat selama beberapa jam, itu adalah sesuatu yang mungkin lebih mudah ditoleransi seolah-olah seluruh toko tidak berfungsi lagi.

Akhirnya, ini mungkin bukan opsi dalam kasus Anda, tetapi jika komponen dapat dibuat berjalan dalam isolasi yang lebih baik satu sama lain, dan jika itu dapat menghindari tabrakan ketergantungan, itu mungkin merupakan pendekatan yang layak untuk dipikirkan.

Doc Brown
sumber
2

Anggap ini aku hanya berpikir keras di sini. Tergantung pada persyaratan / batasan waktu saya dapat mempertimbangkan ini:

1) membuat daftar antarmuka dan implementasinya (menggunakan refleksi, jika tersedia)

2) buat semacam pembungkus DI Anda. Ketika DI diminta untuk memberikan implementasi konkret, lihat apakah sudah ada aturan DI; jika ada aturan - kembalikan apa yang disediakan DI Anda; jika tidak, jika ada satu implementasi antarmuka dan Anda dapat membuat instance - log, dan mengembalikan instance; jika tidak, log dan gagal.

Tergantung pada seberapa terlibat Anda ingin mendapatkan, saya kira, tetapi akhirnya Anda hanya ingin memiliki daftar lengkap tentang apa yang memerlukan apa - solusi ini pada akhirnya akan menghasilkan daftar itu.

Namun, bisa dibilang ini banyak pekerjaan dan tidak dapat diandalkan - bagaimana jika Anda memiliki kondisi aneh yang membutuhkan ketergantungan tertentu sekali dalam bulan biru?

Apa yang Anda maksud ketika Anda mengatakan "perubahan komponen hulu"?

Evgeni
sumber
Maaf, saya tidak ingin memberikan terlalu banyak informasi latar belakang - ketika saya menggambarkan lingkungan operasi, pertanyaan biasanya diturunkan, dan dinyalakan sampai mati. Saya akan memperbarui pertanyaan awal dengan bagian definisi.
Tyler
2

Jika saya mengikuti Anda dengan benar, masalahnya adalah bahwa kode yang perlu Anda gunakan memiliki dependensi run-time pada modul yang diekspresikan dalam Spring XML, tetapi pakar tidak diberitahu tentangnya. Jadi ketika Anda menggunakannya, hal-hal yang mereka butuhkan (dependensi transitif) tidak berada di jalur kelas Anda, dan mereka tidak melakukan apa yang seharusnya.

Saya menduga ketika Anda bertanya kepada rekan kerja Anda 'bagaimana saya bisa membuat ini bekerja?', Mereka mengatakan 'jelas Anda membutuhkan daftar 35 modul dan versi ini , bagaimana Anda tidak tahu itu?'

Agaknya ketika pengujian integrasi dilakukan, modul yang diperlukan dinyatakan sebagai dependensi pengujian. Jadi solusi sistematis adalah dengan mengatur inspeksi pom uji integrasi untuk memastikan mereka tidak memiliki apa-apa selain alat uji pihak ketiga yang dinyatakan sebagai dependensi pengujian. Ini bahkan bisa otomatis oleh plugin penegak pakar .

Tampaknya Anda tidak bisa melakukan itu, jadi pilihan terbaik Anda kemungkinan ditemukan di sini .

soru
sumber
Itulah tepatnya yang terjadi, dari apa yang bisa saya ceritakan. Sejauh ini saya menyulap 30 dependensi, dan memutar-mutar lingkup untuk menghilangkan tabrakan, tetapi, peer review adalah yang diperlukan di sini.
Tyler