Sepuluh Chapter belakangan melengkapi kotak peralatan kita: deklarasi method, parameter, return value, overloading, varargs, rekursi, kepemilikan static/instance, cakupan, hingga kemurnian. Peralatan itu baru benar-benar terasa nilainya ketika dipakai untuk pekerjaan yang sama tiap hari: merombak kode yang sudah bekerja namun susah dibaca menjadi susunan method yang rapi — tanpa mengubah perilakunya sedikit pun. Latihan semacam ini dinamai refactoring: menyusun ulang struktur internal program sambil menjaga perilaku eksternalnya tetap identik. Pada Chapter penutup ini kita ambil satu program laporan nilai yang monolitik, bedah gejalanya, lalu rombak bertahap menjadi method-method kecil yang masing-masing fokus pada satu tanggung jawab.
Studi Kasus Program Monolitik #
Berikut program laporan nilai yang seluruh logikanya ditumpuk di dalam main. Program ini bekerja benar — dan justru karena bekerja benar, struktur yang tidak teratur ini sering dibiarkan tumbuh:
public class LaporanMonolitik {
public static void main(String[] args) {
String[] nama = {"Budi", "Siti", "Dewi"};
int[] nilai = {78, 85, 92};
// Judul laporan
System.out.println("=== Laporan Nilai Ujian ===");
System.out.println("---------------------------");
// Rincian tiap siswa beserta statusnya
for (int i = 0; i < nilai.length; i++) {
String status;
if (nilai[i] >= 75) {
status = "LULUS";
} else {
status = "REMEDIAL";
}
System.out.println(nama[i] + " : " + nilai[i] + " (" + status + ")");
}
// Statistik: total, nilai tertinggi, rata-rata
int total = 0;
int tertinggi = nilai[0];
for (int i = 0; i < nilai.length; i++) {
total += nilai[i];
if (nilai[i] > tertinggi) {
tertinggi = nilai[i];
}
}
double rataRata = (double) total / nilai.length;
// Ringkasan akhir
System.out.println("---------------------------");
System.out.println("rata-rata : " + rataRata);
System.out.println("tertinggi : " + tertinggi);
}
}Output yang Dihasilkan:
=== Laporan Nilai Ujian ===
---------------------------
Budi : 78 (LULUS)
Siti : 85 (LULUS)
Dewi : 92 (LULUS)
---------------------------
rata-rata : 85.0
tertinggi : 92Gejalanya khas program monolitik. Pertama, main mengerjakan empat pekerjaan berbeda sekaligus: mencetak judul, menyusun rincian siswa, menghitung statistik, dan mencetak ringkasan — pembaca harus menelusuri seluruh badan main untuk tahu program berniat apa. Kedua, pengetahuan penting terkubur di tengah kode: ambang kelulusan 75 hanya hidup di dalam percabangan, rata-rata hanya hidup sebagai variabel setempat. Ketiga, tidak ada yang bisa diuji sendiri: membuktikan rataRata benar berarti menjalankan seluruh program dan membaca keluarannya.
Merombak Bertahap #
Refactoring yang aman berjalan satu langkah kecil tiap waktu, dan setiap langkah dituntut satu bukti: keluaran program tidak berubah. Kita mulai dari pertanyaan paling kecil yang terkubur — “berapa status sebuah nilai?” — lalu angkat menjadi method statusNilai. Pertanyaan berikutnya, “berapa rata-rata sekumpulan nilai?” menjadi hitungRataRata; “berapa nilai tertingginya?” menjadi nilaiTertinggi; pencetakan rincian menjadi cetakRincian; terakhir, main cukup mendelegasikan seluruh laporan ke cetakLaporan:
public class LaporanRapi {
// Method murni kecil: satu pertanyaan, satu jawaban
static String statusNilai(int nilai) {
return (nilai >= 75) ? "LULUS" : "REMEDIAL";
}
static double hitungRataRata(int[] nilai) {
int total = 0;
for (int n : nilai) {
total += n;
}
return (double) total / nilai.length;
}
static int nilaiTertinggi(int[] nilai) {
int tertinggi = nilai[0];
for (int n : nilai) {
if (n > tertinggi) {
tertinggi = n;
}
}
return tertinggi;
}
static void cetakRincian(String[] nama, int[] nilai) {
for (int i = 0; i < nilai.length; i++) {
System.out.println(nama[i] + " : " + nilai[i]
+ " (" + statusNilai(nilai[i]) + ")");
}
}
static void cetakLaporan(String[] nama, int[] nilai) {
System.out.println("=== Laporan Nilai Ujian ===");
System.out.println("---------------------------");
cetakRincian(nama, nilai);
System.out.println("---------------------------");
System.out.println("rata-rata : " + hitungRataRata(nilai));
System.out.println("tertinggi : " + nilaiTertinggi(nilai));
}
public static void main(String[] args) {
String[] nama = {"Budi", "Siti", "Dewi"};
int[] nilai = {78, 85, 92};
cetakLaporan(nama, nilai);
}
}Output yang Dihasilkan:
=== Laporan Nilai Ujian ===
---------------------------
Budi : 78 (LULUS)
Siti : 85 (LULUS)
Dewi : 92 (LULUS)
---------------------------
rata-rata : 85.0
tertinggi : 92Mari kita bedah hasil rombakannya:
- Baris 4-6 (
statusNilai): percabanganif-elseyang tadinya terkubur dalam perulangan kini menjadi method murni satu baris. Ambang75kini punya alamat resmi — siapa pun yang mencari makna nilai kelulusan mendarat di sini. - Baris 8-14 (
hitungRataRata) dan 16-24 (nilaiTertinggi): dua statistik menjadi method murni bertipe returndoubledanint. Keduanya hanya membaca parameter, sehingga dapat diuji terpisah — panggilhitungRataRatadengan{78, 85, 92}, bandingkan dengan85.0, selesai. - Baris 26-31 (
cetakRincian): efek samping pencetakan dikumpulkan di method satu tanggung jawab, dan baris 28-29 memanggilstatusNilai(nilai[i])— method kecil saling bekerja sama alih-alih logika digandakan. - Baris 33-40 (
cetakLaporan): method penyusun yang membaca seperti daftar isi — judul, rincian, garis, ringkasan. Struktur laporan kini terlihat dari nama pemanggilan, bukan dari urutanprintln. - Baris 42-46 (
main): menyusut menjadi tiga baris — siapkan data, minta laporan.mainkembali menjadi tempat orkestrasi, bukan tempat kerja.
Menjaga Perilaku Tetap Sama #
Perhatikan bahwa blok output kedua sama persis dengan blok pertama — baris demi baris, spasi demi spasi. Kesamaan itulah satu-satunya alat ukur keberhasilan refactoring pada program kita: pembaca laporan tidak boleh bisa membedakan versi monolitik dari versi rapi. Dalam praktik nyata, disiplin ini diperkuat dengan menjalankan kedua versi (atau rangkaian pengujian otomatis) sebelum dan sesudah setiap langkah rombakan; satu beda saja berarti langkah tadi mengubah perilaku dan perlu dikaji ulang.
Dengan ini perjalanan Section Method dan Modularitas tuntas: dari anatomi method pertama hingga merombak program nyata menjadi method yang fokus dan teruji. Keterampilan memecah program akan terus terpakai di seluruh Course — mulai dari mengelola kumpulan data pada Section Array dan String, hingga menyusun perilaku objek pada Object-Oriented Programming.
Referensi #
- dev.java: Belajar Java
- JLS SE25 §8.4: Method Declarations
- Java API: java.lang.Math (contoh method kecil yang fokus)
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
LaporanMonolitik.java
Unduh berkaspublic class LaporanMonolitik {
public static void main(String[] args) {
String[] nama = {"Budi", "Siti", "Dewi"};
int[] nilai = {78, 85, 92};
// Judul laporan
System.out.println("=== Laporan Nilai Ujian ===");
System.out.println("---------------------------");
// Rincian tiap siswa beserta statusnya
for (int i = 0; i < nilai.length; i++) {
String status;
if (nilai[i] >= 75) {
status = "LULUS";
} else {
status = "REMEDIAL";
}
System.out.println(nama[i] + " : " + nilai[i] + " (" + status + ")");
}
// Statistik: total, nilai tertinggi, rata-rata
int total = 0;
int tertinggi = nilai[0];
for (int i = 0; i < nilai.length; i++) {
total += nilai[i];
if (nilai[i] > tertinggi) {
tertinggi = nilai[i];
}
}
double rataRata = (double) total / nilai.length;
// Ringkasan akhir
System.out.println("---------------------------");
System.out.println("rata-rata : " + rataRata);
System.out.println("tertinggi : " + tertinggi);
}
}
LaporanRapi.java
Unduh berkaspublic class LaporanRapi {
// Method murni kecil: satu pertanyaan, satu jawaban
static String statusNilai(int nilai) {
return (nilai >= 75) ? "LULUS" : "REMEDIAL";
}
static double hitungRataRata(int[] nilai) {
int total = 0;
for (int n : nilai) {
total += n;
}
return (double) total / nilai.length;
}
static int nilaiTertinggi(int[] nilai) {
int tertinggi = nilai[0];
for (int n : nilai) {
if (n > tertinggi) {
tertinggi = n;
}
}
return tertinggi;
}
static void cetakRincian(String[] nama, int[] nilai) {
for (int i = 0; i < nilai.length; i++) {
System.out.println(nama[i] + " : " + nilai[i]
+ " (" + statusNilai(nilai[i]) + ")");
}
}
static void cetakLaporan(String[] nama, int[] nilai) {
System.out.println("=== Laporan Nilai Ujian ===");
System.out.println("---------------------------");
cetakRincian(nama, nilai);
System.out.println("---------------------------");
System.out.println("rata-rata : " + hitungRataRata(nilai));
System.out.println("tertinggi : " + nilaiTertinggi(nilai));
}
public static void main(String[] args) {
String[] nama = {"Budi", "Siti", "Dewi"};
int[] nilai = {78, 85, 92};
cetakLaporan(nama, nilai);
}
}