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 itu 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 bagian berbeda yang ditulis dalam
berbagai bahasa pemrograman dengan web dependensi di antara bagian-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, pembuatan kode tidak lagi memerlukan proses satu langkah. Sekarang Anda harus mengevaluasi apa yang menjadi dependensi kode Anda dan mem-build bagian-bagian tersebut dalam urutan yang tepat, mungkin menggunakan rangkaian 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 merasa tidak memerlukan sistem build dan dapat mengotomatiskan bagian yang membosankan menggunakan beberapa skrip shell sederhana yang menangani pembuatan dalam urutan yang benar. Hal ini membantu untuk sementara, tetapi tidak lama lagi Anda akan mulai mengalami lebih banyak masalah:
Hal ini menjadi merepotkan. Seiring sistem menjadi lebih kompleks, Anda mulai menghabiskan hampir sama banyak waktu untuk mengerjakan skrip build seperti kode sebenarnya. Proses debug skrip shell sangat merepotkan, dengan semakin banyak peretasan yang diterapkan di atas satu sama lain.
Ini terlalu pelan. Untuk memastikan Anda tidak sengaja mengandalkan library yang sudah tidak berlaku, Anda harus membuat skrip build membuat setiap dependensi secara berurutan setiap kali 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 dibuat ulang setiap saat, tetapi Anda kembali ke tahap awal.
Kabar baik: kini saatnya merilis laporan! Sebaiknya cari tahu semua argumen yang perlu Anda teruskan ke perintah jar untuk membuat build akhir. Dan ingat cara menguploadnya dan mengirimnya ke repositori pusat. Kemudian, buat dan kirim pembaruan dokumentasi, serta kirimkan 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 menemukan semuanya lagi dan memastikan semuanya sama dengan versi saat Anda 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. Dan meskipun Anda sudah berupaya sebaik mungkin, masih ada perbedaan kecil di sistem setiap orang. Sering kali, apa yang berfungsi di komputer seseorang tidak berfungsi di komputer orang lain, dan setiap kali dibutuhkan beberapa jam untuk men-debug jalur alat atau versi library untuk mencari tahu apa 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 menyakitkan, tetapi sekarang Anda tidak diuntungkan karena otak manusia dapat mendeteksi dan menyelesaikan masalah kecil. Sekarang, setiap pagi saat Anda masuk, Anda melihat bahwa build tadi malam gagal karena kemarin developer melakukan perubahan yang berfungsi pada sistem mereka tetapi tidak berfungsi pada sistem build otomatis. Setiap kali perbaikannya sederhana, tetapi sering terjadi sehingga Anda akhirnya menghabiskan banyak waktu setiap hari untuk menemukan dan menerapkan perbaikan sederhana ini.
Build menjadi lebih lambat dan lebih lambat seiring pertumbuhan project. Suatu hari, selagi menunggu build selesai, Anda menatap desktop rekan kerja Anda yang sedang tidak aktif, 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.