Terkadang (jarang), tampaknya menciptakan fungsi yang membutuhkan jumlah parameter yang layak adalah rute terbaik. Namun, ketika saya melakukannya, saya merasa seperti saya sering memilih urutan parameter secara acak. Saya biasanya menggunakan "urutan kepentingan", dengan parameter terpenting terlebih dahulu.
Apakah ada cara yang lebih baik untuk melakukan ini? Apakah ada cara "praktik terbaik" memesan parameter yang meningkatkan kejelasan?
refactoring
clean-code
functions
parameters
order
Casey Patton
sumber
sumber
MessageBox.Show
. Lihat itu juga.Jawaban:
Secara umum: gunakan itu .
Tulis tes untuk fungsi Anda, tes dunia nyata.
Sesuatu yang sebenarnya ingin Anda lakukan dengan fungsi itu .
Dan lihat dalam urutan apa Anda meletakkannya.
Kecuali Anda sudah memiliki (atau mengetahui) beberapa fungsi yang melakukan hal serupa.
Dalam hal itu: sesuaikan dengan apa yang sudah mereka lakukan, setidaknya untuk argumen pertama.
mis. Apakah mereka semua mengambil dokumen / objek / file-pointer / serangkaian-nilai / koordinat sebagai argumen pertama? Demi tuhan, sesuaikan dengan argumen itu .
Hindari membingungkan rekan kerja dan masa depan Anda .
sumber
Saya biasanya mengikuti aturan ini, meskipun tidak selalu dengan prioritas yang sama. Saya kira ini adalah proses pemikiran otomatis sekarang, dan saya tidak terlalu memikirkannya, kecuali untuk desain API publik .
Saluran Seleksi
1. Semantik Pertama
Khususnya dalam OOP, pilih parameter berdasarkan signifikansi semantik mereka untuk tindakan atau pesan. Tanda tangan dari metode yang dinamai dengan parameter yang dinamai harus:
(Untuk alasan ini, terkadang menggunakan jenis atau alias khusus alih-alih primitif dapat meningkatkan ekspresi tanda tangan Anda.)
2. Kemudian Pentingnya
Parameter paling "signifikan" adalah yang utama (atau selanjutnya ...)
3. Kemudian Frekuensi
Frekuensi juga penting, terutama dalam bahasa di mana Anda tidak memiliki nama parameter tetapi dapat memiliki nilai default pada parameter posisi. Itu menyiratkan bahwa urutan parameter tidak bervariasi, dan yang jelas Anda tidak dapat mengatur parameter N + 1 jika Anda ingin memaksakan nilai default dari parameter Nth (kecuali jika bahasa Anda memiliki konsep parameter place-holder) ).
Kabar baiknya bagi Anda adalah bahwa biasanya, frekuensi berkaitan dengan kepentingan, sehingga sejalan dengan poin sebelumnya. Dan mungkin terserah Anda untuk membuat API Anda agar memiliki semantik yang sesuai.
4. Jangan Lupa I / O
jika metode / fungsi Anda mengambil beberapa input dan menghasilkan output, dan yang terakhir tidak boleh "dikembalikan" (melalui pernyataan pengembalian) atau "dilempar" (menggunakan sistem pengecualian), maka Anda memiliki opsi untuk lulus nilai kembali ke pemanggil menggunakan parameter lain Anda (atau parameter input). Itu berhubungan dengan semantik, dan dalam banyak kasus masuk akal untuk memiliki parameter pertama yang menentukan output, dan parameter terakhir menerima output.
Selain itu, pendekatan lain untuk memiliki lebih sedikit parameter dan memaksimalkan semantik akan menggunakan pendekatan fungsional, atau untuk menentukan pola Builder , sehingga Anda dapat dengan jelas menumpuk input Anda, menentukan output Anda, dan mengambilnya ketika diperlukan.
(Perhatikan saya tidak menyebutkan variabel global, karena mengapa Anda akan menggunakannya, kan?)
Beberapa hal yang perlu dipertimbangkan
Kegunaan
Sebagian besar di atas akan muncul secara alami jika Anda mengikuti saran ZJR : Gunakan!
Pertimbangkan Refactoring
Jika Anda khawatir tentang pemesanan parameter, mungkin kekhawatiran ini menemukan akarnya di atas dan bahwa API Anda dirancang dengan buruk. Jika Anda memiliki terlalu banyak parameter, sesuatu kemungkinan besar dapat menjadi komponen / modularized dan refactored .
Pertimbangkan Kinerja
Perlu diingat bahwa implementasi beberapa bahasa akan menimbulkan dampak yang sangat penting pada manajemen memori runtime Anda saat menggunakan parameter. Karenanya alasan mengapa banyak buku gaya bahasa merekomendasikan untuk membuat daftar parameter sederhana dan singkat . Pada 4 parameter maks, misalnya. Saya meninggalkannya sebagai latihan bagi Anda untuk mencari tahu alasannya.
Jawaban Bevan dan penyebutan rekomendasi Clean Code juga sangat relevan!
sumber
Dengan hormat saya sampaikan bahwa khawatir tentang pemesanan parameter mengkhawatirkan hal yang salah.
Dalam buku Paman Bob " Kode Bersih " dia menganjurkan, secara persuasif, bahwa metode tidak boleh memiliki lebih dari dua argumen - dan sebagian besar seharusnya hanya memiliki satu, jika ada. Ketika hal ini terjadi, pemesanan jelas atau tidak penting.
Namun tidak sempurna, saya mencoba mengikuti saran Paman Bob - dan itu meningkatkan kode saya.
Dalam kasus yang jarang terjadi di mana metode tampaknya membutuhkan lebih banyak informasi, memperkenalkan objek parameter adalah ide yang bagus. Biasanya, saya menemukan ini adalah langkah pertama menuju penemuan konsep (objek) baru yang merupakan kunci dari algoritma saya.
sumber
Saya mencoba untuk menempatkan parameter IN pertama, parameter OUT kedua. Ada juga beberapa pemesanan alami, misalnya
createPoint(double x, double y)
sangat disukaicreatePoint(double y, double x)
.sumber
addAllTo(target, something1, something2)
.Saya belum pernah melihat "praktik terbaik" yang terdokumentasi mengenai topik khusus ini, tetapi standar pribadi saya adalah mencantumkannya dalam urutan di mana mereka akan muncul dalam metode yang sedang mereka gunakan atau jika metode tersebut lebih dari satu pass-through ke lapisan data saya akan daftar mereka dalam urutan mereka akan muncul dalam skema db atau metode lapisan data.
Juga, ketika ada beberapa kelebihan metode, saya perhatikan bahwa cara yang umum adalah mendaftarnya dimulai dengan parameter yang umum untuk semua (atau sebagian besar) metode dengan setiap metode yang berbeda ditambahkan ke akhir untuk setiap metode kelebihan seperti :
sumber
Urutan: input, output, parameter opsional.
sumber
Saya sering mengikuti konvensi C / C ++ menempatkan
const
parameter terlebih dahulu (yaitu, parameter yang Anda lewati dengan nilai), dan kemudian yang Anda lewati dengan referensi. Ini mungkin bukan metode yang tepat untuk fungsi panggilan tetapi, jika Anda tertarik pada bagaimana masing-masing kompiler menangani parameter, lihat tautan berikut untuk aturan yang mengatur dan / atau urutan parameter didorong ke stack.http://msdn.microsoft.com/en-us/library/zthk2dkh%28v=vs.80%29.aspx
http://en.wikipedia.org/wiki/Calling_convention
sumber
Saya biasanya hanya pergi dengan memesan parameter "apa yang terlihat kurang cyprtic". Semakin sedikit kali saya harus pergi ke metode / definisi fungsi semakin baik. Dan itu bagus untuk menamai parameter yang deskriptif untuk apa mereka digunakan, dengan cara itu ketika tooltip kecil muncul (VS) maka membuatnya lebih mudah.
Jika Anda memiliki garis dan garis parameter, Anda mungkin ingin mempertimbangkan desain yang berbeda. Mundur dan lihat bagaimana Anda dapat memecahnya menjadi lebih banyak fungsi / metode. Hanya sebuah ide, tetapi ketika saya memiliki selusin parameter dalam fungsi saya, itu hampir selalu bukan masalah parameter, tetapi masalah desain.
sumber
Menggunakan beberapa parameter seringkali merupakan indikator yang jelas, bahwa Anda melanggar SRP dalam metode ini. Suatu metode, yang membutuhkan banyak parameter tidak mungkin hanya melakukan satu hal. Pengecualian dapat berupa fungsi matematika atau metode konfigurasi, di mana memang diperlukan beberapa parameter . Saya akan menghindari beberapa parameter karena iblis menghindari air suci. Semakin banyak parameter yang Anda gunakan dalam suatu metode, semakin tinggi peluangnya, bahwa metode itu terlalu rumit; semakin rumit berarti: lebih sulit untuk dipertahankan dan itu kurang diinginkan.
Pada prinsipnya Anda memilih secara acak . Tentu saja Anda mungkin berpikir paramter A lebih relevan daripada parameter B ; tapi itu mungkin bukan kasus untuk pengguna API Anda, yang menganggap B adalah parameter yang paling relevan. Jadi, bahkan jika Anda penuh perhatian dalam memilih pemesanan - bagi orang lain itu bisa tampak acak .
Ada beberapa jalan keluar:
a) Kasus sepele: Jangan gunakan lebih dari satu parameter.
b) Karena Anda tidak menentukan, bahasa apa yang Anda pilih, ada kemungkinan, bahwa Anda memilih bahasa dengan parameter bernama . Ini adalah gula sintaksis yang bagus yang memungkinkan Anda untuk melonggarkan pentingnya urutan parameter:
fn(name:"John Doe", age:36)
Tidak setiap bahasa mengizinkan hal-hal seperti itu. Jadi bagaimana?
c) Anda dapat menggunakan Kamus / Hashmap / Asosiatif Array sebagai parameter: mis. Javascript akan mengizinkan hal berikut:
fn({"name":"John Doe", age:36})
yang tidak jauh dari (b).d) Tentu saja jika Anda bekerja dengan bahasa yang diketik secara statis seperti Java. Anda bisa menggunakan Hashmap , tetapi Anda akan kehilangan informasi jenis (misalnya ketika bekerja dengan
HashMap<String, Object>
) ketika parameter memiliki tipe yang berbeda (dan perlu dilemparkan).Langkah logis berikutnya adalah untuk melewatkan
Object
(jika Anda menggunakan Java) dengan properti yang sesuai atau sesuatu yang lebih ringan seperti struct (jika Anda menulis misalnya C # atau C / C ++).Aturan praktis:
1) Kasus terbaik - metode Anda tidak memerlukan parameter sama sekali
2) Kasus bagus - metode Anda membutuhkan satu parameter
3) Kasing yang dapat ditoleransi - metode Anda membutuhkan dua parameter
4) Semua kasus lain harus di refactored
sumber
Seringkali objek yang kompleks sebagai parameter lebih baik - versi parameter yang disebutkan oleh orang miskin yang bekerja pada sebagian besar platform. Dan membuka pintu ke parameter dengan perilaku untuk boot.
Sebagai contoh sebagian besar hal yang tidak boleh Anda lakukan, Anda mungkin ingin mencoba membaca dokumentasi perpustakaan standar PHP.
sumber
Saya biasanya memesannya dengan yang diperlukan terlebih dahulu, daripada dengan ukuran impor dan frekuensi penggunaan gabungan menurut "perasaan" (dapat dilihat sebagai
ORDER BY required DESC, SOME_MAGIC_FEELING(importancy,frequency)
) dan tidak sesuai dengan praktik tertentu.Namun, seperti yang telah dicatat orang lain, saya pikir masalah mendasar yang membuat masalah ini adalah menggunakan terlalu banyak parameter (IMHO, apa pun> 3 terlalu banyak) dan itulah masalah sebenarnya yang harus Anda atasi. Ada posting yang menarik tentang itu di blog rebecca murphey.
Saya pikir ketika Anda hanya memiliki 1-3 argumen, urutan yang benar cukup jelas dan Anda hanya "merasakan" apa yang benar.
sumber
Mirip dengan jawaban @ Wyatt Barnetts, apa pun lebih dari beberapa parameter atau parameter yang sangat eksplisit untuk metode ini, saya akan merekomendasikan melewati objek sebagai gantinya. Ini biasanya lebih mudah untuk memperbarui / memelihara, lebih jelas untuk membaca, dan menghilangkan keharusan untuk khawatir tentang pemesanan . Juga, terlalu banyak parameter untuk suatu metode adalah bau kode dan ada pola refactoring umum yang dapat Anda ikuti untuk membantu memperbaikinya.
Contoh eksplisit:
Karena ini adalah contoh yang cukup jelas dan penambahan bersifat komutatif (pesanan tidak masalah) maka ikuti saja.
Namun, jika Anda menambahkan sesuatu yang lebih kompleks:
Akan menjadi:
Semoga ini membantu...
sumber
Pesanlah dengan cara apa pun yang menurut Anda paling cocok untuk mendapatkan kari. Misalnya, parameter fungsi terlebih dahulu.
sumber
"Penting dulu" tidak berarti banyak. Ada beberapa konvensi.
Jika Anda melewati objek panggilan (sering disebut pengirim), itu berlaku lebih dulu.
Seharusnya ada beberapa kefasihan dalam daftar, yang berarti Anda harus tahu apa argumen tentang pada saat Anda membacanya. Contoh:
CopyFolder (jalur string, bool rekursif);
Jika Anda mengutamakan rekursif, itu akan membingungkan karena belum ada konteks. Jika Anda sudah sekarang tentang menyalin (1), folder (2), maka argumen rekursif mulai masuk akal.
Ini juga membuat fitur seperti IntelliSense bekerja dengan baik: pengguna belajar saat dia mengisi argumen, dia membangun pemahaman tentang metode dan apa yang dilakukannya. Demikian juga, kelebihan beban harus mempertahankan urutan yang sama untuk bagian yang sama.
Maka Anda mungkin masih menemukan ada argumen yang "sama" dalam hal ini dan Anda mungkin tergoda untuk membiarkan urutan bergantung pada jenis argumen. Hanya karena memiliki beberapa string berturut-turut dan kemudian beberapa booleans terlihat lebih baik. Pada tingkat tertentu ini akan menjadi seni daripada keterampilan.
Saya tidak terlalu peduli dengan pernyataan bahwa Anda harus membungkus semua argumen menjadi objek hanya untuk berakhir dengan satu argumen. Itu hanya membodohi diri sendiri (itu tidak membuat metode ini kurang kompleks, ia masih memiliki semua argumen ini, Anda hanya menyembunyikannya). Ini mungkin masih nyaman dilakukan jika Anda meneruskan set dari metode ke metode beberapa kali, refactoring pasti akan menjadi jauh lebih mudah, tetapi dari sisi desain hanya berpura-pura Anda membuat perbedaan. Ini tidak seperti Anda akan berakhir dengan objek bermakna yang mewakili sesuatu, itu hanya akan menjadi sekelompok argumen, tidak berbeda dari daftar dalam deklarasi metode. Itu tidak akan membuat paman Bob bahagia.
sumber