Apa yang dimaksud dengan praktik kode yang baik tentang kapan membuat fungsi / metode untuk segmen kode berulang kecil?

12

Berkali-kali sepanjang menulis program yang lebih besar saya mempertanyakan setelah berapa banyak salinan dan pasta masuk akal untuk menempatkan kode ke dalam fungsi atau metode dan apa aturan praktis yang baik? Saya telah menggunakan aturan praktis empat baris atau lebih besar dan muncul lebih dari dua kali, lalu saya membuat fungsi / metode sederhana yang berisi kode itu. Bisakah Anda memikirkan praktik yang lebih baik atau menawarkan petunjuk? Ini lebih merupakan pertanyaan pola desain umum daripada pertanyaan khusus bahasa.


sumber

Jawaban:

29

Saya menggunakan fungsi sebagian sebagai cara untuk mendokumentasikan kode. Memanggil fungsi dengan nama yang berarti membuatnya lebih mudah untuk memahami kode. Dalam beberapa kasus, bahkan fungsi dengan satu baris pun masuk akal.

Misalnya, dalam "Kode Bersih", Robert C. Martin memberikan contoh berikut: Yang mana yang lebih Anda sukai? Ini:

// Check to see if the employee is eligible for full benefits
if ((employee.flags & HOURLY_FLAG) &&
    (employee.age > 65))

Atau ini?

if (employee.isEligibleForFullBenefits())

Saya tidak selalu setuju dengannya, tetapi dalam hal ini saya setuju. Kode harus dapat dibaca, tidak hanya ketika Anda menulisnya dan Anda tahu setiap detailnya, tetapi juga pada jam 9 malam ketika Anda harus memperbaiki bug dalam kode orang lain. Menatap kondisi yang panjang dan mencoba mencari tahu semua negatif ganda tidak dianjurkan. Jika Anda bisa menuliskan nama saja (tidak hanya syarat, tapi setiap kode yang Anda tulis), itu menjadi jauh lebih sederhana.

Saya tidak pernah menyesal memasukkan sesuatu ke dalam fungsi, dan jika Anda khawatir tentang kinerja, maka profillah terlebih dahulu.

omrib
sumber
2
Mengikuti latihan sederhana ini pada akhirnya akan memungkinkan Anda untuk menulis kode aplikasi pada tingkat yang relatif tinggi. Fungsi-fungsi kecil dikumpulkan menjadi kelas-kelas kecil dan segera Anda mengubah spesifikasi fungsional menjadi kode hampir kata demi kata.
kevin cline
11
Saya menyukai contoh ini. Tiba-tiba Anda tidak membutuhkan komentar itu lagi. Ini adalah aturan praktis : jika komentar Anda dapat dikonversi ke variabel atau nama fungsi, lakukan!
Karoly Horvath
Saya setuju dengan omrib di sini, ini sering tentang membersihkan kode - apa yang membuatnya lebih mudah dibaca daripada aturan praktis lainnya. Jika saya akhirnya menggunakan kembali sesuatu, saya akan mengekstraknya ke suatu metode. Namun, IDE dan alat saya sering membantu, jadi mudah dan cepat untuk dilakukan.
Travis
+1 Kode semacam ini bahkan bisa lebih cepat, setidaknya jika perlu JIT-ed - Anda hanya membayar untuk apa yang Anda gunakan.
Pekerjaan
1
juga dikenal sebagai Intention Revealing Names .
rwong
13

Ada kesalahpahaman luas bahwa panggilan fungsi hanya boleh dilakukan untuk menghindari segmen kode yang berulang. Aturan praktis saya adalah bahwa setiap unit kerja logis harus dibuat menjadi suatu fungsi, bahkan ketika itu hanya digunakan di satu tempat. Ini biasanya mengarah pada keterbacaan yang lebih baik, dan memungkinkan Anda untuk menulis kode self-documenting, di mana nama fungsi menggantikan komentar dan Anda tidak perlu menulis komentar tambahan menjelaskan apa yang Anda lakukan.

Lie Ryan
sumber
1
Lihat berapa lama programmer akan pergi untuk menghindari menulis komentar?
Alger
1
@Alger sebagaimana mestinya
MatrixFrog
6

Jika digunakan di lebih dari satu tempat, dan

  • kemungkinan akan berubah, atau
  • sulit untuk menjadi benar

lalu jadikan fungsi atau metode. Potongan panjang kode berulang, dalam pengalaman saya, secara alami akan jatuh ke dalam salah satu kategori ini (biasanya yang pertama, tetapi kemudian kategori tumpang tindih banyak;). Tentu saja, apa pun yang ada di antarmuka juga merupakan fungsi / metode dalam dirinya sendiri.

