Mengapa tidak menyandikan nama argumen dalam nama fungsi lebih umum? [Tutup]

47

Dalam Clean Code , penulis memberikan contoh

assertExpectedEqualsActual(expected, actual)

vs.

assertEquals(expected, actual)

dengan mantan diklaim lebih jelas karena menghilangkan kebutuhan untuk mengingat ke mana pergolakan dan potensi penyalahgunaan yang berasal dari itu. Namun, saya belum pernah melihat contoh skema penamaan sebelumnya dalam kode apa pun dan melihat yang terakhir sepanjang waktu. Mengapa coders tidak mengadopsi yang pertama jika, seperti yang ditegaskan oleh penulis, lebih jelas daripada yang terakhir?

EternalStudent
sumber
9
Saya pikir ini adalah pertanyaan yang bagus untuk diskusi. Namun bukan sesuatu yang bisa dijawab dengan jawaban obyektif. Jadi pertanyaan ini mungkin ditutup sebagai berbasis opini.
Euforia
54
Banyak orang akan menentang skema penamaan pertama karena terlalu banyak bertele-tele , jauh melampaui titik di mana itu akan membantu kejelasan. Khusus untuk assertEquals(), metode yang digunakan ratusan kali dalam basis kode sehingga dapat diharapkan bahwa pembaca membiasakan diri dengan konvensi sekali. Kerangka kerja yang berbeda memiliki konvensi yang berbeda (misalnya (actual, expected) or an agnostic (kiri, kanan) `), tetapi dalam pengalaman saya itu paling banyak sumber kebingungan kecil.
amon
5
Karena keuntungan sangat kecil, dibandingkan dengan manfaatnya, sehingga orang waras mana pun mungkin akan pergi. Jika Anda ingin pendekatan yang lebih lancar Anda harus mencoba assert(a).toEqual(b)(bahkan jika IMO itu masih tidak perlu bertele-tele) di mana Anda dapat rantai beberapa pernyataan terkait.
Adriano Repetti
18
Bagaimana kita tahu bahwa nilai aktual dan yang diharapkan adalah? Tentunya itu seharusnya assertExpectedValueEqualsActualValue? Tapi tunggu, bagaimana kita mengingat apakah itu menggunakan ==atau .equalsatau tidak Object.equals? Haruskah begitu assertExpectedValueEqualsMethodReturnsTrueWithActualValueParameter?
user253751
6
Mengingat bahwa, untuk metode khusus ini, urutan kedua argumen itu tidak masalah, sepertinya contoh yang buruk untuk memilih untuk mendukung manfaat dari skema penamaan ini.
Steven Rands

Jawaban:

66

Karena lebih banyak mengetik dan lebih banyak membaca

Alasan paling sederhana adalah bahwa orang suka mengetik lebih sedikit, dan menyandikan informasi itu berarti lebih banyak mengetik. Ketika membacanya, setiap kali saya harus membaca semuanya bahkan jika saya tahu apa urutan argumennya. Bahkan jika tidak terbiasa dengan urutan argumen ...

Banyak pengembang menggunakan IDE

IDE sering menyediakan mekanisme untuk melihat dokumentasi untuk metode yang diberikan dengan mengarahkan atau melalui pintasan keyboard. Karena itu, nama parameter selalu tersedia.

Pengkodean argumen menghasilkan duplikasi dan penggandengan

Nama-nama parameter harus sudah mendokumentasikan apa itu. Dengan menuliskan nama-nama dalam nama metode, kami juga menggandakan informasi itu dalam tanda tangan metode. Kami juga membuat sambungan antara nama metode dan parameter. Katakan expecteddan actualmembingungkan pengguna kami. Beralih dari assertEquals(expected, actual)menjadi assertEquals(planned, real)tidak perlu mengubah kode klien menggunakan fungsi. Pergi dari assertExpectedEqualsActual(expected, actual)ke assertPlannedEqualsReal(planned, real)sarana perubahan melanggar ke API. Atau kami tidak mengubah nama metode, yang dengan cepat membingungkan.

Gunakan jenis alih-alih argumen yang mendua

Masalah sebenarnya adalah bahwa kita memiliki argumen ambigu yang mudah diubah karena mereka adalah tipe yang sama. Sebagai gantinya, kami dapat menggunakan sistem tipe dan kompiler kami untuk menegakkan urutan yang benar:

class Expected<T> {
    private T value;
    Expected(T value) { this.value = value; }
    static Expected<T> is(T value) { return new Expected<T>(value); }
}

class Actual<T> {
    private T value;
    Actual(T value) { this.value = value; }
    static Actual<T> is(T value) { return new Actual<T>(value); }
}

static assertEquals(Expected<T> expected, Actual<T> actual) { /* ... */ }

// How it is used
assertEquals(Expected.is(10), Actual.is(x));

Ini kemudian dapat diberlakukan di tingkat kompiler dan menjamin bahwa Anda tidak bisa mendapatkannya mundur. Mendekati dari sudut yang berbeda, ini pada dasarnya adalah apa yang dilakukan perpustakaan Hamcrest untuk tes.

cbojar
sumber
5
Nah, jika Anda menggunakan IDE, Anda memiliki nama parameter dalam bantuan balon; jika Anda tidak menggunakannya, mengingat nama fungsi sama dengan mengingat argumen, jadi tidak ada yang diperoleh.
Peter - Pasang kembali Monica
29
Jika Anda keberatan dengan assertExpectedEqualsActual"karena lebih banyak mengetik dan lebih banyak membaca", lalu bagaimana Anda bisa mengadvokasi assertEquals(Expected.is(10), Actual.is(x))?
ruakh
9
@ruakh itu tidak sebanding. assertExpectedEqualsActualmasih membutuhkan programmer untuk peduli untuk menentukan argumen dalam urutan yang benar. Tanda assertEquals(Expected<T> expected, Actual<T> actual)tangan menggunakan kompiler untuk menegakkan penggunaan yang benar, yang merupakan pendekatan yang sama sekali berbeda. Anda dapat mengoptimalkan pendekatan ini untuk singkatnya, misalnya expect(10).equalsActual(x), tapi itu bukan pertanyaan ...
Holger
6
Juga, dalam kasus khusus ini (==), urutan argumen sebenarnya tidak relevan dengan nilai akhir. Urutan hanya penting untuk efek samping (melaporkan kegagalan). Ketika memesan hal-hal penting, mungkin (secara marginal) lebih masuk akal. Misalnya strcpy (dest, src).
Kristian H
1
Tidak dapat setuju lagi, terutama dengan bagian tentang duplikasi & penggandengan ... Jika setiap kali parameter fungsi mengubah namanya, nama fungsi juga harus berubah, Anda harus melacak semua penggunaan fungsi itu dan ubah juga ... Itu akan membuat banyak kapal melanggar perubahan untukku, timku, dan yang lainnya menggunakan kode kita sebagai ketergantungan ...
mrsmn
20

Anda bertanya tentang perdebatan lama dalam pemrograman. Seberapa banyak verbositas baik? Sebagai jawaban umum, pengembang telah menemukan bahwa verbositas ekstra yang menyebutkan argumen tidak sepadan.

Verbositas tidak selalu berarti lebih jelas. Mempertimbangkan

copyFromSourceStreamToDestinationStreamWithoutBlocking(fileStreamFromChoosePreferredOutputDialog, heuristicallyDecidedSourceFileHandle)

melawan

copy(output, source)

Keduanya mengandung bug yang sama, tetapi apakah kita benar-benar membuatnya lebih mudah untuk menemukan bug itu? Sebagai aturan umum, hal yang paling mudah untuk di-debug adalah ketika semuanya terse maksimal, kecuali beberapa hal yang memiliki bug, dan itu cukup jelas untuk memberi tahu Anda apa yang salah.

Ada sejarah panjang dalam menambahkan verbositas. Misalnya, ada " notasi Hongaria " yang umumnya tidak populer yang memberi kita nama-nama yang bagus lpszName. Itu umumnya telah jatuh di pinggir jalan di populasi programmer umum. Namun, menambahkan karakter ke nama variabel anggota (suka mNameatau m_Nameatau name_) terus memiliki popularitas di beberapa kalangan. Yang lain menjatuhkan itu sepenuhnya. Saya kebetulan bekerja pada basis kode simulasi fisika yang dokumen gaya pengkodeannya mengharuskan setiap fungsi yang mengembalikan vektor harus menentukan bingkai vektor dalam pemanggilan fungsi ( getPositionECEF).

Anda mungkin tertarik pada beberapa bahasa yang dipopulerkan oleh Apple. Objective-C menyertakan nama argumen sebagai bagian dari tanda tangan fungsi (Fungsi [atm withdrawFundsFrom: account usingPin: userProvidedPin]ditulis dalam dokumentasi sebagai withdrawFundsFrom:usingPin:. Itulah nama fungsi). Swift membuat seperangkat keputusan yang sama, mengharuskan Anda untuk memasukkan nama argumen dalam panggilan fungsi ( greet(person: "Bob", day: "Tuesday")).

Cort Ammon
sumber
13
Selain semua poin lain, itu akan jauh lebih mudah dibaca jika copyFromSourceStreamToDestinationStreamWithoutBlocking(fileStreamFromChoosePreferredOutputDialog, heuristicallyDecidedSourceFileHandle)ditulis copy_from_source_stream_to_destination_stream_without_blocking(file_stream_from_choose_preferred_output_dialog, heuristically_decided_source_file_handle). Lihat betapa mudahnya itu ?! Itu karena terlalu mudah untuk melewatkan perubahan kecil di tengah-tengah kata kunci humungousunbroken, dan butuh waktu lebih lama untuk mencari tahu di mana kata batas. Menghancurkan membingungkan.
tchrist
1
Sintaks obj-C withdrawFundsFrom: account usingPin: userProvidedPinsebenarnya dipinjam dari SmallTalk.
joH1
14
@tchrist berhati-hatilah dengan memastikan Anda benar tentang topik yang melibatkan perang suci. Sisi lain tidak selalu salah.
Cort Ammon
3
@tchrist Addingunderscoresnakesthingseasiertoreadnotharderasyouseememanipulasi argumen. Jawaban di sini menggunakan huruf besar, yang Anda abaikan. AddingCapitalizationMakesThingsEasyEnoughToReadAsYouCanSeeHere. Kedua, 9 kali dari 10, sebuah nama tidak boleh tumbuh melebihi [verb][adjective][noun](di mana setiap blok adalah opsional), sebuah format yang dapat dibaca dengan baik menggunakan ReadSimpleName
huruf
5
@tchrist - ilmu penelitian Anda ( tautan teks lengkap gratis ) hanya menunjukkan bahwa programmer yang dilatih untuk menggunakan gaya garis bawah lebih cepat membaca gaya garis bawah daripada kasing unta. Data juga menunjukkan bahwa perbedaannya lebih kecil untuk mata pelajaran yang lebih berpengalaman (dan sebagian besar mata pelajaran adalah siswa menunjukkan bahwa bahkan mereka yang kemungkinan tidak berpengalaman). Ini tidak berarti bahwa programmer yang menghabiskan lebih banyak waktu menggunakan kasing unta juga akan memberikan hasil yang sama.
Jules
8

Penulis "Kode Bersih" menunjukkan masalah yang sah, tetapi solusi yang disarankannya agak tidak sopan. Biasanya ada cara yang lebih baik untuk meningkatkan nama metode yang tidak jelas.

Dia benar bahwa assertEquals(dari pustaka uji unit xUnit style) tidak memperjelas argumen mana yang diharapkan dan mana yang sebenarnya. Ini juga menggigitku! Banyak perpustakaan unit test telah mencatat masalah ini dan telah memperkenalkan sintaksis alternatif, seperti:

actual.Should().Be(expected);

Atau serupa. Yang tentunya jauh lebih jelas daripada assertEqualstetapi juga jauh lebih baik daripada assertExpectedEqualsActual. Dan itu juga jauh lebih komposable.

JacquesB
sumber
1
Saya anal dan saya memang mengikuti pesanan yang direkomendasikan tetapi menurut saya jika saya mengharapkan hasil fun(x)menjadi 5 maka apa yang bisa salah jika membalikkan urutan - assert(fun(x), 5)? Bagaimana itu menggigitmu?
emory
3
@emory Saya tahu jUnit (setidaknya) membuat pesan kesalahan dari nilai expecteddan actual, jadi membalikkannya mungkin menghasilkan pesan yang tidak akurat. Tapi saya setuju bahwa kedengarannya lebih alami :)
joH1
@ joH1 sepertinya lemah bagi saya. kode yang gagal akan gagal dan kode yang lewat akan lulus apakah Anda melakukannya assert(expected, observed)atau assert(observed, expected). Contoh yang lebih baik adalah sesuatu locateLatitudeLongitude- jika Anda membalikkan koordinat, itu akan sangat kacau.
emory
1
@emory Orang yang tidak peduli dengan pesan kesalahan yang masuk akal dalam unit test adalah alasan mengapa saya harus berurusan dengan "Assert.IsTrue gagal" di beberapa basis kode lama. Sangat menyenangkan untuk melakukan debug. Tapi ya dalam kasus ini masalahnya mungkin tidak begitu penting (kecuali jika kita melakukan perbandingan kabur di mana urutan argumen umumnya penting). Pernyataan lancar memang cara yang bagus untuk menghindari masalah ini dan juga membuat kode lebih ekspresif (dan memberikan pesan kesalahan yang jauh lebih baik untuk boot).
Voo
@emory: Membalik argumen akan membuat pesan kesalahan menyesatkan, dan mengirim Anda ke jalur yang salah saat debugging.
JacquesB
5

Anda mencoba untuk mengarahkan jalan Anda antara Scylla dan Charybdis untuk kejelasan, mencoba untuk menghindari kata-kata yang tidak berguna (juga dikenal sebagai rambling tanpa tujuan) serta keringkasan yang berlebihan (juga dikenal sebagai kesederhanaan samar).

Jadi, kita harus melihat antarmuka yang ingin Anda evaluasi, cara untuk melakukan debug-pernyataan bahwa dua objek sama.

  1. Apakah ada fungsi lain yang bisa mempertimbangkan arity dan nama?
    Tidak, jadi nama itu sendiri sudah cukup jelas.
  2. Apakah jenisnya penting?
    Tidak, jadi mari kita abaikan saja. Anda sudah melakukannya? Baik.
  3. Apakah argumennya simetris?
    Hampir, pada kesalahan pesan menempatkan setiap representasi argumen ke tempat mereka sendiri.

Jadi, mari kita lihat apakah perbedaan kecil itu penting, dan tidak tercakup oleh konvensi kuat yang ada.

Apakah audiens yang dituju tidak nyaman jika argumennya tidak sengaja ditukar?
Tidak, pengembang juga mendapatkan jejak-jejak dan mereka harus memeriksa kode sumber untuk memperbaiki bug.
Bahkan tanpa jejak stack-penuh, posisi pernyataan menyelesaikan pertanyaan itu. Dan bahkan jika itu hilang dan tidak jelas dari pesan yang mana, itu paling banyak menggandakan kemungkinan.

Apakah argumennya mengikuti konvensi?
Tampaknya demikian. Meskipun tampaknya konvensi yang lemah.

Dengan demikian, perbedaannya terlihat sangat tidak signifikan, dan tatanan argumen ditutupi oleh konvensi yang cukup kuat sehingga setiap upaya untuk memasukkannya ke dalam fungsi-nama memiliki utilitas negatif.

Deduplicator
sumber
baik urutan mungkin masalah dengan jUnit, yang membangun pesan kesalahan spesifik dari nilai-nilai expecteddan actual(setidaknya dengan Strings)
joH1
Saya rasa saya membahas bagian itu ...
Deduplicator
Anda menyebutkannya tetapi mempertimbangkan: assertEquals("foo", "doo")memberikan pesan kesalahan adalah ComparisonFailure: expected:<[f]oo> but was:<[d]oo>... Menukar nilai akan membalikkan makna pesan, yang terdengar lebih anti simetris bagi saya. Pokoknya seperti yang Anda katakan dev memiliki indikator lain untuk menyelesaikan kesalahan, tetapi itu bisa menyesatkan IMHO dan membutuhkan sedikit waktu debugging.
joH1
Gagasan bahwa ada "konvensi" untuk pesanan argumen adalah lucu, mengingat bahwa kedua kubu (dest, src vs src, dest) telah berdebat tentang hal ini setidaknya selama AT&T vs Intel sintaks telah ada. Dan pesan kesalahan yang tidak membantu dalam unit test adalah wabah yang harus diberantas tidak ditegakkan. Itu hampir seburuk "Tegaskan. Gagal gagal" ("hei Anda harus menjalankan tes unit bagaimanapun juga untuk men-debugnya, jadi jalankan saja lagi dan letakkan breakpoint di sana", "hei Anda harus melihat kodenya, jadi cukup periksa apakah pesanan sudah benar ").
Voo
@ Voo: Intinya adalah bahwa "kerusakan" karena kesalahan itu sangat kecil (logika tidak tergantung padanya, dan utilitas pesan tidak terganggu ke tingkat yang signifikan), dan ketika menulis IDE akan menunjukkan kepada Anda nama parameter dan ketik saja.
Deduplicator
3

Seringkali itu tidak menambah kejelasan logis.

Bandingkan "Tambah" ke "AddFirstArgumentToSecondArgument".

Jika Anda membutuhkan kelebihan itu, katakanlah, tambahkan tiga nilai. Apa yang lebih masuk akal?

Lain "Tambah" dengan tiga argumen?

atau

"AddFirstAndSecondAndThirdArgument"?

Nama metode harus menyampaikan makna logisnya. Seharusnya tahu apa fungsinya. Memberitahu, pada tingkat mikro, langkah apa yang diambil tidak membuatnya lebih mudah bagi pembaca. Nama-nama argumen akan memberikan detail tambahan jika diperlukan. Jika Anda masih membutuhkan detail lebih lanjut, kodenya akan tersedia untuk Anda.

Martin Maat
sumber
4
Addmenyarankan operasi komutatif. OP prihatin dengan situasi di mana urutan itu penting.
Rosie F
Di Swift, misalnya Anda akan memanggil tambah (5, ke: x) atau tambahkan (5, tambah: 7, ke: x) atau tambahkan (5, tambah: 7, memberi: x) jika Anda menetapkan fungsi tambah () demikian.
gnasher729
Kelebihan ketiga harus dinamai "Sum"
StingyJack
@ StringyJack Hmm .. Sum bukan instruksi, itu adalah kata benda yang membuatnya kurang cocok untuk nama metode. Tetapi jika Anda merasa seperti itu dan Jika Anda ingin menjadi purist tentang hal itu, versi dua argumen juga harus dinamai Sum. Jika Anda memiliki metode Tambah, itu harus memiliki satu argumen yang ditambahkan ke instance objek itu sendiri (yang harus menjadi tipe numerik atau vektor). 2 atau lebih varietas argumen (apa pun nama Anda) akan menjadi statis. Maka versi argumen 3 atau lebih akan berlebihan dan kami akan menerapkan operator plus: - |
Martin Maat
1
@ Martin Tunggu apa? sumadalah kata kerja cromulent sempurna . Ini sangat umum dalam frasa "untuk menyimpulkan".
Voo
2

Saya ingin menambahkan sesuatu yang diisyaratkan oleh jawaban lain, tetapi saya tidak berpikir telah disebutkan secara eksplisit:

@puck mengatakan "Masih tidak ada jaminan argumen yang disebutkan pertama dalam nama fungsi benar-benar adalah parameter pertama."

@cbojar mengatakan "Gunakan tipe bukan argumen yang mendua"

Masalahnya adalah bahwa bahasa pemrograman tidak mengerti nama: mereka hanya diperlakukan sebagai simbol atom yang buram. Oleh karena itu, seperti halnya dengan komentar kode, tidak perlu ada korelasi antara apa fungsi dinamai dan bagaimana fungsinya sebenarnya.

Bandingkan assertExpectedEqualsActual(foo, bar)dengan beberapa alternatif (dari halaman ini dan di tempat lain), seperti:

# Putting the arguments in a labelled structure
assertEquals({expected: foo, actual: bar})

# Using a keyword arguments language feature
assertEquals(expected=foo, actual=bar)

# Giving the arguments different types, forcing us to wrap them
assertEquals(Expected(foo), Actual(bar))

# Breaking the symmetry and attaching the code to one of the arguments
bar.Should().Be(foo)

Ini semua memiliki struktur lebih dari nama verbose, yang memberikan bahasa sesuatu yang tidak buram untuk dilihat. Definisi dan penggunaan fungsi juga tergantung pada struktur ini, sehingga tidak bisa tidak sinkron dengan apa yang dilakukan oleh implementasi (seperti nama atau komentar yang bisa).

Ketika saya menemukan atau melihat masalah seperti ini, sebelum saya berteriak pada komputer saya dengan frustrasi, saya pertama-tama meluangkan waktu untuk bertanya apakah itu adil untuk menyalahkan mesin. Dengan kata lain, apakah mesin itu memberikan informasi yang cukup untuk membedakan apa yang saya inginkan dari yang saya minta?

Panggilan seperti assertEqual(expected, actual)sangat masuk akal assertEqual(actual, expected), jadi mudah bagi kita untuk membuat mereka tercampur dan alat berat maju dan melakukan hal yang salah. Jika kita menggunakan assertExpectedEqualsActualsebagai gantinya, itu mungkin membuat kita cenderung untuk membuat kesalahan, tetapi itu tidak memberikan informasi lebih lanjut ke mesin (tidak bisa mengerti bahasa Inggris, dan pilihan nama tidak boleh mempengaruhi semantik).

Apa yang membuat pendekatan "terstruktur" lebih disukai, seperti argumen kata kunci, bidang berlabel, jenis berbeda, dll. Adalah bahwa informasi tambahan juga dapat dibaca oleh mesin , sehingga kami dapat membuat mesin mendeteksi kesalahan penggunaan dan membantu kami melakukan hal-hal dengan benar. The assertEqualkasus ini tidak terlalu buruk, karena satu-satunya masalah akan pesan akurat. Contoh yang lebih seram mungkin String replace(String old, String new, String content), yang mudah membingungkan dengan String replace(String content, String old, String new)yang memiliki arti yang sangat berbeda. Obat sederhana adalah mengambil pasangan [old, new], yang akan membuat kesalahan memicu kesalahan segera (bahkan tanpa tipe).

Perhatikan bahwa walaupun dengan tipe, kita mungkin tidak 'memberi tahu mesin apa yang kita inginkan'. Misalnya anti-pola yang disebut "pemrograman mengetik ketat" memperlakukan semua data sebagai string, yang membuatnya mudah untuk membuat argumen bercampur (seperti kasus ini), untuk lupa melakukan beberapa langkah (misalnya melarikan diri), untuk secara tidak sengaja memecahkan invarian (mis. membuat JSON yang tidak dapat dihapus), dll.

Ini juga terkait dengan "kebutaan boolean", di mana kami menghitung sekelompok boolean (atau angka, dll.) Di satu bagian kode, tetapi ketika mencoba menggunakannya di bagian lain, tidak jelas apa yang sebenarnya mereka wakili, apakah kita telah mencampuradukkannya, dll. Bandingkan ini dengan misalnya enum yang berbeda yang memiliki nama deskriptif (misalnya LOGGING_DISABLEDbukan false) dan yang menyebabkan pesan kesalahan jika kita membuatnya tercampur.

Warbo
sumber
1

karena menghilangkan kebutuhan untuk mengingat ke mana perginya argumen

Benarkah itu? Masih tidak ada jaminan argumen yang disebutkan pertama dalam nama fungsi benar-benar adalah parameter pertama. Jadi lebih baik mencarinya (atau biarkan IDE Anda melakukan itu) dan tetap menggunakan nama yang masuk akal daripada mengandalkan secara membabi buta pada nama yang cukup konyol.

Jika Anda membaca kode, Anda harus dengan mudah melihat apa yang terjadi ketika parameter dinamai sebagaimana mestinya. copy(source, destination)jauh lebih mudah dipahami daripada apa pun copyFromTheFirstLocationToTheSecondLocation(placeA, placeB).

Mengapa coders tidak mengadopsi yang pertama jika, seperti yang ditegaskan oleh penulis, lebih jelas daripada yang terakhir?

Karena ada sudut pandang berbeda pada gaya yang berbeda dan Anda dapat menemukan x penulis artikel lain yang menyatakan sebaliknya. Anda akan menjadi gila mencoba mengikuti semua yang ditulis seseorang di suatu tempat ;-)

keping
sumber
0

Saya setuju bahwa pengkodean nama parameter menjadi nama fungsi membuat penulisan dan penggunaan fungsi menjadi lebih intuitif.

copyFromSourceToDestination( // "...ahh yes, the source directory goes first"

Sangat mudah untuk melupakan urutan argumen dalam fungsi dan perintah shell dan banyak programmer bergantung pada fitur IDE atau referensi fungsi untuk alasan ini. Memiliki argumen yang dijelaskan dalam nama akan menjadi solusi yang fasih untuk ketergantungan ini.

Namun begitu ditulis, deskripsi argumen menjadi redunant ke programmer berikutnya yang harus membaca pernyataan, karena dalam banyak kasus variabel bernama akan digunakan.

copy(sourceDir, destinationDir); // "...makes sense"

Kesederhanaan ini akan memenangkan sebagian besar programmer dan saya pribadi merasa lebih mudah untuk membaca.

EDIT: Seperti yang ditunjukkan oleh @Blrfl, parameter pengkodean tidak begitu 'intuitif' karena Anda harus mengingat nama fungsi di tempat pertama. Ini membutuhkan mencari referensi fungsi atau mendapatkan bantuan dari IDE yang kemungkinan akan menyediakan informasi pemesanan parameter.

Josh Taylor
sumber
9
Jadi, jika saya bisa bermain sebagai penasihat setan sebentar: Itu hanya intuitif ketika Anda tahu nama lengkap fungsinya. Jika Anda tahu ada fungsi penyalinan dan Anda tidak ingat apakah itu copyFromSourceToDestinationatau tidak copyToDestinationFromSource, pilihan Anda menemukannya dengan coba-coba atau membaca bahan referensi. IDE yang dapat melengkapi sebagian nama hanyalah versi otomatis dari yang terakhir.
Blrfl
@ Bllfl Maksudnya copyFromSourceToDestinationadalah bahwa jika Anda pikir itu copyToDestinationFromSource, kompiler akan menemukan bug Anda, tetapi jika dipanggil copy, ia tidak akan melakukannya. Mendapatkan salinan-rutin params dengan cara yang salah itu mudah, karena strcpy, strcat dll menetapkan preseden. Dan apakah yang paling mudah dibaca? Apakah mergeLists (listA, listB, listC) membuat listA dari listB & listC, atau membaca listA & listB dan menulis listC?
Rosie F
4
@RosieF Jika saya tidak yakin apa arti argumen, saya akan membaca dokumentasi sebelum menulis kode. Selain itu, bahkan dengan nama fungsi yang lebih banyak, masih ada ruang untuk interpretasi tentang apa sebenarnya urutannya. Seseorang yang memandang dingin pada kode tidak akan dapat memahami bahwa Anda telah menetapkan konvensi bahwa apa yang ada dalam nama fungsi mencerminkan urutan argumen. Mereka masih harus mengetahuinya lebih dulu atau membaca dokumen.
Blrfl
OTOH, destinationDir.copy (sourceDir); // "... lebih masuk akal"
Kristian H
1
@ KristianH Arah apa yang dir1.copy(dir2)bekerja? Tidak ada ide. Bagaimana dengan dir1.copyTo(dir2)?
maaartinus