Mengapa mengembangkan perpustakaan internal untuk aplikasi internal?

10

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.

Andrew Murtagh
sumber
Kemungkinan rangkap dari Memecah satu proyek menjadi perpustakaan
agas

Jawaban:

25

Ada banyak alasan untuk membuat perpustakaan & perpustakaan bersama, (dalam file .dll atau .so) bahkan untuk penggunaan internal:

  1. Penggunaan Kembali di seluruh proyek jauh lebih bersih
  2. Pemisahan tanggung jawab - bagian dari kode Anda mungkin lebih cocok untuk pengembang atau tim yang berbeda
  3. Anda bisa mendapat manfaat dari peningkatan di perpustakaan yang dibuat tim lain tanpa harus menemukan kode spesifik
  4. Waktu pembangunan lebih cepat, jika perpustakaan stabil tidak perlu membangun kembali.
  5. Ruang Disk - Anda hanya dapat memiliki perpustakaan dan header di proyek
  6. Jika Anda menggunakan pustaka bersama, Anda dapat menghemat memori hanya dengan satu salinan dimuat ke dalam RAM meskipun beberapa program menggunakannya
  7. Anda biasanya berakhir dengan dokumentasi dan pengujian perpustakaan yang lebih baik
  8. Desain dan kode yang lebih bersih - berpikir tentang penataan hal-hal menjadi perpustakaan harus menghasilkan kelompok fungsionalitas terkait di setiap perpustakaan dan Anda cenderung memisahkan kode generik, ke perpustakaan , dari spesifik aplikasi, dalam aplikasi .
  9. Jika Anda memiliki algoritme kepemilikan di perpustakaan, Anda dapat membatasi akses ke sumbernya, mis. Tidak mengizinkan kontraktor atau tim yang bersumber dari luar untuk mendapatkan sumbernya.
  10. Kode perpustakaan dapat ditempatkan di bawah lisensi yang berbeda untuk Aplikasi yang pada awalnya ditulis sebagai bagian dari, beberapa perusahaan bahkan telah dikenal oleh perpustakaan Open Source yang mereka banggakan - mendapatkan pujian utama dalam komunitas Open Source dan terkadang peningkatan besar berkontribusi kembali.

Beberapa perusahaan bahkan memiliki praktik akuntansi di mana proyek yang membuat perpustakaan mendapatkan penggantian biaya pada setiap penggunaan ulang.

Steve Barnes
sumber
1
Atau dalam variasi poin 9, Anda bisa merilis perpustakaan di bawah lisensi yang berbeda dari kode aplikasi utama.
Michael Borgwardt
@MichaelBorgwardt - Poin baik yang mendorong poin 10 di atas.
Steve Barnes
Selain itu, memiliki beberapa kode sebagai pustaka terpisah membantu menghindari pintasan saat pemrograman, seperti "Saya hanya akan menambahkan parameter tambahan ini di sini .." dan membantu menemukan cara yang lebih baik untuk mengimplementasikan fitur yang diperlukan.
Valdas
11

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 .

Ben Cottrell
sumber
3
@ downvoter - dapatkah Anda menjelaskan alasan downvote? Umpan balik tentang jawaban berguna untuk meningkatkan kualitas situs ini untuk semua orang.
Ben Cottrell
4

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).

Doc Brown
sumber
Memang benar yang saya maksud perpustakaan kode sumber yang umum untuk beberapa proyek di mana Anda hanya mereferensikan file yang Anda butuhkan melalui petunjuk #include - saya tidak tahu istilah untuk itu sampai Anda mengatakannya dan saya akan mengedit pertanyaan sekarang. Jawaban tertaut Anda juga sangat membantu.
Andrew Murtagh
@AndrewMurtagh: fakta bahwa Anda begitu cepat menerima jawaban MichaelBorgwardt membuat saya heran, karena apa yang ditulisnya kelihatannya merupakan kesalahpahaman tentang dia atau milik saya.
Doc Brown
baik dia mengklarifikasi kebingungan awal yang saya miliki tentang kapan untuk mengelompokkan kode yang akan umum untuk beberapa proyek menjadi satu paket (apakah itu di perpustakaan biner atau perpustakaan kode sumber) tetapi diberikan, saya berbicara tentang memiliki direktori sumber tunggal kode yang dapat dibagikan di seluruh proyek dan tidak menyalin dan menempelkan setiap file ke setiap proyek karena saya mungkin membutuhkannya.
Andrew Murtagh
2

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:

  1. Waktu / energi yang dihabiskan untuk mempertimbangkan kasus penggunaan "umum"
  2. Waktu yang dihabiskan untuk membuat "perpustakaan" dapat didistribusikan ke "klien" Anda (kode Anda sendiri)
  3. Tekanan di masa depan untuk memanfaatkan "perpustakaan" bahkan jika itu tidak sepenuhnya cocok dengan use case berikutnya