Fred Foo
sumber
3
Pertanyaannya adalah: mengapa Anda tidak menulis fungsi untuk sepotong kode yang biasanya diulang bahkan jika itu tidak sulit untuk mendapatkan yang benar atau kemungkinan berubah? (Aturan praktis saya: jika diulang dan lebih lama memanggil fungsi, jadikan fungsi)
Winston Ewert
Saya akan melangkah lebih jauh. Sebagai seorang programmer Anda harus menghilangkan semua jenis pengulangan . Baik itu di database (normalisasi), beberapa pengujian manual (ganti dengan unit test) atau penyebaran (otomasikan).
Karoly Horvath
@ Winston: itu tergantung pada bahasa yang digunakan. Tidak setiap konstruk dapat ditangkap secara alami sebagai suatu fungsi, fungsi tersebut mungkin membutuhkan lebih banyak ruang daripada kode asli (pikirkan C dan kembali dengan pointer), panggilan fungsi dapat menimbulkan overhead.
Fred Foo
@ Larsman, saya ingin tahu apa yang Anda maksudkan dengan "(pikirkan C dan kembali dengan pointer)". Tetapi apa yang Anda katakan adalah apa yang saya coba lakukan dengan aturan praktis saya. Memanggil fungsi harus lebih mudah (yaitu secara alami menangkap dan mengambil lebih sedikit ruang) kemudian mengimplementasikan konten fungsi.
Winston Ewert
Jika sepotong kode menghitung beberapa nilai, ucapkan float x, int ydan double density, kemudian atur perhitungan itu sebagai fungsi C bisa lebih rumit daripada sekadar mengulang kode, karena Anda harus menemukan cara untuk mengeluarkan ketiga nilai. Jika perhitungan berulang itu sendiri sepele, terkadang lebih baik membiarkannya saja.
Fred Foo
4

Hampir selalu, terutama jika setiap duplikat mewakili operasi yang sama dari sudut pandang konseptual. Jika dilakukan dengan cara yang sama, tetapi pada tipe yang berbeda, buat implementasi generik.

Satu-satunya alasan yang tidak dapat saya pikirkan adalah salah satu pemeliharaan: kadang-kadang mungkin lebih nyaman untuk menghindari menciptakan ketergantungan antara hal-hal yang terpisah, bahkan dengan biaya duplikasi.

Nicola Musatti
sumber
Waspadalah terhadap pengetikan bebek, jika untuk saat ini implementasinya mirip, tetapi fungsinya berbeda secara efektif, maka menggabungkan keduanya membuatnya sangat menyebalkan. Terutama dalam bahasa dengan dukungan IDE yang buruk (hei, saya bekerja di C ++ ...)
Matthieu M.
Di sisi lain dengan memisahkan mereka, Anda memiliki dua fungsi yang melakukan hal yang sama untuk menguji, setengah peluang kode Anda dijalankan, dua tempat di mana bug yang sama merayap naik dan Anda harus ingat untuk memperbaikinya di mana bug belum terdeteksi. Saya ingin tetap bekerja di C ++, dukungan IDE yang buruk meskipun ;-)
Nicola Musatti
1

Pencarian untuk " refactoring " akan membawa Anda ke banyak sumber daya untuk "praktik terbaik" industri untuk proses yang sangat umum ini. Artikel yang agak terkenal, Once and Only Once adalah referensi sejarah hebat yang menjelaskan apa yang oleh sebagian orang dianggap sebagai "praktik terbaik" untuk masalah yang dikemukakan oleh pertanyaan Anda. Juga, konsep yang lebih umum dikenal sebagai Don't Repeat Yourself (DRY) . Untuk rangkaian jawaban yang sangat mendalam untuk pertanyaan Anda, bacalah buku klasik Martin Fowler yang hebat, Refactoring: Meningkatkan Desain Kode yang Ada , yang mencakup beberapa saran paling dikenal untuk refactoring , yang secara intuitif Anda coba capai !

John Tobler
sumber
0

Jika kode tersebut tepat diulang di lebih dari satu tempat dan bagian yang diulang tidak akan berubah dalam waktu dekat maka saya memecahnya menjadi suatu fungsi.

Steven D.
sumber
1
jika itu akan berubah, bahkan lebih banyak alasan untuk menolaknya. Maka Anda hanya perlu mengubahnya sekali
SHug
0

Itu tergantung pada sifat kohesi kode yang diulang. Jika bagian berulang kode melakukan fungsi tertentu, maka itu adalah kandidat yang sangat baik untuk dijadikan metode, sebagian karena prinsip KERING , sebagian karena jika fungsi perlu dioptimalkan atau diperbaiki, maka hanya ada satu bagian kode untuk ditangani.

Jika asosiasi itu kebetulan, lebih baik mengulang kode daripada membuatnya menjadi metode. Jika Anda perlu menambahkan sesuatu ke tengah-tengah salah satu urutan kode untuk memenuhi salah satu penggunaan potongan itu, jika itu dalam suatu metode, perubahan yang Anda buat dapat memengaruhi penggunaan lain dari metode itu.

Lihat artikel Wikipedia tentang konsep kohesi kode .

Jay Elston
sumber
jika asosiasi tersebut terlihat kebetulan, kemungkinan kedua proses tersebut memiliki ide yang sama, dan Anda mungkin harus mengeksplorasi apakah kedua proses tersebut memang dua sisi dari hal yang sama. Lebih sering daripada tidak.
Lie Ryan
0

Anda harus membedakan antara fungsi-fungsi dalam pengertian pemrograman terstruktur dan metode kelas.

Dalam contoh Anda, apa yang telah Anda perlihatkan adalah metode yang karenanya tidak boleh dikodekan secara in-line.

Anda mungkin harus memvalidasi string untuk melihat apakah itu angka atau tidak, dalam hal ini, Anda menggunakan fungsi dan sebagian besar jawaban sebelumnya berlaku.

Perbedaan ini penting khususnya dalam proyek-proyek besar.

Sebisa mungkin, berusaha untuk memisahkan aturan bisnis (yang merupakan metode) dari algoritma komputasi (yang merupakan fungsi pemrograman murni).

Tidak mungkin
sumber