Saya punya beberapa kode yang memiliki urutan if
s yang berfungsi, tetapi hanya merasa berantakan. Pada dasarnya, saya ingin memilih yang terbesar dari tiga bilangan bulat dan menetapkan bendera status untuk mengatakan yang dipilih. Kode saya saat ini terlihat seperti ini:
a = countAs();
b = countBs();
c = countCs();
if (a > b && a > c)
status = MOSTLY_A;
else if (b > a && b > c)
status = MOSTLY_B;
else if (c > a && c > b)
status = MOSTLY_C;
else
status = DONT_KNOW;
Pola ini muncul beberapa kali, dan dengan nama variabel yang panjang akan sedikit sulit untuk memastikan secara visual bahwa masing-masing if
sudah benar. Saya merasa mungkin ada cara yang lebih baik dan lebih jelas untuk melakukan ini; adakah yang bisa menyarankan sesuatu?
Ada beberapa duplikat potensial, tetapi mereka tidak cukup sejalan dengan pertanyaan ini.
Dalam duplikat yang disarankan: Pendekatan untuk memeriksa berbagai kondisi? semua solusi yang disarankan tampak sama kikuknya dengan kode asli, sehingga tidak memberikan solusi yang lebih baik.
Dan posting ini cara-cara yang elegan untuk menangani jika (jika lain) hanya berurusan dengan tingkat dan asimetri bersarang, yang tidak menjadi masalah di sini.
sumber
Jawaban:
Memfaktorkan logika, kembali lebih awal
Seperti yang disarankan dalam komentar, itu akan cukup untuk hanya membungkus logika Anda dalam suatu fungsi dan keluar lebih awal dengan
return
itu untuk menyederhanakan banyak hal. Juga, Anda bisa memfaktorkan sedikit fungsionalitas dengan mendelegasikan tes ke fungsi lain. Lebih konkret:Ini lebih pendek dari upaya saya sebelumnya:
Di atas sedikit lebih verbose, tetapi mudah dibaca IMHO dan tidak menghitung ulang perbandingan beberapa kali.
Konfirmasi visual
Dalam jawaban Anda, Anda mengatakan:
... juga, dalam pertanyaan Anda, Anda mengatakan:
Saya mungkin tidak mengerti apa yang ingin Anda capai: apakah Anda ingin menyalin-menempel pola di mana pun Anda membutuhkannya? Dengan fungsi seperti yang di atas, Anda menangkap pola sekali, dan Anda memeriksa sekali untuk semua yang digunakan semua perbandingan
a
,b
danc
sesuai kebutuhan. Maka, Anda tidak perlu khawatir lagi saat memanggil fungsi. Tentu saja, mungkin dalam praktiknya masalah Anda sedikit lebih kompleks daripada yang Anda jelaskan: jika demikian, tambahkan beberapa detail jika mungkin.sumber
MOSTLY_A
atauMOSTLY_C
dalam kasusa == c
dana > b
. Ini sudah diperbaiki. Terima kasih.TL: DR; Kode Anda sudah benar dan "bersih".
Saya melihat banyak orang bertanya-tanya tetapi semua orang kehilangan hutan melalui pepohonan. Mari kita lakukan ilmu komputer penuh dan analisis matematika untuk sepenuhnya memahami pertanyaan ini.
Pertama, kita perhatikan bahwa kita memiliki 3 variabel, masing-masing dengan 3 menyatakan: <, =, atau>. Jumlah total permutasi adalah 3 ^ 3 = 27 status, yang akan saya berikan nomor unik, dilambangkan dengan P #, untuk setiap status. Nomor P # ini adalah sistem angka faktorial .
Merinci semua permutasi yang kita miliki:
Dengan inspeksi kami melihat kami memiliki:
Mari kita menulis sebuah program (lihat catatan kaki) untuk menghitung semua permutasi ini dengan nilai untuk A, B, dan C. Penyortiran yang stabil dengan P #:
Jika Anda bertanya-tanya bagaimana saya tahu negara bagian mana yang tidak mungkin, sekarang Anda tahu. :-)
Jumlah perbandingan minimum untuk menentukan pesanan adalah:
Log2 (27) = Log (27) / Log (2) = ~ 4,75 = 5 perbandingan
yaitu coredump memberikan 5 perbandingan jumlah minimal yang benar. Saya akan memformat kodenya sebagai:
Untuk masalah Anda, kami tidak peduli tentang pengujian untuk kesetaraan sehingga kami dapat menghilangkan 2 tes.
Tidak masalah seberapa bersih / buruk kodenya jika mendapat jawaban yang salah jadi ini pertanda baik bahwa Anda menangani semua kasing dengan benar!
Selanjutnya, untuk kesederhanaan, orang-orang terus berusaha untuk "meningkatkan" jawabannya, di mana mereka berpikir meningkatkan berarti "mengoptimalkan" jumlah perbandingan, tetapi itu tidak sepenuhnya apa yang Anda minta. Anda bingung semua orang di mana Anda bertanya "Saya merasa mungkin ada yang lebih baik" tetapi tidak mendefinisikan apa artinya 'lebih baik'. Lebih sedikit perbandingan? Kode kurang? Perbandingan yang optimal?
Sekarang karena Anda bertanya tentang keterbacaan kode (diberikan kebenaran) saya hanya akan membuat satu perubahan pada kode Anda untuk keterbacaan: Sejajarkan tes pertama dengan yang lain.
Secara pribadi saya akan menulisnya dengan cara berikut tetapi ini mungkin terlalu tidak lazim untuk standar pengkodean Anda:
Catatan Kaki: Berikut ini adalah kode C ++ untuk menghasilkan permutasi:
Suntingan: Berdasarkan umpan balik, memindahkan TL: DR ke atas, menghapus tabel yang tidak disortir, mengklarifikasi 27, membersihkan kode, menggambarkan keadaan yang mustahil.
sumber
@ msw memberi tahu Anda untuk menggunakan array alih-alih a, b, c, dan @Basile memberi tahu Anda refactor logika "maks" menjadi fungsi. Menggabungkan dua gagasan ini mengarah ke
lalu berikan fungsi yang menghitung indeks maks dari array arbitrer:
dan menyebutnya seperti
Jumlah total LOC tampaknya telah meningkat dari yang asli, tetapi sekarang Anda memiliki logika inti dalam fungsi yang dapat digunakan kembali, dan jika Anda dapat menggunakan kembali fungsi beberapa kali, itu mulai membuahkan hasil. Selain itu,
FindStrictMaxIndex
fungsi tersebut tidak terjalin dengan "persyaratan bisnis" Anda lagi (pemisahan kekhawatiran), sehingga risiko Anda harus memodifikasinya nanti jauh lebih rendah daripada di versi asli Anda (prinsip buka-tutup). Misalnya, fungsi itu tidak perlu diubah bahkan jika jumlah argumen berubah, atau perlu menggunakan nilai balik lain selain MOSTLY_ABC, atau Anda sedang memproses variabel lain selain a, b, c. Selain itu, penggunaan array bukan 3 nilai berbeda a, b, c mungkin menyederhanakan kode Anda di tempat lain juga.Tentu saja, jika di seluruh program Anda hanya ada satu atau dua tempat untuk memanggil fungsi ini, dan Anda tidak memiliki aplikasi lebih lanjut untuk menyimpan nilai-nilai dalam array, maka saya mungkin akan meninggalkan kode asli seperti itu (atau menggunakan @ peningkatan coredump).
sumber
FindStrictMaxIndex()
mungkin tidak terlalu bersih, tetapi dari sudut pandang penelepon cukup jelas apa yang berusaha dicapai.int
fungsi yang diketik sederhana . Tapi saya setuju dengan komentar Anda jika seseorang menggunakan bahasa yang berbeda seperti Python atau Perl.FindStrictMaxIndex
fungsi tersebut dapat digunakan kembali. Untuk satu atau dua kali penggunaan ulang, ini tidak akan membuahkan hasil, tentu saja, tetapi itulah yang sudah saya tulis dalam jawaban saya. Perhatikan juga keuntungan lain yang saya sebutkan di atas mengenai perubahan di masa depan.return result[FindStrictMaxIndex(val,3)];
pada titik di mana kode 8 baris asli ditempatkan . Bagian lain, terutamaFindStrictMaxIndex
itu sendiri sepenuhnya terpisah dari "logika bisnis", yang memindahkan mereka dari fokus perubahan persyaratan bisnis.Anda mungkin harus menggunakan makro atau fungsi yang
MAX
memberikan maksimal dua angka.Maka Anda hanya ingin:
Anda mungkin telah mendefinisikan
tapi hati-hati - terutama tentang efek samping - saat menggunakan makro (karena
MAX(i++,j--)
akan berperilaku aneh)Jadi lebih baik mendefinisikan suatu fungsi
dan gunakan (atau setidaknya
#define MAX(X,Y) max2ints((X),(Y))
....)Jika Anda perlu memahami asal-usul MAX Anda mungkin memiliki makro panjang seperti
#define COMPUTE_MAX_WITH_CAUSE(Status,Result,X,Y,Z)
yang merupakando{
...}while(0)
makro panjang , mungkinMaka Anda bisa memohon
COMPUTE_MAX_WITH_CAUSE(status,res,a,b,c)
di beberapa tempat. Agak jelek. Saya mendefinisikan variabel lokalx
,y
,z
untuk menurunkan efek samping yang buruk ....sumber
Saya sudah lebih banyak memikirkan hal ini, jadi karena masalah saya kebanyakan adalah konfirmasi visual bahwa semua perbandingan menggunakan variabel yang sama, saya pikir ini mungkin pendekatan yang berguna:
Bahwa setiap makro mengambil
a
,b
danc
dalam urutan yang sama mudah untuk dikonfirmasi, dan nama makro menyelamatkan saya harus mencari tahu apa yang dilakukan semua perbandingan dan AND.sumber