Apakah perpustakaan umum adalah ide yang bagus?

16

Saya selalu berpikir bahwa "perpustakaan umum" adalah ide yang bagus. Maksud saya perpustakaan yang berisi fungsionalitas umum yang sering dibutuhkan oleh beberapa aplikasi yang berbeda. Ini menghasilkan duplikasi / redundansi kode yang lebih sedikit.

Saya baru-baru ini membaca sebuah artikel (tidak dapat menemukan sekarang) yang mengatakan ini sebenarnya adalah ide yang buruk dan bahkan mengatakan itu adalah "anti-pola"

Meskipun ada sisi negatif dari pendekatan ini. Versi dan pengelolaan perubahan berarti uji regresi untuk rangkaian aplikasi yang menggunakan pustaka ini.

Saya agak terjebak dalam rutinitas untuk proyek baru saya (Golang). Deduplikasi kode telah dipalu pada saya selama bertahun-tahun tetapi saya merasa saya harus mencobanya kali ini.

Saat menulis ini, saya mulai berpikir bahwa pendekatan "common lib" ini adalah hasil dari membaca sekilas tentang arsitektur? Mungkin desain saya perlu lebih dipikirkan?

Tertarik mendengar pikiran.

Jim
sumber
2
2 sen saya ... Jika Anda harus membuat perubahan pada api biasa jika salah satu sistem menggunakannya perlu perubahan itu, maka API atau pustaka tersebut bukanlah perpustakaan umum sama sekali
Raja Anbazhagan
1
Saya menemukan bahwa ada trade-off mendasar antara duplikasi dan penggandaan kode. Pertanyaan Anda adalah contoh utama dari hal itu. Keseimbangan yang Anda serang di antara keduanya mungkin akan tergantung pada lingkungan yang pada akhirnya akan dieksekusi oleh kode Anda.
Joel Cornett
Sebagian besar pengembang C yang saya kenal memiliki koleksi utilitas yang mereka sebut sebagai "kotak peralatan" mereka. Namun, biasanya tidak dikumpulkan ke satu perpustakaan yang disertakan. Ini lebih "pilih dan pilih".
Mark Benningfield
2
Seseorang panggil Apache dan perbaiki kegilaan ini. Apache commons
Laiv

Jawaban:

21

Perpustakaan dan penggunaan kembali benar-benar hal yang baik. Mereka memiliki satu kelemahan besar, yaitu jika tidak dikelola dengan hati-hati, laci tersebut menjadi setara dengan laci di dapur Anda yang menampung semua peluang dan ujung yang tidak mengarah ke tempat lain.

Saya melihat ini dalam tindakan ketika saya menjadi bertanggung jawab untuk port pertama dari seluruh kode nilai unit bisnis (kebanyakan baru bagi saya) untuk sistem 64-bit dan melakukan perombakan total untuk bangunan dan pengemasan kami, banyak yang sedang dilakukan dengan tangan dan kadang-kadang tidak terlalu baik. * Kami cenderung membangun apa yang kami kirimkan dari setumpuk aplikasi, di mana klien akan berkata, "Saya ingin sistem yang melakukan A, B, D dan F, ditambah hal-hal M dan N yang belum Anda lakukan dan sedikit lem yang berbeda mengintegrasikan semuanya. " Kesamaan semua itu adalah perpustakaan laci-sampah yang, selama beberapa dekade, ** mengumpulkan semua hal yang orang pikir harus digunakan kembali. Untuk membuat cerita panjang pendek, sebagian kecil dari kode di perpustakaan bukan. Kami menghabiskan banyak waktu yang berharga untuk membangun dan mempertahankan dependensi-dependensi itu hanya agar perpustakaan umum dapat diinstal, bukan karena kami benar-benar membutuhkannya.

