Dalam pemrograman, apa manfaat transparansi referensial ?
RT membuat salah satu perbedaan utama antara paradigma fungsional dan imperatif, dan sering digunakan oleh pendukung paradigma fungsional sebagai keuntungan yang jelas dibandingkan paradigma imperatif; tetapi dalam semua upaya mereka, para advokat ini tidak pernah menjelaskan mengapa itu bermanfaat bagi saya sebagai seorang programmer .
Tentu, mereka akan memiliki penjelasan akademis tentang seberapa "murni" dan "elegan" itu, tetapi bagaimana cara membuatnya lebih baik daripada kode yang kurang "murni"? Apa manfaatnya bagi saya dalam pemrograman sehari-hari saya?
Catatan: Ini bukan duplikat dari Apa itu transparansi referensial? Yang terakhir membahas topik apa itu RT, sementara pertanyaan ini menekankan manfaatnya (yang mungkin tidak begitu intuitif).
sumber
Jawaban:
Manfaatnya adalah fungsi murni membuat kode Anda lebih mudah untuk dipikirkan. Atau, dengan kata lain, efek samping meningkatkan kompleksitas kode Anda.
Ambil contoh
computeProductPrice
metode.Metode murni akan meminta Anda untuk kuantitas produk, mata uang, dll. Anda tahu bahwa setiap kali metode dipanggil dengan argumen yang sama, itu akan selalu menghasilkan hasil yang sama.
Metode non-murni akan lebih kompleks untuk digunakan dan debug. Karena itu tergantung pada keadaan variabel selain argumen dan mungkin mengubahnya, itu berarti bahwa itu dapat menghasilkan hasil yang berbeda ketika dipanggil beberapa kali, atau tidak memiliki perilaku yang sama ketika tidak dipanggil sama sekali atau dipanggil terlalu cepat atau terlambat.
Contoh
Bayangkan ada metode dalam kerangka kerja yang mem-parsing angka:
Itu tidak memiliki transparansi referensial, karena itu tergantung pada:
Variabel lingkungan yang menentukan sistem penomoran, yaitu Basis 10 atau sesuatu yang lain.
Variabel dalam
math
pustaka yang menentukan ketepatan angka untuk diuraikan. Jadi dengan nilai1
, parsing"12.3456"
akan memberikan string12.3
.Budaya, yang mendefinisikan pemformatan yang diharapkan. Misalnya, dengan
fr-FR
, parsing"12.345"
akan memberi12345
, karena karakter pemisahan seharusnya,
, bukan.
Bayangkan betapa mudah atau sulitnya bekerja dengan metode seperti itu. Dengan input yang sama, Anda dapat memiliki hasil yang sangat berbeda tergantung pada saat Anda memanggil metode, karena sesuatu, di suatu tempat mengubah variabel lingkungan atau beralih budaya atau mengatur presisi yang berbeda. Karakter non-deterministik dari metode ini akan menyebabkan lebih banyak bug dan lebih banyak mimpi buruk debugging. Memanggil
math.parse("12345")
dan memperoleh5349
sebagai jawaban karena beberapa kode paralel menguraikan angka oktal tidak baik.Bagaimana cara memperbaiki metode yang jelas-jelas rusak ini? Dengan memperkenalkan transparansi referensial. Dengan kata lain, dengan menyingkirkan keadaan global, dan memindahkan semuanya ke parameter metode:
Sekarang metodenya murni, Anda tahu bahwa tidak peduli kapan Anda memanggil metode, itu akan selalu menghasilkan hasil yang sama untuk argumen yang sama.
sumber
packet = socket.recv()
transparan referensial agak mengalahkan titik fungsi.invariant
? Entah mereka sama denganen_us
, dalam hal ini, mengapa repot, atau mereka berkorespondensi dengan negara lain, dalam hal ini, yang mana dan mengapa yang ini bukannyaen_us
, atau mereka memiliki aturan khusus yang tidak cocok dengan negara mana pun , yang tidak akan berguna. Tidak ada "jawaban sejati" antara12,345.67
dan12 345,67
: "aturan default" apa pun akan berfungsi untuk beberapa negara, dan tidak akan berfungsi untuk negara lain.12345
diuraikan sebagai 12345,12 345
atau12,345
atau12.345
ada kesalahan.12.345
diurai sebagai angka floating-point yang tidak berubah selalu menghasilkan 12,345, sesuai dengan konvensi bahasa pemrograman menggunakan. sebagai pemisah desimal. String diurutkan berdasarkan titik kode Unicode dan case-sensitive. Dan seterusnya.Apakah Anda sering menambahkan titik istirahat ke titik dalam kode Anda dan menjalankan aplikasi di debugger untuk mengetahui apa yang terjadi? Jika ya, itu sebagian besar karena Anda tidak menggunakan transparansi referensial (RT) dalam desain Anda. Jadi harus menjalankan kode untuk mengetahui fungsinya.
Inti dari ke RT adalah bahwa kodenya sangat deterministik, yaitu Anda dapat membaca kodenya dan mencari tahu apa yang dilakukannya, setiap saat, untuk rangkaian input yang sama. Setelah Anda mulai menambahkan dalam variabel yang bermutasi, beberapa di antaranya memiliki cakupan di luar fungsi tunggal, Anda tidak bisa hanya membaca kode. Kode tersebut harus dijalankan, baik di kepala Anda atau di debugger, untuk mengetahui cara kerjanya.
Kode yang lebih sederhana adalah membaca dan bernalar, semakin mudah untuk memelihara dan menemukan bug, sehingga menghemat waktu dan uang untuk Anda dan majikan Anda.
sumber
Orang-orang membuang istilah "lebih mudah untuk dipikirkan," tetapi tidak pernah menjelaskan apa artinya itu. Perhatikan contoh berikut:
Apakah
result1
danresult2
sama atau berbeda? Tanpa transparansi referensial, Anda tidak tahu. Anda harus benar-benar membaca isi darifoo
untuk memastikan, dan mungkin isi dari setiap fungsifoo
memanggil, dan sebagainya.Orang-orang tidak menyadari beban ini karena mereka terbiasa dengan itu, tetapi jika Anda bekerja di lingkungan yang murni fungsional selama satu atau dua bulan kemudian kembali, Anda akan merasakannya, dan itu adalah masalah besar .
Ada begitu banyak mekanisme pertahanan yang dilakukan orang untuk mengatasi kurangnya transparansi referensial. Sebagai contoh kecil saya, saya mungkin ingin
result1
mengingat-ingat, karena saya tidak akan tahu apakah itu akan berubah. Kemudian saya memiliki kode dengan dua status: sebelumresult1
disimpan dan sesudahnya. Dengan transparansi referensial, saya bisa menghitung ulang dengan mudah, asalkan perhitungan ulang tidak memakan waktu.sumber
result1
danresult2
itu sama. Aspek penting lainnya adalah bahwa jikafoo("bar", 12)
transparan referensial, maka Anda tidak perlu bertanya pada diri sendiri apakah panggilan ini telah menghasilkan beberapa efek di tempat lain (mengatur beberapa variabel? Menghapus file? Apa pun).Saya akan mengatakan: transparansi referensial tidak hanya baik untuk pemrograman fungsional tetapi untuk semua orang yang bekerja dengan fungsi karena mengikuti prinsip paling tidak heran.
Anda memiliki fungsi dan dapat memberi alasan yang lebih baik tentang apa yang dilakukannya karena tidak ada faktor eksternal yang perlu Anda perhitungkan, karena input yang diberikan output akan selalu sama. Bahkan dalam bahasa imperatif saya, saya mencoba mengikuti paradigma ini sebanyak mungkin, hal berikutnya yang pada dasarnya secara otomatis mengikuti dari ini adalah: fungsi-fungsi kecil yang mudah dimengerti daripada fungsi-fungsi garis 1000+ mengerikan yang terkadang saya jalankan.
Fungsi-fungsi besar itu melakukan sihir dan saya takut menyentuhnya karena mereka dapat pecah dengan cara yang spektakuler.
Jadi fungsi murni bukan hanya untuk pemrograman fungsional, tetapi untuk setiap program.
sumber