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 assertExpectedEqualsActual
sebagai 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 assertEqual
kasus 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_DISABLED
bukan false
) dan yang menyebabkan pesan kesalahan jika kita membuatnya tercampur.