Moralnya adalah perpustakaan harus diperlakukan seperti kelas dan tidak dibebani dengan terlalu banyak tanggung jawab. Jangan meletakkan parser JSON Anda di perpustakaan yang sama dengan fungsi aljabar linier Anda, bahkan jika setiap program yang Anda tulis menggunakan keduanya.

Menjaga mereka tetap terpisah memiliki banyak manfaat, yang terbesar di antaranya adalah memaksa pengembang dan pembuat paket Anda untuk membuat perhitungan terperinci tentang apa yang sebenarnya dibutuhkan produk mereka alih-alih hanya termasuk laci sampah dan bagasi yang menyertainya. Ketika Anda mengatur sistem menggunakan paket-paket yang dibangun, dependensi berbutir halus memastikan bahwa hanya bagian-bagian yang diperlukan saja yang diinstal. Bahkan jika Anda mengabaikan repositori Anda dan terus mengkompilasi hal-hal yang lama dan kasar, tidak ada yang tidak lagi digunakan bocor ke dalam apa yang Anda kirim.

Tentu saja ada pengecualian seperti libcitu menjejalkan banyak fungsi ke dalam satu perpustakaan. Itulah salah satu kasus di mana manfaat melakukannya dengan cara seperti itu dapat dipikirkan alih-alih membabi buta dengan semangat ke lorong yang bersikeras bahwa cara lain selain X selalu merupakan praktik yang buruk.


* Dalam prosesnya, saya menemukan biner yang telah diedarkan dan belum dikompilasi dari awal dalam enam tahun.

** Tidak ada yang salah dengan kode lama. Kami memiliki sejumlah algoritma kritis yang telah terbukti sangat baik sehingga kami bodoh untuk menulis ulang hanya untuk kepentingan modernitas.

Blrfl
sumber
1
Aturan praktis saya adalah, jika Anda bermaksud memberi nama perpustakaan Anda sesuatu seperti "umum," Anda akan menghadapi masalah.
Karl Bielefeldt
9

Dengan memalukan saya memperkenalkan perpustakaan "umum", yang dinamai demikian, di lingkungan tim beberapa dekade yang lalu. Saya tidak begitu memahami dinamika saat itu tentang apa yang bisa terjadi dalam pengaturan tim yang terkoordinasi secara longgar hanya dalam hitungan bulan.

Ketika saya memperkenalkannya, saya pikir saya sudah menjelaskan dan juga mendokumentasikan bahwa itu untuk hal-hal yang kita semua setuju bahwa kita akan berguna setiap hari, bahwa itu dimaksudkan untuk menjadi perpustakaan minimalis, dan bahwa perpustakaan harus bergantung pada hal lain selain perpustakaan standar sehingga semudah mungkin digunakan dalam proyek-proyek baru. Pemikiran saya pada saat itu adalah bahwa itu adalah perluasan kecil kami sendiri ke perpustakaan standar untuk hal-hal yang, dalam domain khusus kami, kami temukan berguna setiap hari.

Dan itu dimulai dengan cukup baik. Kami mulai dengan perpustakaan matematika ( common/math*) dari rutinitas yang kami semua gunakan setiap hari, karena kami bekerja dalam grafik komputer yang sering berat pada aljabar linier. Dan karena kami sering berinteraksi dengan kode C, kami menyetujui beberapa fungsi utilitas yang bermanfaat seperti find_indexitu, tidak sepertistd::finddi C ++, akan mengembalikan indeks ke elemen yang ditemukan secara berurutan alih-alih iterator yang meniru bagaimana fungsi C kita bekerja - hal-hal semacam ini - sedikit eklektik tetapi minimalis dan cukup banyak digunakan untuk tetap akrab dan praktis untuk semua orang , dan keakraban instan adalah kriteria yang sangat penting seperti yang saya lihat dalam mencoba membuat apa pun yang "umum" atau "standar" karena jika itu benar-benar "umum", itu harus memiliki kualitas yang akrab tentang itu sebagai hasil dari luasnya adopsi dan penggunaan sehari-hari.

