Satu keputusan menentukan arah pengerjaan proyek di jalur ini, yaitu bentuk proyek yang dipilih sebelum baris pertama kodenya ditulis. Topik ini menimbang tiga bentuk yang seluruh tekniknya sudah dicakup sepanjang jalur, yakni plugin build Gradle, Shared Library Jenkins, dan otomasi CLI (command line interface) berbasis picocli. Penimbangannya memakai lima kriteria, matriks perbandingan, serta skor berbobot yang dihitung oleh skrip Groovy kecil sehingga setiap angkanya dapat dihitung ulang. Hasil akhirnya berupa rekomendasi default yang jujur beserta syarat yang membuatnya perlu digeser.
Tiga bentuk proyek akhir#
Ketiga bentuk proyek memakai bahasa yang sama, sehingga pembedanya bukan pada bahasanya, melainkan pada tempat kode itu hidup dan cara sampai ke tangan penggunanya. Plugin build Gradle adalah kode Groovy yang dikemas menjadi jar dan dimuat oleh build.gradle untuk menambahkan task atau konvensi baru pada build proyek. Kode itu hidup di dalam siklus build, penggunanya adalah semua orang yang membangun proyek yang memakai plugin tersebut, dan distribusinya menuntut publikasi ke Gradle Plugin Portal atau repository internal.
Shared Library Jenkins adalah repository Groovy berisi folder src untuk kelas dan folder vars untuk langkah global, dan alamatnya didaftarkan di Jenkins agar dapat dimuat oleh pipeline mana pun. Kode itu hidup di server Jenkins, dipakai tim yang menulis Jenkinsfile setiap hari, dan dieksekusi melalui transformasi CPS sehingga pengujian lokalnya tidak sesederhana skrip Groovy biasa. Pemusatan kode bersama semacam ini menghindari penyalinan langkah yang sama ke banyak Jenkinsfile.
Otomasi CLI picocli adalah program berdiri sendiri yang dipanggil dari terminal, dibangun dari satu kelas beranotasi dengan dependensi yang diunduh sendiri melalui @Grab. Kode itu hidup di terminal penggunanya, baik manusia maupun server CI (continuous integration), yaitu mesin yang menjalankan pekerjaan otomatis semacam pengujian. Cukup JVM dan berkas skripnya, sehingga tidak ada aplikasi lain yang wajib terpasang di tempat programnya dijalankan.
Lima kriteria pemilihan#
Kriteria pertama adalah penggunanya. Alat untuk diri sendiri boleh sesederhana skrip tunggal, alat untuk tim perlu terpasang di tempat kerja tim, sedangkan alat untuk server CI harus dapat dipanggil tanpa antarmuka selain baris perintah. Kriteria kedua adalah cara distribusinya, karena skrip tunggal cukup disalin, jar harus dipublikasikan ke repository, plugin menuntut portal atau repository milik organisasi, dan Shared Library hanya membutuhkan alamat repository yang didaftarkan sekali.
Kriteria ketiga adalah kebutuhan pengujian. Bentuk yang logikanya murni dapat diuji Spock di sandbox tanpa aplikasi apa pun, sedangkan plugin memerlukan Gradle TestKit, yaitu perangkat uji resmi yang menjalankan build percobaan, dan langkah vars pada Shared Library baru teruji ketika pipeline benar-benar berjalan. Kriteria keempat adalah ketergantungan jaringan dan lingkungan, misalnya @Grab yang mengunduh jar dari Maven Central pada eksekusi pertama, versi Gradle yang harus cocok dengan plugin, dan instance Jenkins yang harus hidup. Kriteria kelima adalah daya tahan API, karena kelas yang dipakai plugin berubah antar versi Gradle, sedangkan anotasi picocli relatif stabil sehingga skrip lama tetap berjalan.
Skor berbobot dari lima kriteria#
Matriks kualitatif mudah dibaca tetapi sulit dibandingkan, sehingga lima kriteria tersebut diterjemahkan menjadi angka. Setiap kriteria diberi bobot yang menyatakan besar perhatiannya pada situasi yang sedang dianalisis, lalu setiap bentuk diberi nilai 1 sampai 5 per kriteria. Skor sebuah bentuk berupa jumlah hasil kali bobot dengan nilai kriterianya, sedangkan persentasenya dihitung terhadap skor maksimum, yakni bobot total dikali lima. Skrip berikut menghitung skor CLI picocli untuk satu situasi contoh, yaitu pengembang yang kebanyakan bekerja sendiri dengan server CI ringan.
// mekanisme skor berbobot: setiap kriteria menyumbang bobot x nilai
def bobot = [pengguna: 3, distribusi: 2, pengujian: 2, lingkungan: 2, dayaTahan: 1]
def nilaiCli = [pengguna: 5, distribusi: 4, pengujian: 5, lingkungan: 4, dayaTahan: 4]
int skorMaks = bobot.values().sum() * 5
int skor = bobot.collect { k, w -> w * nilaiCli[k] }.sum()
println "Bobot total : ${bobot.values().sum()}"
println "Skor CLI : ${skor} dari maksimum ${skorMaks}"
printf('Persentase : %.1f%%%n', skor / skorMaks * 100)Bobot total : 10
Skor CLI : 45 dari maksimum 50
Persentase : 90.0%Bobot totalnya 10 dan skornya 45, yang berarti 90.0 persen dari skor maksimum. Angka itu bukan penilaian mutlak atas CLI, melainkan konsekuensi langsung dari bobot yang dipilih, yaitu pengujian dan lingkungan yang dinilai penting pada situasi belajar di sandbox. Kriteria yang paling memengaruhi angka tersebut adalah pengujian dan lingkungan, karena keduanya menyumbang 18 dari 45 poin. Penjumlahan sederhana semacam ini juga mudah dipindahkan ke lembar kerja apa pun ketika situasi yang dianalisis bukan lagi situasi contoh. Mengubah satu bobot saja sudah cukup untuk menggeser skor akhir, dan pergeseran yang lebih dramatis terjadi pada tabel keputusan di bagian berikutnya.
Matriks dan tabel keputusan#
Tabel berikut membandingkan ketiga bentuk secara kualitatif sebelum perbandingan angkanya disusun.
| Bentuk | Distribusi | Pengguna utama | Kebutuhan pengujian | Contoh kasus cocok |
|---|---|---|---|---|
| Plugin build Gradle | jar ke Gradle Plugin Portal atau repository internal | semua orang yang membangun proyek yang memakainya | Gradle TestKit dengan proyek build percobaan | membakukan langkah build dan pemeriksaan kualitas untuk banyak proyek sekaligus |
| Shared Library Jenkins | repository yang alamatnya didaftarkan di Jenkins | tim yang menulis Jenkinsfile setiap hari | kelas di src diuji Spock, langkah di vars teruji saat pipeline berjalan | tahap uji dan arsip yang sama dipakai puluhan pipeline milik satu tim |
| CLI picocli | skrip tunggal dengan @Grab atau jar yang disalin | manusia di terminal dan server CI | logika murni diuji Spock di sandbox tanpa aplikasi lain | alat rekap statistik nilai ujian yang dipanggil dari terminal maupun CI |
Skrip berikut melengkapi matriks tersebut dengan angka pada dua situasi berbeda. Situasi pertama memakai bobot pada bagian sebelumnya, yaitu pengembang tunggal dengan CI ringan. Situasi kedua memperkenalkan bobot baru yang menonjolkan pengguna dan distribusi, karena anggota tim memakai Jenkins setiap hari dan uji kodenya berjalan di Jenkins sendiri.
// matriks-keputusan.groovy: tabel keputusan dari lima kriteria berbobot
// Bobot dan nilai 1-5 menggambarkan situasi yang dianalisis, bukan konstanta universal.
def bobotSolo = [
pengguna : 3, // siapa yang memakainya: diri sendiri, tim, atau server CI
distribusi: 2, // cara sampai ke pengguna: jar, repository, atau skrip tunggal
pengujian : 2, // kemudahan diuji di sandbox tanpa aplikasi tambahan
lingkungan: 2, // ketergantungan pada jaringan dan aplikasi eksternal
dayaTahan : 1, // kestabilan API yang dipakai antar versi
]
def bobotTimJenkins = [pengguna: 5, distribusi: 4, pengujian: 1, lingkungan: 1, dayaTahan: 1]
// nilai 1-5 untuk tiap bentuk, dinilai menurut masing-masing situasi
def situasiSolo = [
'Plugin build Gradle' : [pengguna: 3, distribusi: 2, pengujian: 3, lingkungan: 2, dayaTahan: 2],
'Shared Library Jenkins': [pengguna: 4, distribusi: 3, pengujian: 2, lingkungan: 1, dayaTahan: 3],
'CLI picocli' : [pengguna: 5, distribusi: 4, pengujian: 5, lingkungan: 4, dayaTahan: 4],
]
def situasiTimJenkins = [
'Plugin build Gradle' : [pengguna: 3, distribusi: 2, pengujian: 3, lingkungan: 2, dayaTahan: 2],
'Shared Library Jenkins': [pengguna: 5, distribusi: 5, pengujian: 2, lingkungan: 1, dayaTahan: 3],
'CLI picocli' : [pengguna: 4, distribusi: 3, pengujian: 5, lingkungan: 4, dayaTahan: 4],
]
def cetakTabel = { String judul, Map situasi, Map bobot ->
int skorMaks = bobot.values().sum() * 5
def peringkat = situasi.collect { nama, nilai ->
[nama: nama, skor: bobot.collect { k, w -> w * nilai[k] }.sum()]
}.sort { -it.skor }
println "Situasi: ${judul}"
peringkat.each { p ->
printf('%-24s : %2d dari %2d (%.1f%%)%n', p.nama, p.skor, skorMaks, p.skor / skorMaks * 100)
}
printf('%-24s : %s%n', 'Skor tertinggi', peringkat[0].nama)
println()
}
cetakTabel('pengembang tunggal dengan CI ringan', situasiSolo, bobotSolo)
cetakTabel('tim yang memakai Jenkins setiap hari', situasiTimJenkins, bobotTimJenkins)Situasi: pengembang tunggal dengan CI ringan
CLI picocli : 45 dari 50 (90.0%)
Shared Library Jenkins : 27 dari 50 (54.0%)
Plugin build Gradle : 25 dari 50 (50.0%)
Skor tertinggi : CLI picocli
Situasi: tim yang memakai Jenkins setiap hari
Shared Library Jenkins : 51 dari 60 (85.0%)
CLI picocli : 45 dari 60 (75.0%)
Plugin build Gradle : 30 dari 60 (50.0%)
Skor tertinggi : Shared Library JenkinsKemenangannya berpindah antar situasi. CLI picocli unggul jauh pada situasi pertama dengan 90.0 persen, sedangkan Shared Library Jenkins menyusul ke puncak pada situasi kedua dengan 85.0 persen, mengalahkan CLI yang mendapat 75.0 persen. Perpindahan itu murni akibat bobot, karena nilai Shared Library pada kriteria pengguna dan distribusi memang tertinggi di antara ketiganya. Tabel keputusan dengan demikian tidak menjawab bentuk mana yang terbaik secara umum, melainkan bentuk mana yang terbaik untuk bobot yang diisikan, dan kejujuran analisis terletak pada kejujuran bobot tersebut.
Rekomendasi default dan proyek pemandu#
Rekomendasi default jalur ini adalah otomasi CLI picocli. Alasannya melekat pada isi jalur ini sendiri, karena seluruh teknik yang diperlukan sudah dicakup, mulai dari kelas perintah beranotasi picocli, pengunduhan dependensi lewat @Grab, hingga pengujian dengan Spock. CLI juga paling murah diuji karena logikanya berjalan di sandbox tanpa Jenkins maupun distribusi Gradle, sehingga dua kriteria berbobot besar pada situasi belajar, yaitu pengujian dan lingkungan, terpenuhi sekaligus. Rekomendasi itu berubah bila tim benar-benar memakai Jenkins setiap hari, sebab situasi kedua pada skrip menempatkan Shared Library Jenkins di puncak. Plugin build Gradle menjadi pilihan tepat ketika yang ingin dibakukan adalah langkah build proyek itu sendiri dan pola tersebut perlu dipakai banyak proyek.
Proyek pemandu jalur ini berupa satu CLI terpilih yang dirancang dan dibangun pada topik-topik lain dalam modul ini. Perancangannya dimulai dari tata bahasa DSL (domain-specific language) sebelum implementasi, kemudian pembangunannya berjalan bertahap dengan spesifikasi Spock sebagai checkpoint, yaitu titik pemeriksaan yang wajib lulus sebelum tahap berikutnya dimulai. Bentuk yang direkomendasikan pada topik ini menjadi payung bagi kedua tahap tersebut karena seluruh tekniknya telah tersedia.
Kesalahan umum#
Kesalahan pertama adalah memilih bentuk karena daya tariknya, bukan karena penggunanya. Plugin build yang ditulis untuk alat yang hanya dipakai dua kali setahun oleh satu orang menanggung biaya publikasi jar, penjagaan versi Gradle, dan penulisan TestKit, tanpa ada yang menuai manfaatnya. Perbaikannya berupa aturan sederhana, yaitu mulai dari bentuk paling ringan yang memenuhi kriteria, lalu naikkan bentuknya saat frekuensi pemakaian dan jumlah pengguna benar-benar menuntut.
Kesalahan kedua adalah berkomitmen pada bentuk yang lingkungannya tidak pernah dapat dicoba. Shared Library misalnya terlihat ringan karena cukup repository, tetapi perubahannya baru tampak ketika pipeline benar-benar berjalan di Jenkins.
Perbaikannya menempatkan logika murni pada folder src agar dapat diuji Spock tanpa Jenkins, atau memilih bentuk yang seluruh siklus ujinya berjalan di sandbox seperti CLI. Kriteria ketiga dan keempat pada bagian sebelumnya memang menimbang seberapa jauh siklus uji sebuah bentuk dapat berjalan tanpa aplikasi luar.
Ringkasan#
- Tiga bentuk proyek akhir jalur ini adalah plugin build Gradle, Shared Library Jenkins, dan otomasi CLI picocli, dengan pembeda utama pada tempat kode hidup dan cara distribusinya.
- Lima kriteria pemilihannya mencakup pengguna, cara distribusi, kebutuhan pengujian, ketergantungan jaringan dan lingkungan, serta daya tahan API.
- Skor berbobot mengubah kriteria menjadi angka yang dapat dihitung ulang, dan tabel keputusannya memperlihatkan pemenang yang berpindah mengikuti bobot, dari CLI picocli pada situasi pengembang tunggal menjadi Shared Library Jenkins pada tim pemakai Jenkins harian.
- Rekomendasi default jalur ini adalah CLI picocli, sedangkan proyek pemandu pada topik-topik lain modul ini merancang dan membangun satu CLI terpilih dengan DSL yang dirancang lebih dahulu serta checkpoint Spock.
Referensi#
- Understanding Plugins — Gradle — panduan resmi jenis-jenis plugin beserta pembuatan dan publikasi plugin build kustom.
- Extending with Shared Libraries — Jenkins — struktur folder src dan vars Shared Library beserta cara pemuatan dan pengujiannya.
- Dokumentasi picocli — picocli — manual anotasi picocli yang menjadi dasar bentuk CLI pada rekomendasi topik ini.