Saya mengalami kesulitan memahami mengapa Anda harus mengembangkan perpustakaan internal untuk digunakan secara eksklusif untuk mengembangkan aplikasi internal. Saya menghargai bahwa jika saya ingin menggunakan perangkat lunak yang ditulis oleh seseorang di luar organisasi maka mereka dapat mengirimkan saya file header dan file .a atau .so dan saya hanya dapat menautkannya ke proyek saya (dengan asumsi mereka dikompilasi dalam lingkungan yang sama) .
Tetapi mengapa perpustakaan internal harus dikembangkan hanya untuk dihubungkan ke aplikasi internal ketika saya memiliki akses ke header dan file implementasi dan dapat dengan mudah memasukkannya ke dalam pohon sumber saya dan mengkompilasinya bersama-sama?
Dengan kata lain: jika beberapa kode sumber ditulis, bagaimana Anda memutuskan apakah harus dikompilasi ke perpustakaan biner dan ditautkan ke aplikasi Anda atau hanya disertakan dalam file sumber proyek dan dikompilasi secara teratur?
Ketika saya mengatakan 'sertakan' file di setiap proyek, saya tidak bermaksud menyalin dan menempelkan setiap file ke dalam pohon sumber proyek yang sedang dikembangkan. Maksud saya mengembangkan beberapa direktori / perpustakaan (terpisah untuk proyek apa pun) yang berisi kode sumber umum yang dapat dimasukkan ke dalam file proyek dengan cara biasa, yaitu #include.
ps Saya berbicara tentang pengembangan c / c ++ di sini untuk beberapa aplikasi desktop.
Jawaban:
Ada banyak alasan untuk membuat perpustakaan & perpustakaan bersama, (dalam file .dll atau .so) bahkan untuk penggunaan internal:
Beberapa perusahaan bahkan memiliki praktik akuntansi di mana proyek yang membuat perpustakaan mendapatkan penggantian biaya pada setiap penggunaan ulang.
sumber
Beberapa kemungkinan alasan lain yang mungkin berlaku untuk proyek yang lebih besar dan tidak penting:
Waktu kompilasi: Proyek C ++ monolitik besar dengan ribuan file, ribuan kelas, fungsi, dll. Dapat membutuhkan waktu yang sangat lama untuk dikompilasi (yang mengganggu produktivitas jika Anda ingin mengkompilasi ulang setiap kali Anda mengubah beberapa baris kode). Pustaka yang tertaut secara statis dan tertaut secara dinamis dikompilasi secara independen dan tidak perlu dikompilasi ulang jika sumbernya tidak berubah.
Pemisahan logis dari modul atau subsistem yang berbeda : Sistem besar biasanya lebih mudah dikelola jika area fungsionalitas yang berbeda ditempatkan dalam modul terpisah, dan pengembang tidak dihadapkan dengan pencarian melalui folder / proyek besar yang berisi ribuan file / kelas.
Batas antara pengembang / tim : Pengembang membangun fungsionalitas baru yang terpisah pada saat yang sama dapat mengurangi potensi untuk menggabungkan konflik jika memungkinkan masing-masing pengembang bekerja dalam modul yang berbeda.
Kode yang tidak boleh dilepaskan ke lingkungan hidup : Misalnya, perpustakaan uji unit atau perpustakaan 'tiruan' yang digunakan untuk pengujian pengembang untuk menggantikan komponen sistem langsung (perangkat keras, API, sistem jarak jauh, basis data, dll.)
Bendera kompiler : Jika Anda berada dalam posisi yang sangat tidak menguntungkan untuk berintegrasi dengan API pihak ketiga yang mengharapkan bendera kompiler aneh, maka perpustakaan dapat menjadi "lapisan dekontaminasi" yang berada di antara API pihak ke-3 dan aplikasi lainnya.
Fitur opsional / Optimasi : Dalam sistem besar, aplikasi mungkin menunggu sebelum memuat modul tertentu yang terhubung secara dinamis ke dalam memori saat runtime jika mereka tidak kritis terhadap fungsionalitas dasar aplikasi.
Secara umum, banyak proyek internal seringkali merupakan aplikasi mikro kecil yang tidak diuntungkan karena dipecah menjadi perpustakaan yang terpisah. Jika Anda mengerjakan proyek kecil sebagai pengembang tunggal, maka Anda 'mungkin' tidak perlu khawatir memecah kode menjadi pustaka (belum ...). Jangan lupakan prinsip YAGNI .
sumber
Pertanyaan awal Anda mungkin telah menyebabkan kesalahpahaman di sini untuk sebagian besar jawaban lainnya. Karena Anda bermaksud untuk tidak menyalin kode yang ada di seluruh proyek, tetapi untuk memasukkan file sumber yang sama dari proyek yang berbeda sebagai referensi , argumen "kode duplikat" apa pun menjadi tidak ada artinya, serta banyak argumen lain yang disajikan.
Perhatikan bahwa ini kadang-kadang (- tidak selalu -) teknik yang masuk akal . Bahkan, ketika Anda meletakkan semua file sumber yang ingin Anda gunakan kembali di seluruh proyek ke dalam satu folder include terpisah, Anda sudah membangun perpustakaan juga - perpustakaan kode sumber, bukan biner lib. Khususnya di C ++, ketika membuat pustaka generik dengan templat, tidak jarang memiliki lib header-saja, yang hanya perlu menyertakan sederhana, dan tidak ada persiapan menghubungkan yang terpisah.
Jadi saya kira pertanyaan Anda yang sebenarnya adalah - kapan harus membangun lib kode sumber, atau kapan harus memilih lib biner yang dikompilasi sebelumnya? Dalam jawaban yang lebih lama di situs ini , saya membahas beberapa pro dan kontra dari lib hanya header, mungkin itu membantu Anda. Keuntungan utama lib kode sumber adalah, mereka tidak perlu dikompilasi dengan run-time yang sama dan / atau flag compiler / linker yang kompatibel seperti aplikasi yang menggunakannya. Kerugiannya adalah waktu kompilasi tambahan, dan persyaratan untuk menyediakan akses ke kode sumber (yang jelas bukan masalah untuk jenis proyek "internal" yang ada dalam pikiran Anda).
sumber
Saya setuju dengan komentator lain ketika mereka menulis bahwa Anda tidak boleh menggandakan kode. Namun, dalam kasus Anda, Anda (atau orang yang bekerja dengan Anda) membuat perpustakaan untuk kode yang tidak diduplikasi di tempat lain.
Dalam hal ini, saya memperingatkan terhadap generalisasi prematur . Sering ada saat-saat ketika seseorang merasa sepotong kode dapat digunakan kembali. Namun, tanpa mengetahui detail intim tentang bagaimana use case kedua akan menggunakan kode tersebut, sangat mudah untuk menghabiskan waktu ekstra pada fitur "reusability" yang sebenarnya tidak akan berguna dalam kasus-kasus tambahan atau untuk membuat asumsi yang terbukti salah dalam kasus kedua.
Menulis "perpustakaan" untuk satu kasus penggunaan dapat berubah menjadi latihan yang sangat mahal tanpa imbalan --- Saya telah digigit oleh ini beberapa kali.
Contoh biaya:
Aturan umum saya adalah: jangan membuat kode menjadi pustaka kecuali saya memiliki setidaknya 2 tempat terpisah di mana kode dibutuhkan.
sumber
Karena jika Anda "cukup sertakan di sumber saya", Anda menduplikasi kode .
Masalahnya adalah Anda tidak akan mendapat manfaat dari perbaikan apa pun (termasuk perbaikan bug penting) yang dibuat oleh proyek tempat Anda menyalin kode, juga tidak akan mendapat manfaat dari perbaikan apa pun yang Anda lakukan.
Anda mungkin berpikir bahwa Anda dapat menyelesaikan masalah ini dengan hanya menyalin versi terbaru dari kode ke pohon sumber Anda secara teratur, bahkan mungkin otomatis dengan menggunakan submodule di git atau yang serupa. Tapi kemudian Anda akan terus-menerus membuat kerusakan karena perubahan API yang tidak kompatibel. Perpustakaan di sisi lain memiliki API publik "resmi" yang diketahui pengembangnya tidak dapat diubah tanpa menyesuaikan dengan klien.
Akhirnya, mungkin ada alasan teknis - dapat menjaga bagian dari kode sebagai pustaka diperlukan sehingga dapat dimuat secara opsional atau bahkan dimuat dan dibongkar sesuai permintaan, dan dengan demikian mengurangi penggunaan memori ketika fungsi tidak diperlukan?
sumber
Saya ingin menguraikan biaya solusi Anda dalam jangka panjang.
Jelas, menambahkan perpustakaan ke proyek memiliki beberapa overhead, semua di atas jika itu yang pertama: alur kerja harus diubah, kadang-kadang bahkan infrastruktur dan beberapa anggota tim mungkin tidak menyukainya (pada awalnya). Jadi keuntungan dari solusi Anda jelas, karena membebankan biaya lebih sedikit sekarang .
Namun, seiring proyek Anda tumbuh juga biaya "pseudo-library" akan. Asumsikan Anda memiliki "pseudo-library"
A
yang digunakan oleh aplikasi dan unit tester. Setiap kali Anda menambahkan cppA
, Anda harus menambahkannya ke kedua proyek, jika tidak, mereka tidak akan ditautkan.Bagaimana jika "pseudo-library" Anda digunakan oleh "pseudo-library" lain
B
? Anda harus menambahkan cpp baru Anda di banyak proyek lainnya. Dan jikaB
beralih menggunakan perpustakaan lain? Anda harus menghapus cpps dariA
dalam semua proyek hanya bergantung padaB
.Ini semua akan gratis jika perpustakaan nyata akan digunakan. Jadi pertanyaannya adalah, berapa banyak cpps yang diperlukan untuk membenarkan pemindahan ke perpustakaan asli?
Tapi tunggu, ada lebih banyak jaminan: Pengembang tidak suka pekerjaan bodoh ini memburu semua proyek yang membutuhkan cpp baru dan akan menambahkan kode / kelasnya di suatu tempat ke dalam file yang sudah ada, yang bukan merupakan hal yang baik dalam jangka panjang.
Jadi menggunakan "pseudo-library" bisa menjadi langkah pertama untuk memecah proyek monolitik, tetapi Anda tidak harus menunggu terlalu lama untuk menjadikannya perpustakaan nyata untuk dapat menggunakan kelebihannya.
sumber
Jika perpustakaan hanya pernah digunakan oleh satu aplikasi maka Anda mungkin tidak membutuhkannya sebagai perpustakaan terpisah.
Jika perpustakaan digunakan oleh 3.500 aplikasi maka Anda benar - benar membutuhkannya sebagai perpustakaan terpisah.
Bagaimana jika ada bug di perpustakaan dan Anda perlu memperbaikinya? Atau ada perubahan hukum atau peraturan yang berarti Anda harus mengubah cara kerja perpustakaan?
Jika ada di pustaka yang terpisah, maka Anda dapat (berpotensi) memperbaiki pustaka, menguji kembali dan menyebarkannya kembali dan setiap aplikasi mendapat manfaat dari perbaikan tersebut.
Jika hanya dalam kode sumber yang "lokal" untuk setiap aplikasi, maka Anda harus mengubah, membangun kembali, menguji ulang, dan menggunakan kembali setiap aplikasi secara individual . Itu latihan yang jauh lebih besar (yaitu lebih mahal).
sumber