Namun seiring waktu niat desain perpustakaan terlepas dari jari saya ketika orang mulai menambahkan hal-hal yang mereka gunakan secara pribadi yang mereka pikir mungkin berguna bagi orang lain, hanya untuk menemukan tidak ada orang lain yang menggunakannya. Dan kemudian seseorang mulai menambahkan fungsi yang bergantung pada OpenGL untuk rutin terkait GL yang umum. Selanjutnya kami mengadopsi Qt dan orang-orang mulai menambahkan kode yang bergantung pada Qt, jadi sudah umum perpustakaan bergantung pada dua perpustakaan eksternal. Pada titik tertentu seseorang menambahkan rutinitas shader umum yang bergantung pada pustaka shader khusus aplikasi kami, dan pada saat itu Anda bahkan tidak dapat menggunakannya di proyek baru tanpa memasukkan Qt, OGL, dan pustaka shader khusus aplikasi dan penulisan kami skrip bangun non-sepele untuk proyek Anda. Jadi itu berubah menjadi kekacauan eklektik dan saling tergantung ini.

Tetapi saya juga menemukan dengan memperdebatkan apa yang harus dan tidak harus masuk ke perpustakaan ini bahwa apa yang dianggap "umum" dapat dengan mudah berubah menjadi ide yang sangat subyektif jika Anda tidak menetapkan aturan garis yang sangat keras bahwa apa yang "umum" adalah apa yang cenderung bermanfaat bagi setiap orang setiap hari. Setiap pelonggaran standar dan dengan cepat menurunkan dari hal-hal yang setiap orang merasa berguna setiap hari menjadi sesuatu yang berguna bagi pengembang tunggal yang mungkin memiliki kemungkinan bermanfaat bagi orang lain, dan pada saat itu perpustakaan terdegradasi menjadi kekacauan eklektik yang sangat cepat .

Tetapi lebih jauh lagi ketika Anda mencapai titik itu, beberapa pengembang dapat mulai menambahkan hal-hal karena alasan sederhana bahwa mereka tidak menyukai bahasa pemrograman. Mereka mungkin tidak menyukai sintaks for for loop atau function call, di mana perpustakaan mulai dipenuhi dengan hal-hal yang hanya melawan sintaks dasar bahasa, mengganti beberapa baris kode langsung yang tidak benar-benar menduplikasi logika apa pun hingga satu baris singkat kode eksotis hanya akrab bagi pengembang yang memperkenalkan steno semacam itu. Kemudian pengembang seperti itu mungkin mulai menambahkan lebih banyak fungsi ke perpustakaan umum yang diimplementasikan menggunakan steno seperti itu, pada titik mana bagian-bagian penting dari perpustakaan umum menjadi terjalin dengan steno-steno eksotis yang mungkin tampak indah dan intuitif bagi pengembang yang memperkenalkannya tetapi jelek dan asing dan sulit dimengerti untuk semua orang. Dan pada titik itu saya pikir Anda tahu bahwa setiap harapan untuk membuat sesuatu yang benar-benar "umum" hilang, karena "umum" dan "asing" adalah ide yang berlawanan.

Jadi ada semua jenis kaleng cacing di sana, setidaknya di lingkungan tim yang terkoordinasi dengan longgar, dengan perpustakaan dengan ambisi seluas dan sama umum dengan "barang yang biasa digunakan". Dan sementara masalah yang mendasari mungkin adalah koordinasi longgar di atas segalanya, setidaknya beberapa perpustakaan dimaksudkan untuk melayani tujuan yang lebih tunggal, seperti perpustakaan yang dimaksudkan untuk menyediakan rutinitas matematika dan tidak ada yang lain, mungkin tidak akan menurunkan secara signifikan dalam hal ini. desain kemurnian dan dependensi sebagai perpustakaan "umum". Jadi dalam retrospeksi saya pikir akan jauh lebih baik untuk berbuat salah di sisi perpustakaan yang memiliki niat desain yang jauh lebih jelas. Saya juga menemukan selama bertahun-tahun bahwa tujuan yang sempit dan penerapan yang sempit adalah ide yang sangat berbeda.

