Halaman ini membahas definisi sistem build, fungsinya, alasan Anda harus menggunakan sistem build, dan alasan compiler dan skrip build bukan pilihan terbaik saat organisasi Anda mulai diskalakan. Ini ditujukan bagi developer yang tidak memiliki banyak pengalaman dengan sistem build.
Apa yang dimaksud dengan sistem build?
Pada dasarnya, semua sistem build memiliki tujuan yang sederhana: sistem ini mengubah kode sumber yang ditulis oleh engineer menjadi biner yang dapat dieksekusi yang dapat dibaca oleh mesin. Sistem build tidak hanya untuk kode yang ditulis manusia, tetapi juga memungkinkan mesin membuat build secara otomatis, baik untuk pengujian atau rilis hingga produksi. Dalam organisasi yang memiliki ribuan engineer, biasanya sebagian besar build dipicu secara otomatis, bukan langsung oleh engineer.
Tidak bisakah saya hanya menggunakan compiler?
Kebutuhan akan sistem build mungkin tidak
segera terlihat jelas. Sebagian besar engineer
tidak menggunakan sistem build saat belajar membuat kode: sebagian besar memulai dengan memanggil alat
seperti gcc
atau javac
langsung dari command line, atau yang setara di
lingkungan pengembangan terintegrasi (IDE). Selama semua kode sumber berada di
direktori yang sama, perintah seperti ini akan berfungsi dengan baik:
javac *.java
Tindakan ini akan menginstruksikan compiler Java untuk mengambil setiap file sumber Java di direktori saat ini dan mengubahnya menjadi file class biner. Dalam kasus paling sederhana, hanya inilah yang Anda butuhkan.
Namun, begitu kode diperluas, komplikasi akan dimulai. javac
cukup pintar
untuk mencari di subdirektori direktori saat ini guna menemukan kode yang
akan diimpor. Namun, tidak ada cara untuk menemukan kode yang disimpan di bagian lain
sistem file (mungkin library yang digunakan bersama oleh beberapa project). Anda juga hanya tahu cara
mem-build kode Java. Sistem besar sering kali melibatkan berbagai bagian yang ditulis dalam
berbagai bahasa pemrograman dengan jaringan dependensi di antara bagian tersebut,
yang berarti tidak ada compiler untuk satu bahasa yang dapat mem-build seluruh sistem.
Setelah Anda menangani kode dari beberapa bahasa atau beberapa unit kompilasi, proses build tidak lagi menjadi proses satu langkah. Sekarang Anda harus mengevaluasi apa saja yang menjadi dependensi kode Anda dan mem-build bagian-bagian tersebut dalam urutan yang tepat, mungkin menggunakan kumpulan alat yang berbeda untuk setiap bagian. Jika dependensi berubah, Anda harus mengulangi proses ini untuk menghindari ketergantungan pada biner yang sudah tidak berlaku. Untuk codebase dengan ukuran sedang, proses ini dengan cepat menjadi membosankan dan rentan error.
Compiler juga tidak mengetahui apa pun tentang cara menangani dependensi
eksternal, seperti file JAR
pihak ketiga di Java. Tanpa sistem build,
Anda dapat mengelolanya dengan mendownload dependensi dari internet, menyimpannya
di folder lib
di hard drive, dan mengonfigurasi compiler untuk membaca
library dari direktori tersebut. Seiring waktu, sulit untuk mempertahankan
update, versi, dan sumber dependensi eksternal ini.
Bagaimana dengan skrip shell?
Misalkan project hobi Anda dimulai cukup sederhana sehingga Anda dapat mem-build-nya hanya menggunakan compiler, tetapi Anda mulai mengalami beberapa masalah yang dijelaskan sebelumnya. Mungkin Anda masih tidak merasa memerlukan sistem build dan dapat mengotomatiskan bagian-bagian yang membosankan menggunakan beberapa skrip shell sederhana yang menangani build dalam urutan yang benar. Hal ini membantu untuk sementara waktu, tetapi segera Anda mulai mengalami lebih banyak masalah:
Hal ini menjadi merepotkan. Ketika sistem Anda berkembang menjadi lebih kompleks, Anda mulai menghabiskan banyak waktu untuk mengerjakan skrip build seperti pada kode sebenarnya. Proses debug skrip shell sangat merepotkan, dengan semakin banyak hack yang ditumpuk satu sama lain.
Prosesnya lambat. Untuk memastikan Anda tidak mengandalkan library yang sudah tidak berlaku secara tidak sengaja, Anda harus mengatur agar skrip build mem-build setiap dependensi secara berurutan setiap kali Anda menjalankannya. Anda mempertimbangkan untuk menambahkan beberapa logika untuk mendeteksi bagian mana yang perlu dibuat ulang, tetapi kedengarannya sangat rumit dan rentan error untuk suatu skrip. Atau, Anda berpikir untuk menentukan bagian mana yang perlu di-build ulang setiap kali, tetapi Anda kembali ke awal.
Kabar baik: sekarang waktunya merilis. Sebaiknya cari tahu semua argumen yang perlu Anda teruskan ke perintah jar untuk membuat build akhir. Dan ingat cara menguploadnya dan mengirimkannya ke repositori pusat. Kemudian, build dan dorong update dokumentasi, serta kirim notifikasi kepada pengguna. Hmm, mungkin ini membutuhkan skrip lain...
Bencana! Hard drive Anda mengalami error, dan sekarang Anda perlu membuat ulang seluruh sistem. Anda cukup pintar untuk menyimpan semua file sumber di kontrol versi, tetapi bagaimana dengan library yang Anda download? Dapatkah Anda menemukannya lagi dan memastikan versinya sama seperti saat pertama kali mendownloadnya? Skrip Anda mungkin bergantung pada alat tertentu yang diinstal di tempat tertentu—dapatkah Anda memulihkan lingkungan yang sama sehingga skrip berfungsi kembali? Bagaimana dengan semua variabel lingkungan yang Anda tetapkan jauh-jauh hari agar compiler berfungsi dengan baik, lalu Anda lupa?
Meskipun ada masalah, project Anda cukup berhasil sehingga Anda dapat mulai mempekerjakan lebih banyak engineer. Sekarang Anda menyadari bahwa tidak perlu terjadi bencana agar masalah sebelumnya muncul—Anda harus melalui proses bootstraping yang merepotkan yang sama setiap kali developer baru bergabung dengan tim Anda. Meskipun sudah berupaya sebaik mungkin, masih ada perbedaan kecil pada sistem setiap orang. Sering kali, hal yang berfungsi di komputer satu orang tidak berfungsi di komputer orang lain, dan setiap kali diperlukan waktu beberapa jam untuk men-debug jalur alat atau versi library untuk mengetahui perbedaannya.
Anda memutuskan bahwa Anda perlu mengotomatiskan sistem build. Secara teori, hal ini sesederhana mendapatkan komputer baru dan menyiapkannya untuk menjalankan skrip build setiap malam menggunakan cron. Anda masih harus melalui proses penyiapan yang merepotkan, tetapi sekarang Anda tidak memiliki manfaat otak manusia yang dapat mendeteksi dan menyelesaikan masalah kecil. Sekarang, setiap pagi saat Anda datang, Anda melihat bahwa build tadi malam gagal karena kemarin developer membuat perubahan yang berfungsi di sistem mereka, tetapi tidak berfungsi di sistem build otomatis. Setiap kali terjadi, Anda dapat memperbaikinya dengan mudah, tetapi hal ini sering terjadi sehingga Anda harus menghabiskan banyak waktu setiap hari untuk menemukan dan menerapkan perbaikan sederhana ini.
Build menjadi lebih lambat dan lebih lambat seiring pertumbuhan project. Suatu hari, sambil menunggu build selesai, Anda menatap dengan sedih desktop rekan kerja yang tidak ada aktivitasnya, yang sedang berlibur, dan berharap ada cara untuk memanfaatkan semua daya komputasi yang terbuang sia-sia.
Anda mengalami masalah skala klasik. Untuk satu developer yang mengerjakan maksimal beberapa ratus baris kode selama maksimal satu atau dua minggu (yang mungkin merupakan seluruh pengalaman sejauh ini dari developer junior yang baru saja lulus universitas), compiler adalah satu-satunya yang Anda butuhkan. Skrip mungkin dapat membawa Anda sedikit lebih jauh. Namun, begitu Anda perlu berkoordinasi di beberapa developer dan komputer mereka, bahkan skrip build yang sempurna pun tidak cukup karena menjadi sangat sulit untuk memperhitungkan perbedaan kecil di komputer tersebut. Pada tahap ini, pendekatan sederhana ini akan gagal dan saatnya berinvestasi dalam sistem build yang sebenarnya.