Aturan umum saya adalah: jangan membuat kode menjadi pustaka kecuali saya memiliki setidaknya 2 tempat terpisah di mana kode dibutuhkan.

Sam
sumber
2
Saya telah melihat alasan yang hampir sama persis digunakan oleh beberapa pengembang mengapa kode mereka semua dalam satu file sumber baris> 20k. Ketika dikombinasikan dengan penamaan yang unik dan komentar yang buruk Anda segera memiliki kode yang lebih cepat ditulis ulang daripada dipelihara.
Steve Barnes
Poin bagus: Saya tentu saja tidak membantah penulisan kode yang dapat dikelola dan dibaca. File yang terpisah, metode / kelas yang disebutkan dengan baik, dan struktur paket adalah komponen penting dari perawatan. Maksud saya adalah bahwa biaya penulisan + distribusi perpustakaan sangat mahal bila hanya ada satu use case untuk "library".
Sam
1
Sebaliknya saya tidak berpendapat bahwa Anda perlu mengemas dan mendistribusikan pustaka dalam setiap kasus, hanya saja penulisan dan penataan seolah-olah kode Anda suatu hari nanti menjadi pustaka biasanya bernilai sedikit usaha dan sering membayar dividen walaupun kode tersebut tidak pernah menjadi didistribusikan sebagai perpustakaan.
Steve Barnes
1

mengapa perpustakaan internal harus dikembangkan hanya untuk dihubungkan ke aplikasi internal ketika saya memiliki akses ke header dan file implementasi dan bisa memasukkannya ke dalam pohon sumber saya dan mengkompilasinya bersama-sama?

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?

Michael Borgwardt
sumber
1
Jadi seperti yang saya mengerti, alasan utama untuk membuat beberapa kode menjadi perpustakaan adalah ketika akan digunakan di proyek yang berbeda (bahkan jika mereka semua dikembangkan secara internal) agar kode tersebut tidak dapat diduplikasi, diperbarui, dipelihara terpisah? Dan jika Anda hanya akan mengembangkan proyek tunggal maka tidak perlu membuat sesuatu menjadi perpustakaan (kecuali jika Anda bermaksud menggunakannya dalam proyek lebih lanjut di kemudian hari).
Andrew Murtagh
@AndrewMurtagh: Ya, persis seperti itulah saya katakan. Meskipun mungkin ada alasan teknis juga; Saya tidak begitu akrab dengan pengembangan C / C ++ - mungkin menjaga bagian dari kode sebagai perpustakaan diperlukan sehingga dapat dimuat secara opsional atau bahkan dimuat dan dibongkar sesuai permintaan, dan dengan demikian mengurangi penggunaan memori ketika fuctionality tidak diperlukan?
Michael Borgwardt
Saya percaya itu dimungkinkan melalui perpustakaan bersama. Terima kasih telah menjelaskan, saya akan menandai jawaban Anda sebagai diterima.
Andrew Murtagh
Hampir setiap VCS selama dekade terakhir mendukung referensi atau submodula eksternal. Ini menghapus kode duplikat dan masalah perbaikan bug. Mungkin menyertakan lebih banyak informasi tentang mengapa ini bukan solusi yang layak jika Anda masih percaya itu masalah yang valid.
Sirisian
Pikirkan juga dalam pemeliharaan. 1) Lib dapat dipertahankan secara independen dan paralel. 2) Apakah kode mudah diganti. 3) Basis kode kecil lebih mudah dikelola untuk tim kecil dan lebih mudah dipahami untuk semua orang. 4) jika waktu-ke-pasar sangat penting, Anda akan lebih memilih untuk membangun lebih cepat. Kode dalam lib adalah kode yang tidak Anda kompilasi berulang-ulang di dalam pipeline (IMO). 5) Ini kode yang dapat digunakan kembali yang dapat diandalkan ... Anda membuatnya ;-)
Laiv
1

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" Ayang digunakan oleh aplikasi dan unit tester. Setiap kali Anda menambahkan cpp A, 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 jika Bberalih menggunakan perpustakaan lain? Anda harus menghapus cpps dari Adalam semua proyek hanya bergantung pada B.

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.

benar-benar
sumber
0

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?

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).

Phill W.
sumber