Ketika saya baru-baru ini bekerja di sebuah perusahaan besar, saya perhatikan bahwa para programmer di sana mengikuti gaya pengkodean ini:
Misalkan saya memiliki fungsi yang mengembalikan 12 jika inputnya adalah A, 21 jika inputnya adalah B, dan 45 jika inputnya adalah C.
Jadi saya bisa menulis fungsi tanda tangan sebagai:
int foo(String s){
if(s.equals("A")) return 12;
else if(s.equals("B")) return 21;
else if(s.equals("C")) return 45;
else throw new RuntimeException("Invalid input to function foo");
}
Tetapi pada ulasan kode saya diminta untuk mengubah fungsi sebagai berikut:
int foo(String s){
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("A", 12);
map.put("B", 21);
map.put("C", 45);
return map.get(s);
}
Saya tidak bisa meyakinkan diri sendiri mengapa kode kedua lebih baik dari yang pertama. Kode kedua pasti akan membutuhkan lebih banyak waktu untuk dijalankan.
Satu-satunya alasan untuk menggunakan kode kedua adalah karena ia menawarkan keterbacaan yang lebih baik. Tetapi jika fungsi dipanggil berkali-kali maka bukankah fungsi kedua memperlambat waktu menjalankan utilitas menyebutnya?
Apa yang Anda pikirkan tentang ini?
sumber
switch
sepertinya lebih tepat daripadaif-else
). Tetapi pada titik tertentu, itu menjadi bermasalah. Keuntungan utama menggunakan Peta adalah Anda dapat memuatnya dari file atau tabel, dll. Jika Anda mengkodekan input ke peta, saya tidak melihat banyak nilai di atas sakelar.Jawaban:
Intinya adalah untuk memindahkan pembuatan hashmap di luar fungsi dan melakukannya sekali (atau hanya kurang dari kali).
Namun java sejak java7 dapat memiliki string (final) di switch:
sumber
Dalam contoh kedua Anda,
Map
harus menjadi anggota statis pribadi untuk menghindari overhead inisialisasi berlebihan.Untuk sejumlah besar nilai, peta akan berkinerja lebih baik. Dengan menggunakan hashtable, seseorang dapat mencari jawabannya dalam waktu yang konstan. Konstruk multi-jika harus membandingkan input ke setiap kemungkinan hingga menemukan jawaban yang tepat.
Dengan kata lain, pencarian peta adalah O (1) sedangkan
if
s adalah O (n) dengan n adalah jumlah input yang mungkin.Pembuatan peta adalah O (n), tetapi hanya dilakukan sekali jika keadaan konstan statis. Untuk pencarian yang sering dilakukan, peta akan mengungguli
if
pernyataan dalam jangka panjang, dengan biaya sedikit lebih banyak saat program dijalankan (atau kelas dimuat, tergantung pada bahasa).Karena itu, peta tidak selalu merupakan alat yang tepat untuk pekerjaan ini. Sangat menyenangkan ketika ada banyak nilai, atau nilai-nilai harus dapat dikonfigurasi melalui file teks, input pengguna, atau database (dalam hal ini peta bertindak sebagai cache).
sumber
Ada dua kecepatan dalam perangkat lunak: waktu yang diperlukan untuk menulis / membaca / men-debug kode; dan waktu yang diperlukan untuk menjalankan kode.
Jika Anda dapat meyakinkan saya (dan pengulas kode Anda) bahwa fungsi hashmap memang lebih lambat daripada if / then / else (setelah refactoring untuk membuat hashmap statis) DAN Anda dapat meyakinkan saya / pengulas bahwa diperlukan waktu yang cukup untuk membuat aktual perbedaan, lalu pergi dan ganti hashmap dengan if / else.
Kalau tidak, kode hash jelas dapat dibaca; dan (mungkin) bugfree; Anda dapat menentukan itu dengan cepat hanya dengan melihatnya. Anda tidak bisa mengatakan hal yang sama tentang if / else tanpa benar-benar mempelajarinya; perbedaannya bahkan lebih besar ketika ada ratusan opsi.
sumber
Saya sangat suka jawaban gaya HashMap.
Ada metrik untuk ini
Ada metrik kualitas kode yang disebut Kompleksitas Siklomatik . Metrik ini pada dasarnya menghitung jumlah lintasan yang berbeda melalui kode ( cara menghitung Kompleksitas Cyclomatik ).
Untuk setiap jalur eksekusi yang mungkin, metode menjadi semakin sulit untuk dipahami DAN sepenuhnya diuji kebenarannya.
Itu bermuara pada fakta bahwa "mengendalikan kata kunci" seperti: jika, elses, whiles, dll ... meningkatkan tes boolean yang bisa salah. Penggunaan berulang "mengendalikan kata kunci" menghasilkan kode yang rapuh.
Keuntungan tambahan
Juga, "pendekatan berbasis peta" mendorong pengembang untuk memikirkan pasangan input-output sebagai dataset yang dapat diekstraksi, digunakan kembali, dimanipulasi saat runtime, diuji, dan diverifikasi. Misalnya, di bawah ini saya menulis ulang "foo" sehingga kami tidak terkunci secara permanen ke "A-> 12, B-> 21, C-> 45":
rachet_freak menyebutkan jenis refactor ini dalam jawabannya, ia berpendapat untuk kecepatan dan penggunaan kembali, saya berpendapat untuk fleksibilitas runtime (walaupun menggunakan koleksi abadi dapat memiliki manfaat besar tergantung pada situasi)
sumber
Data lebih baik daripada kode. Paling tidak karena terlalu menggoda untuk menambahkan cabang lain ke kode, namun menambahkan baris ke tabel sulit untuk salah. Pertanyaan ini adalah contoh kecil dari ini. Anda sedang menulis tabel pencarian. Entah menulis implementasi, lengkap dengan logika kondisional dan dokumentasi, atau tulis tabel keluar kemudian cari di dalamnya.
Sebuah tabel data selalu merupakan representasi yang lebih baik dari beberapa data daripada kode, optimasi modulo berlalu. Betapa sulitnya tabel untuk diekspresikan mungkin bergantung pada bahasa - Saya tidak tahu Java, tetapi saya berharap Java dapat mengimplementasikan tabel look up lebih sederhana daripada contoh dalam OP.
Ini adalah tabel pencarian dengan python. Jika ini dipandang sebagai konflik yang mengundang, harap pertimbangkan bahwa pertanyaannya bukan tagged java, refactoring adalah agnostik bahasa dan kebanyakan orang tidak tahu java.
Gagasan merestrukturisasi kode untuk mengurangi runtime memiliki manfaat, tetapi saya lebih suka menggunakan kompiler yang mengerek pengaturan umum daripada melakukannya sendiri.
sumber