Juga saya diakui setidaknya sedikit tidak praktis dan peduli mungkin sedikit terlalu banyak tentang estetika, tetapi cara saya cenderung memahami ide saya tentang kualitas perpustakaan (dan mungkin bahkan "keindahan") dinilai lebih oleh tautan terlemahnya daripada ini yang terkuat, dengan cara yang sama bahwa jika Anda menyajikan saya makanan yang paling menggugah selera di dunia tetapi, di piring yang sama, menaruh sesuatu yang membusuk di sana yang baunya sangat buruk, saya cenderung ingin menolak seluruh piring. Dan jika Anda seperti saya dalam hal itu dan membuat sesuatu yang mengundang segala macam tambahan sebagai sesuatu yang disebut "umum", Anda mungkin menemukan diri Anda melihat piring analog dengan sesuatu yang membusuk di samping. Jadi saya pikir itu baik jika perpustakaan dikelola dan dinamai dan didokumentasikan sedemikian rupa sehingga tidak ' t mengundang semakin banyak penambahan dari waktu ke waktu. Dan itu bahkan dapat diterapkan pada kreasi pribadi Anda, karena saya tentu saja telah membuat beberapa barang busuk di sana-sini, dan itu "lebih sedikit" mencemari jika tidak ditambahkan ke piring terbesar. Memisahkan hal-hal menjadi perpustakaan kecil, sangat tunggal memiliki kecenderungan untuk memisahkan kode yang lebih baik juga, jika hanya karena kebajikan semata yang menjadi jauh lebih tidak nyaman untuk mulai menggabungkan semuanya.

Deduplikasi kode telah dipalu pada saya selama bertahun-tahun tetapi saya merasa saya harus mencobanya kali ini.

Apa yang mungkin saya sarankan dalam kasus Anda adalah untuk mulai memudahkan deduplikasi kode. Saya tidak mengatakan untuk menyalin dan menempelkan potongan besar kode yang tidak teruji, rawan kesalahan di sekitar atau semacam ini, atau menduplikasi kode non-sepele dalam jumlah besar yang memiliki probabilitas yang layak untuk memerlukan perubahan di masa depan.

Tetapi terutama jika Anda memiliki pola pikir untuk membuat perpustakaan "umum", yang menurut saya keinginan Anda adalah untuk menciptakan sesuatu yang dapat diterapkan secara luas, sangat dapat digunakan kembali, dan mungkin idealnya sesuatu yang Anda temukan sama bermanfaatnya hari ini seperti yang Anda lakukan satu dekade dari sekarang , maka terkadang Anda bahkan mungkin perlu atau menginginkan duplikasi untuk mencapai kualitas yang sulit dipahami ini. Karena duplikasi mungkin sebenarnya berfungsi sebagai mekanisme decoupling. Ini seperti jika Anda ingin memisahkan pemutar video dari pemutar MP3, maka Anda setidaknya harus menduplikasi beberapa hal seperti baterai dan hard drive. Mereka tidak dapat berbagi hal-hal ini atau kalau tidak, mereka tidak dapat digabungkan dan tidak dapat digunakan secara independen satu sama lain, dan pada saat itu orang mungkin tidak tertarik pada perangkat lagi jika semua yang ingin mereka lakukan adalah memutar MP3. Tetapi beberapa waktu setelah Anda memisahkan kedua perangkat ini, Anda mungkin menemukan bahwa pemutar MP3 dapat mengambil manfaat dari desain baterai yang berbeda atau hard drive yang lebih kecil dari pemutar video, di mana Anda tidak lagi menduplikasi apa pun; apa yang awalnya dimulai sebagai duplikasi untuk memungkinkan perangkat yang saling bergantung ini dipecah menjadi dua, perangkat independen yang terpisah nantinya dapat menghasilkan desain dan implementasi yang tidak lagi mubazir sama sekali.

Ada baiknya mempertimbangkan hal-hal dari perspektif yang menggunakan perpustakaan. Apakah Anda benar-benar mau menggunakannyaperpustakaan yang meminimalkan duplikasi kode? Kemungkinannya adalah Anda tidak akan melakukannya karena yang melakukannya secara alami akan bergantung pada perpustakaan lain. Dan pustaka-pustaka lain itu mungkin bergantung pada pustaka lain untuk menghindari duplikasi kodenya, dan seterusnya, sampai Anda mungkin perlu mengimpor / menautkan 50 pustaka yang berbeda hanya untuk mendapatkan beberapa fungsi dasar seperti memuat dan memainkan file audio, dan itu menjadi sangat sulit . Sementara itu jika perpustakaan audio seperti itu sengaja memilih untuk menduplikasi beberapa hal di sana-sini untuk mencapai kemandiriannya, itu akan menjadi jauh lebih mudah untuk digunakan dalam proyek-proyek baru, dan kemungkinan bahwa itu tidak perlu diperbarui hampir sesering sejak ia menang ' tidak perlu berubah sebagai akibat dari perubahan perpustakaan eksternal yang bergantung yang mungkin berusaha memenuhi tujuan yang lebih umum daripada apa yang dibutuhkan perpustakaan audio.

Jadi kadang-kadang ada baiknya secara sengaja memilih untuk menggandakan sedikit (secara sadar, tidak pernah kemalasan - sebenarnya karena ketekunan) untuk memisahkan perpustakaan dan menjadikannya independen karena, melalui kemandirian itu, ia mencapai jangkauan penerapan praktis yang lebih luas dan bahkan stabilitas (tidak ada lagi kopling aferen). Jika Anda ingin mendesain pustaka yang paling dapat digunakan kembali yang mungkin akan bertahan Anda dari satu proyek ke yang berikutnya dan selama bertahun-tahun, maka di atas mempersempit cakupannya ke minimum, saya benar-benar akan menyarankan mempertimbangkan duplikasi sedikit di sini. Dan secara alami tulis unit test dan pastikan itu benar-benar diuji dan dapat diandalkan pada apa yang dilakukannya Ini hanya untuk perpustakaan yang Anda benar-benar ingin meluangkan waktu untuk menggeneralisasi ke titik yang jauh melampaui satu proyek.


sumber
3

Ada tiga kategori fungsi yang dapat Anda pertimbangkan untuk dimasukkan ke perpustakaan:

  1. Barang-barang yang layak digunakan kembali untuk semua orang.
  2. Barang hanya layak digunakan kembali untuk organisasi Anda.
  3. Barang tidak layak digunakan kembali.

Kategori satu adalah sesuatu yang harus ada di perpustakaan standar , tetapi untuk beberapa alasan tidak ada yang membuat (atau apakah seseorang? Apakah Anda mencari secara menyeluruh?). Dalam hal ini pertimbangkan untuk menjadikan perpustakaan Anda open source. Berbagi pekerjaan Anda tidak hanya membantu orang lain, tetapi juga membantu Anda, karena Anda akan menerima laporan bug dan tambalan dari pengguna lain. Ketika Anda ragu siapa pun akan berkontribusi pada perpustakaan Anda, maka Anda mungkin berurusan dengan fungsionalitas yang sebenarnya adalah kategori 2 atau 3.

Kategori kedua adalah hal-hal yang Anda butuhkan berulang kali, tetapi tidak ada orang lain di dunia yang membutuhkannya. Misalnya, implementasi protokol jaringan yang tidak jelas untuk berkomunikasi dengan sistem backend yang dikembangkan di dalam perusahaan Anda. Dalam hal ini mungkin masuk akal untuk memasukkan barang-barang itu ke dalam perpustakaan internal untuk meningkatkan kecepatan pengembangan aplikasi baru. Pastikan itu tidak terlalu terpengaruh oleh fitur creep dan mulai mengandung hal-hal yang benar-benar cocok dengan kategori 1 atau 3. Selain itu, saran oleh Blrfl mengenai modularisasi sangat baik: Jangan membuat satu Perpustakaan Conor Corp. monolitik. Buat beberapa perpustakaan terpisah untuk fungsi yang terpisah.

Kategori tiga adalah fungsionalitas yang sangat sepele untuk diterapkan sehingga memindahkannya ke perpustakaan tidak layak atau di mana Anda tidak yakin Anda akan membutuhkannya lagi dalam bentuk yang persis seperti itu di aplikasi lain. Fungsi ini harus tetap menjadi bagian dari aplikasi yang dikembangkannya. Jika ragu, kemungkinan termasuk dalam kategori ini.

Philipp
sumber
1

Hampir semua bahasa memiliki perpustakaan umum / standar, jadi ini secara luas diakui sebagai ide yang bagus. Menggunakan perpustakaan bagian ketiga untuk berbagai tugas daripada menciptakan kembali roda juga umumnya dianggap ide yang baik, meskipun biaya / manfaat dan kualitas perpustakaan jelas harus dievaluasi dalam setiap kasus.

Lalu ada perpustakaan "utilitas umum" yang digunakan oleh pengembang atau lembaga individual di proyek yang tidak terkait. Ini adalah jenis perpustakaan yang dapat dianggap sebagai anti-pola. Dalam kasus yang saya lihat, perpustakaan ini hanya mereplikasi fungsi dari perpustakaan standar atau perpustakaan pihak ketiga yang lebih terkenal dengan cara yang tidak standar dan tidak terdokumentasi dengan baik.

JacquesB
sumber
these libraries just replicate functionality from standard librariesini bukan sepenuhnya hal yang buruk, dalam javascript Anda telah menambahkan perpustakaan yang sudah menerapkan hal-hal yang ada untuk menambah dukungan pada mesin js lama, Anda juga memiliki dukungan android libs untuk sdk yang lebih tua dll.
svarog
@svarog: Apakah Anda memikirkan "polyfill" yang mengemulasi fungsionalitas dalam standar baru untuk mesin lama yang tidak mendukungnya secara asli? Saya tidak melihat alasan untuk menulis ini sendiri, karena ada perpustakaan open-source terkenal tersedia untuk tujuan ini.
JacquesB
0

Sebagian besar perpustakaan yang dibagi di seluruh tim menyebabkan lebih banyak masalah daripada yang mereka pecahkan. "Jalan menuju neraka ditaburi dengan niat baik."

Pengecualian adalah perpustakaan yang memenuhi sebagian besar di bawah ini:

  • Memiliki dana perawatan jangka panjang yang aman
  • Memiliki tim / komunitas pendukung yang berdedikasi
  • Memiliki bugtracker
  • Memiliki cakupan tes yang luas
  • Memiliki satu tujuan yang jelas
  • Tidak memiliki dependensi sendiri (baik di build dan runtime), selain dari perpustakaan standar atau kuasi-standar
  • Memiliki perbedaan bersih antara api publik dan internal
  • Memiliki saluran komunikasi dan proses untuk semua / banyak pengguna untuk menyetujui fitur dan rilis baru

Di dalam perusahaan (non-startup) yang khas, hampir tidak ada kondisi di atas yang tersedia untuk perpustakaan yang dibagikan di seluruh tim. Itu karena sebagian besar tim perusahaan dibayar untuk mengirimkan produk, bukan perpustakaan. Beberapa perusahaan memang memiliki strategi berbagi yang sukses, seperti Google monorepo, tetapi ini datang dengan investasi yang sangat tinggi dalam membangun dan menguji infrastruktur.

tkruse
sumber