Mengapa efek samping dianggap jahat dalam pemrograman fungsional?

69

Saya merasa bahwa efek samping adalah fenomena alam. Tapi itu seperti tabu dalam bahasa fungsional. Apa alasannya?

Pertanyaan saya khusus untuk gaya pemrograman fungsional. Tidak semua bahasa / paradigma pemrograman.

Gulshan
sumber
6
Program tanpa efek samping tidak berguna, jadi efek sampingnya tidak jahat atau tabu. Tetapi FP mengatur pembatasan kode dengan efek samping, sehingga sebagian besar kode mungkin adalah fungsi bebas efek samping. Ini didorong karena fungsi dan subsistem bebas efek samping lebih mudah dipahami, lebih mudah dianalisis, lebih mudah diuji dan lebih mudah dioptimalkan.
JacquesB
@ JacquesB Ini akan menjadi jawaban yang bagus untuk menjelaskan mengapa mereka lebih mudah dipahami, lebih mudah untuk dianalisis, lebih mudah untuk diuji dan lebih mudah untuk dioptimalkan.
ceving

Jawaban:

72

Menulis fungsi / metode Anda tanpa efek samping - jadi itu adalah fungsi murni - membuatnya lebih mudah untuk beralasan tentang kebenaran program Anda.

Itu juga membuatnya mudah untuk menyusun fungsi-fungsi itu untuk menciptakan perilaku baru.

Ini juga memungkinkan optimasi tertentu, di mana kompiler dapat misalnya memoise hasil fungsi, atau menggunakan Penghapusan Subekspresi Umum.

Sunting: atas permintaan Benjol: Karena banyak negara Anda disimpan dalam tumpukan (aliran data, bukan aliran kontrol, seperti yang disebut Jonas di sini ), Anda dapat memparalelkan atau menyusun ulang pelaksanaan bagian-bagian perhitungan Anda yang independen dari satu sama lain. Anda dapat dengan mudah menemukan bagian-bagian independen itu karena satu bagian tidak memberikan masukan kepada yang lain.

Dalam lingkungan dengan debugger yang memungkinkan Anda memutar kembali tumpukan dan melanjutkan komputasi (seperti Smalltalk), memiliki fungsi murni berarti Anda dapat dengan mudah melihat bagaimana suatu perubahan nilai, karena status sebelumnya tersedia untuk diperiksa. Dalam perhitungan yang berat mutasi, kecuali jika Anda secara eksplisit menambahkan tindakan lakukan / batalkan ke struktur atau algoritma Anda, Anda tidak dapat melihat sejarah perhitungan. (Ini terkait dengan paragraf pertama: menulis fungsi murni membuatnya lebih mudah untuk memeriksa kebenaran program Anda.)

Frank Shearar
sumber
4
Mungkin pertimbangkan untuk menambahkan sesuatu tentang konkurensi dalam jawaban Anda?
Benjol
5
Fungsi bebas efek samping lebih mudah untuk diuji dan digunakan kembali.
LennyProgrammers
@ Lenny222: reuse adalah apa yang saya mengisyaratkan dengan berbicara tentang komposisi fungsi.
Frank Shearar
@ Frank: Ah, ok, penjelajahan juga dangkal. :)
LennyProgrammers
@ Lenny222: Tidak apa-apa; itu mungkin hal yang baik untuk mengejanya.
Frank Shearar
23

Dari artikel tentang pemrograman Fungsional :

Dalam praktiknya, aplikasi perlu memiliki beberapa efek samping. Simon Peyton-Jones, kontributor utama untuk bahasa pemrograman fungsional Haskell, mengatakan hal berikut: "Pada akhirnya, setiap program harus memanipulasi keadaan. Program yang tidak memiliki efek samping apa pun adalah semacam kotak hitam. Yang bisa Anda katakan hanyalah bahwa kotak semakin panas. " ( http://oscon.blip.tv/file/324976 ) Kuncinya adalah untuk membatasi efek samping, mengidentifikasi dengan jelas, dan menghindari menyebarkannya di seluruh kode.

Peter Stuifzand
sumber
23

Anda salah, pemrograman fungsional mempromosikan efek samping yang terbatas untuk membuat program mudah dipahami dan dioptimalkan. Bahkan Haskell memungkinkan Anda menulis ke file.

Pada dasarnya apa yang saya katakan adalah bahwa pemrogram fungsional tidak menganggap efek samping itu jahat, mereka hanya berpikir membatasi penggunaan efek samping itu baik. Saya tahu itu mungkin tampak seperti perbedaan yang sederhana tetapi membuat semua perbedaan.

Kekacauan Kekacauan
sumber
Itulah sebabnya mereka "sesuatu seperti tabu" - FPL mendorong Anda untuk membatasi efek samping.
Frank Shearar
+1 untuk pendekatan. efek samping masih ada. memang, mereka terbatas
Belun
Untuk klarifikasi, saya belum mengatakan 'mengapa efek samping tidak diperbolehkan dalam pemrograman fungsional' atau 'mengapa efek samping tidak diperlukan'. Saya tahu itu diperbolehkan dalam bahasa fungsional dan kadang-kadang adalah suatu keharusan. Tetapi sangat tidak disarankan dalam pemrograman fungsional. Mengapa? Itu pertanyaan saya.
Gulshan
@Gulshan - Karena efek samping membuat program lebih sulit untuk dipahami dan dioptimalkan.
ChaosPandion
dalam kasus haskell, poin utamanya bukan untuk "membatasi efek samping". efek samping tidak mungkin diungkapkan dalam LANGUAGE. fungsi apa yang readFilesedang dilakukan adalah mendefinisikan urutan tindakan. urutan ini secara fungsional murni dan seperti pohon abstrak yang menggambarkan APA yang harus dilakukan. efek samping kotor yang sebenarnya kemudian dilakukan oleh runtime.
sara
13

Beberapa catatan:

  • Fungsi tanpa efek samping dapat dengan mudah dieksekusi secara paralel, sedangkan fungsi dengan efek samping biasanya memerlukan semacam sinkronisasi.

  • Fungsi tanpa efek samping memungkinkan pengoptimalan yang lebih agresif (misalnya dengan menggunakan cache hasil secara transparan), karena selama kita mendapatkan hasil yang benar, bahkan tidak masalah apakah fungsi itu benar - benar dieksekusi atau tidak.

pengguna281377
sumber
Poin yang sangat menarik: bahkan tidak masalah apakah fungsi itu benar-benar dieksekusi . Akan menarik untuk berakhir dengan kompiler yang dapat menyingkirkan panggilan berikutnya untuk fungsi bebas efek samping yang diberikan parameter yang setara.
Noel Widmer
1
@NoelWidmer Sesuatu seperti itu sudah ada. Oracle PL / SQL menawarkan deterministicklausa untuk fungsi tanpa efek samping, sehingga mereka tidak dieksekusi lebih sering daripada yang diperlukan.
user281377
Wow! Namun, saya pikir bahasa harus semantik ekspresif sehingga kompiler dapat mengetahuinya sendiri tanpa harus menentukan bendera eksplisit (saya tidak yakin apa klausa itu). Solusinya bisa dengan menentukan parameter yang bisa berubah / tidak berubah, secara umum, ini membutuhkan sistem tipe yang kuat di mana asumsi tentang efek samping dapat dibuat oleh kompiler. Dan fitur tersebut harus dapat dimatikan jika diinginkan. Opt-out, bukan opt-in. Itu hanya pendapat saya, berdasarkan pengetahuan terbatas yang saya miliki sejak saya membaca jawaban Anda :)
Noel Widmer
The deterministicklausul hanya kata kunci yang memberitahu compiler bahwa ini adalah fungsi deterministik, sebanding dengan bagaimana finalkata kunci di Jawa memberitahu compiler bahwa variabel tidak dapat berubah.
user281377
11

Saya terutama bekerja dalam kode fungsional sekarang, dan dari perspektif itu tampak sangat jelas. Efek samping membuat besar beban mental pada programmer mencoba membaca dan memahami kode. Anda tidak menyadari beban itu sampai Anda bebas darinya untuk sementara waktu, lalu tiba-tiba harus membaca kode dengan efek samping lagi.

Pertimbangkan contoh sederhana ini:

val foo = 42
// Several lines of code you don't really care about, but that contain a
// lot of function calls that use foo and may or may not change its value
// by side effect.

// Code you are troubleshooting
// What's the expected value of foo here?

Dalam bahasa fungsional, saya tahu itu foomasih 42. Saya bahkan tidak perlu melihat kode di antaranya, apalagi memahaminya, atau melihat implementasi dari fungsi yang dipanggil.

Semua hal tentang konkurensi dan paralelisasi dan optimisasi itu bagus, tetapi itulah yang dimasukkan oleh para ilmuwan komputer pada brosur. Tidak perlu bertanya-tanya siapa yang mengubah variabel Anda dan kapan hal yang benar-benar saya nikmati dalam latihan sehari-hari.

Karl Bielefeldt
sumber
6

Sedikit bahasa yang tidak memungkinkan menyebabkan efek samping. Bahasa yang sepenuhnya bebas efek samping akan sangat sulit (hampir tidak mungkin) untuk digunakan, kecuali dalam kapasitas yang sangat terbatas.

Mengapa efek samping dianggap jahat?

Karena mereka membuatnya jauh lebih sulit untuk berpikir tentang apa yang dilakukan suatu program, dan untuk membuktikan bahwa itu melakukan apa yang Anda harapkan.

Pada tingkat yang sangat tinggi, bayangkan menguji seluruh situs web 3-tier dengan hanya pengujian kotak hitam. Tentu, itu bisa dilakukan, tergantung pada skalanya. Tetapi tentu saja ada banyak duplikasi yang terjadi. Dan jika ada yang bug (yang berhubungan dengan efek samping), maka Anda bisa berpotensi merusak seluruh sistem untuk pengujian lebih lanjut, sampai bug ini didiagnosis dan tetap, dan memperbaiki dikerahkan untuk lingkungan pengujian.

Manfaat

Sekarang, turunkan itu. Jika Anda cukup pandai menulis kode bebas efek samping, seberapa cepat Anda akan mempertimbangkan apa yang dilakukan oleh beberapa kode yang ada? Seberapa cepat Anda bisa menulis unit test? Seberapa yakin Anda akan merasa bahwa kode tanpa efek samping dijamin bebas bug, dan bahwa pengguna dapat membatasi eksposur mereka untuk bug itu tidak memiliki?

Jika kode tidak memiliki efek samping, kompiler juga dapat memiliki optimasi tambahan yang dapat dilakukan. Mungkin lebih mudah untuk mengimplementasikan optimasi tersebut. Mungkin jauh lebih mudah untuk bahkan membuat konsep optimasi untuk kode bebas efek samping, yang berarti bahwa vendor kompiler Anda mungkin menerapkan optimasi yang sulit untuk mustahil dalam kode dengan efek samping.

Concurrency juga secara drastis lebih mudah untuk diimplementasikan, untuk secara otomatis menghasilkan, dan untuk mengoptimalkan ketika kode tidak memiliki efek samping. Ini karena semua bagian dapat dievaluasi dengan aman dalam urutan apa pun. Mengizinkan pemrogram untuk menulis kode yang sangat konkuren secara luas dianggap sebagai tantangan besar berikutnya yang perlu ditangani oleh Ilmu Komputer, dan salah satu dari sedikit lindung nilai yang tersisa terhadap Hukum Moore .

Merlyn Morgan-Graham
sumber
1
Ada membuatnya sangat sulit untuk menyebabkan efek samping. Itu bukan tidak mungkin, tetapi Anda jelas tahu apa yang Anda lakukan saat itu.
mouviciel
@mouviciel: Saya pikir setidaknya ada beberapa bahasa yang berguna di luar sana yang membuat efek samping menjadi sangat sulit, dan mencoba untuk memindahkannya ke Monads.
Merlyn Morgan-Graham
4

Efek samping seperti "kebocoran" dalam kode Anda yang perlu ditangani nanti, baik oleh Anda atau rekan kerja yang tidak curiga.

Bahasa fungsional menghindari variabel keadaan dan data yang bisa berubah sebagai cara membuat kode kurang tergantung konteks dan lebih modular. Modularitas memastikan bahwa pekerjaan satu pengembang tidak akan memengaruhi / merusak pekerjaan pengembang lain.

Penskalaan laju pengembangan dengan ukuran tim, adalah "cawan suci" pengembangan perangkat lunak saat ini. Ketika bekerja dengan programmer lain, beberapa hal sama pentingnya dengan modularitas. Bahkan efek samping logis yang paling sederhana pun membuat kolaborasi menjadi sangat sulit.

Ami
sumber
+1 - "atau rekan kerja yang tidak curiga"
Merlyn Morgan-Graham
1
-1 untuk efek samping menjadi "kebocoran yang perlu ditangani." Menciptakan "efek samping" (kode non-murni-fungsional) adalah seluruh tujuan penulisan program komputer non-sepele.
Mason Wheeler
Komentar ini muncul enam tahun kemudian, tetapi ada efek samping dan kemudian ada efek samping. Jenis efek samping yang diinginkan, melakukan I / O dan sebagainya, memang perlu untuk program apa pun, karena Anda perlu memberikan hasil kepada pengguna, entah bagaimana - tetapi jenis efek samping lainnya, di mana kode Anda berubah status tanpa efek yang baik. alasan seperti melakukan I / O, memang merupakan "kebocoran" yang perlu ditangani nanti. Ide dasarnya adalah pemisahan perintah-kueri : fungsi yang mengembalikan nilai seharusnya tidak memiliki efek samping.
rmunn
4

Nah, IMHO, ini sangat munafik. Tidak ada yang suka efek samping, tetapi semua orang membutuhkannya.

Apa yang sangat berbahaya tentang efek samping adalah bahwa jika Anda memanggil suatu fungsi, maka ini mungkin memiliki efek tidak hanya pada cara fungsi berperilaku ketika dipanggil lain kali, tetapi mungkin memiliki efek ini pada fungsi lain. Dengan demikian efek samping menimbulkan perilaku yang tidak terduga dan ketergantungan nontrivial.

Pemrograman paradigma seperti OO dan fungsional keduanya mengatasi masalah ini. OO mengurangi masalah dengan memaksakan pemisahan kekhawatiran. Ini berarti status aplikasi, yang terdiri dari banyak data yang dapat diubah, dienkapsulasi menjadi objek, yang masing-masing bertanggung jawab untuk mempertahankan statusnya sendiri saja. Dengan cara ini risiko ketergantungan berkurang dan masalah jauh lebih terisolasi dan lebih mudah dilacak.

Pemrograman fungsional mengambil pendekatan yang jauh lebih radikal, di mana status aplikasi tidak dapat diubah dari perspektif pemrogram. Ini adalah ide yang bagus, tetapi menjadikan bahasa itu sendiri tidak berguna. Mengapa? Karena SETIAP I / O-operasi memiliki efek samping. Segera setelah Anda membaca dari aliran input apa pun, status aplikasi Anda kemungkinan akan berubah, karena kali berikutnya Anda menjalankan fungsi yang sama, hasilnya kemungkinan akan berbeda. Anda mungkin membaca data yang berbeda, atau - juga kemungkinan - operasi mungkin gagal. Hal yang sama berlaku untuk output. Bahkan keluaran adalah operasi dengan efek samping. Ini bukan apa-apa yang sering Anda sadari saat ini, tetapi bayangkan Anda hanya memiliki 20K untuk output Anda dan jika Anda output lagi, aplikasi Anda macet karena Anda kehabisan ruang disk atau apa pun.

Jadi ya, efek sampingnya buruk dan berbahaya dari sudut pandang seorang programmer. Sebagian besar bug berasal dari cara bagian-bagian tertentu dari keadaan aplikasi yang saling terkait dalam cara yang hampir tidak jelas, melalui efek samping yang tidak dipertimbangkan dan seringkali tidak perlu. Dari perspektif pengguna, efek samping adalah titik menggunakan komputer. Mereka tidak peduli dengan apa yang terjadi di dalam atau bagaimana hal itu diatur. Mereka melakukan sesuatu dan berharap komputer untuk MENGUBAH sesuai.

back2dos
sumber
Menariknya pemrograman logika tidak hanya tidak memiliki efek samping fungsional; tetapi Anda bahkan tidak bisa mengubah nilai variabel yang pernah ditetapkan.
Ilan
@Lan: Ini juga berlaku untuk beberapa bahasa fungsional dan itu adalah gaya yang mudah diadopsi.
back2dos
"Pemrograman fungsional mengambil pendekatan yang jauh lebih radikal, di mana keadaan aplikasi tidak dapat diubah dari perspektif pemrogram. Ini adalah ide yang bagus, tetapi menjadikan bahasa tidak berguna dengan sendirinya. Mengapa? Karena SETIAP operasi I / O apa pun memiliki sisi efek ": FP tidak melarang efek samping, melainkan membatasi mereka ketika tidak diperlukan. Misalnya (1) efek samping I / O -> diperlukan; (2) tidak menghitung fungsi agregat dari urutan nilai -> efek samping (misalnya untuk loop dengan variabel akumulator).
Giorgio
2

Setiap efek samping memperkenalkan parameter input / output ekstra yang harus diperhitungkan saat pengujian.

Ini membuat validasi kode jauh lebih kompleks karena lingkungan tidak dapat dibatasi hanya pada kode yang divalidasi, tetapi harus membawa sebagian atau semua lingkungan sekitarnya (global yang diperbarui tinggal dalam kode itu di sana, yang pada gilirannya tergantung pada kode, yang pada gilirannya tergantung pada hidup di dalam server Java EE lengkap ....)

Dengan mencoba menghindari efek samping, Anda membatasi jumlah eksternalisme yang diperlukan untuk menjalankan kode.


sumber
1

Dalam pengalaman saya desain yang baik dalam pemrograman Object Orientated mengamanatkan penggunaan fungsi yang memiliki efek samping.

Misalnya, ambil aplikasi desktop UI dasar. Saya mungkin memiliki program yang sedang berjalan yang memiliki tumpukan objek grafik yang mewakili keadaan saat ini dari model domain program saya. Pesan tiba ke objek dalam grafik itu (misalnya, melalui metode panggilan dipanggil dari pengontrol lapisan UI). Grafik objek (model domain) pada heap dimodifikasi sebagai respons terhadap pesan. Pengamat model diberitahu tentang perubahan, UI dan mungkin sumber daya lain dimodifikasi.

Jauh dari kejahatan, pengaturan yang benar dari efek samping heap-modifying dan modifying screen ini adalah inti dari desain OO (dalam hal ini pola MVC).

Tentu saja, itu tidak berarti bahwa metode Anda harus memiliki efek samping arbiter. Dan fungsi bebas efek samping memang memiliki tempat dalam meningkatkan keterbacaan dan kadang-kadang kinerja, kode Anda.

flamingpenguin
sumber
1
Pengamat (termasuk UI) harus mencari tahu tentang modifikasi melalui berlangganan pesan / acara yang dikirim objek Anda. Ini bukan efek samping kecuali objek memodifikasi langsung pengamat - yang akan menjadi desain yang buruk.
ChrisF
1
@ ChrisF Paling defintely itu adalah efek samping. Pesan yang diteruskan ke pengamat (dalam bahasa OO yang kemungkinan besar pemanggilan metode pada antarmuka) akan mengarah ke keadaan komponen UI pada perubahan tumpukan (dan objek tumpukan ini dapat dilihat oleh bagian lain dari program). Komponen UI bukanlah parameter metode atau nilai pengembalian. Dalam arti formal, agar suatu fungsi menjadi bebas efek samping, ia harus idempoten. Pemberitahuan dalam pola MVC tidak, misalnya UI dapat menampilkan daftar pesan yang telah diterimanya - konsol - menyebutnya dua kali menghasilkan status program yang berbeda.
flamingpenguin
0

Kejahatan sedikit di atas .. itu semua tergantung pada konteks penggunaan bahasa.

Pertimbangan lain untuk yang telah disebutkan adalah bahwa hal itu membuat pembuktian kebenaran suatu program menjadi lebih sederhana jika tidak ada efek samping fungsional.

Ilan
sumber
0

Seperti yang ditunjukkan oleh pertanyaan di atas, bahasa fungsional tidak terlalu mencegah kode dari memiliki efek samping seperti menyediakan alat untuk mengelola efek samping apa yang dapat terjadi dalam bagian kode tertentu dan kapan.

Ini ternyata memiliki konsekuensi yang sangat menarik. Pertama, dan yang paling jelas, ada banyak hal yang dapat Anda lakukan dengan kode bebas efek samping, yang telah dijelaskan. Tetapi ada hal-hal lain yang dapat kita lakukan juga, bahkan ketika bekerja dengan kode yang memiliki efek samping:

  • Dalam kode dengan status yang bisa berubah, kita dapat mengelola ruang lingkup negara sedemikian rupa untuk memastikan secara statis bahwa itu tidak dapat bocor di luar fungsi yang diberikan, ini memungkinkan kita untuk mengumpulkan sampah tanpa penghitungan referensi atau skema gaya mark-and-sweep , namun tetap yakin bahwa tidak ada referensi yang bertahan. Jaminan yang sama juga berguna untuk menjaga informasi sensitif privasi, dll. (Ini dapat dicapai menggunakan ST monad di haskell)
  • Saat memodifikasi keadaan bersama di beberapa utas, kita dapat menghindari perlunya kunci dengan melacak perubahan dan melakukan pembaruan atom pada akhir transaksi, atau memutar kembali transaksi dan mengulanginya jika utas lain membuat modifikasi yang bertentangan. Ini hanya dapat dicapai karena kami dapat memastikan bahwa kode tidak memiliki efek selain dari modifikasi negara (yang dapat kami tinggalkan dengan senang hati). Ini dilakukan oleh monad STM (Software Transactional Memory) di Haskell.
  • kita dapat melacak efek kode dan mengirimnya ke kotak pasir secara sepele, memfilter efek apa pun yang mungkin perlu dilakukan untuk memastikan keamanannya, sehingga memungkinkan (misalnya) kode yang dimasukkan pengguna dijalankan dengan aman di situs web
Jules
sumber
0

Dalam basis kode yang kompleks, interaksi kompleks dari efek samping adalah hal paling sulit yang saya temukan untuk dipikirkan. Saya hanya bisa berbicara secara pribadi dengan cara otak saya bekerja. Efek samping dan keadaan persisten dan input bermutasi dan sebagainya membuat saya harus berpikir tentang "kapan" dan "di mana" sesuatu terjadi dengan alasan tentang kebenaran, bukan hanya "apa" yang terjadi di setiap fungsi individu.

Saya tidak bisa hanya fokus pada "apa". Saya tidak dapat menyimpulkan setelah benar-benar menguji suatu fungsi yang menyebabkan efek samping yang akan menyebarkan udara keandalan di seluruh kode yang menggunakannya, karena penelepon mungkin masih menyalahgunakannya dengan memanggilnya pada waktu yang salah, dari utas yang salah, di salah memesan. Sementara itu fungsi yang tidak menyebabkan efek samping dan hanya mengembalikan output baru yang diberikan input (tanpa menyentuh input) sangat tidak mungkin untuk disalahgunakan dengan cara ini.

Tapi saya tipe pragmatis, saya pikir, atau setidaknya mencoba untuk menjadi, dan saya tidak berpikir kita harus menghapus semua efek samping seminimal mungkin untuk alasan tentang kebenaran kode kita (paling tidak paling tidak Saya akan menemukan ini sangat sulit dilakukan dalam bahasa seperti C). Di mana saya merasa sangat sulit untuk beralasan tentang kebenaran adalah ketika kita memiliki kombinasi aliran kontrol yang kompleks dan efek samping.

Alur kontrol kompleks kepada saya adalah yang bersifat seperti grafik, sering rekursif atau rekursif (antrian acara, misalnya, yang tidak secara langsung menyebut peristiwa secara rekursif tetapi bersifat "rekursif-suka"), mungkin melakukan hal-hal dalam proses melintasi struktur grafik tertaut yang sebenarnya, atau memproses antrian peristiwa non-homogen yang berisi campuran eklektik peristiwa untuk diproses membawa kita ke semua jenis bagian basis kode yang berbeda dan semua memicu efek samping yang berbeda. Jika Anda mencoba untuk menggambar semua tempat yang pada akhirnya Anda akan berakhir dalam kode, itu akan menyerupai grafik yang kompleks dan berpotensi dengan node dalam grafik yang Anda tidak pernah harapkan akan ada di sana pada saat itu, dan mengingat bahwa mereka semua menyebabkan efek samping,

Bahasa fungsional dapat memiliki aliran kontrol yang sangat kompleks dan rekursif, tetapi hasilnya sangat mudah dipahami dalam hal kebenaran karena tidak ada segala macam efek samping eklektik yang terjadi dalam proses. Hanya ketika aliran kontrol yang kompleks memenuhi efek samping eklektik, saya merasa sakit kepala untuk mencoba memahami keseluruhan dari apa yang terjadi dan apakah itu akan selalu melakukan hal yang benar.

Jadi ketika saya memiliki kasus-kasus itu, saya sering merasa sangat sulit, jika bukan tidak mungkin, merasa sangat yakin tentang kebenaran kode tersebut, apalagi sangat yakin bahwa saya dapat membuat perubahan pada kode tersebut tanpa tersandung pada sesuatu yang tidak terduga. Jadi solusinya bagi saya ada yang menyederhanakan aliran kontrol atau meminimalkan / menyatukan efek samping (dengan menyatukan, maksud saya seperti hanya menyebabkan satu jenis efek samping ke banyak hal selama fase tertentu dalam sistem, bukan dua atau tiga atau lusin). Saya perlu salah satu dari dua hal itu terjadi untuk memungkinkan otak bodoh saya merasa yakin tentang kebenaran kode yang ada dan kebenaran perubahan yang saya perkenalkan. Sangat mudah untuk merasa yakin tentang kebenaran kode yang memperkenalkan efek samping jika efek sampingnya seragam dan sederhana bersama dengan aliran kontrol, seperti:

for each pixel in an image:
    make it red

Sangat mudah untuk alasan tentang kebenaran kode tersebut, tetapi terutama karena efek sampingnya sangat seragam dan aliran kontrolnya sangat sederhana. Tetapi katakanlah kita memiliki kode seperti ini:

for each vertex to remove in a mesh:
     start removing vertex from connected edges():
         start removing connected edges from connected faces():
             rebuild connected faces excluding edges to remove():
                  if face has less than 3 edges:
                       remove face
             remove edge
         remove vertex

Maka ini adalah pseudocode yang terlalu sederhana yang biasanya melibatkan lebih banyak fungsi dan loop bersarang dan lebih banyak hal yang harus dilakukan (memperbarui beberapa peta tekstur, bobot tulang, keadaan pemilihan, dll), tetapi bahkan kodesemu membuatnya sangat sulit untuk alasan tentang kebenaran karena interaksi aliran kontrol seperti grafik yang kompleks dan efek samping yang terjadi. Jadi satu strategi untuk menyederhanakan itu adalah menunda pemrosesan dan hanya fokus pada satu jenis efek samping pada suatu waktu:

for each vertex to remove:
     mark connected edges
for each marked edge:
     mark connected faces
for each marked face:
     remove marked edges from face
     if num_edges < 3:
          remove face

for each marked edge:
     remove edge
for each vertex to remove:
     remove vertex

... sesuatu untuk efek ini sebagai satu iterasi penyederhanaan. Itu berarti kita melewati data beberapa kali yang pasti menimbulkan biaya komputasi, tetapi kita sering menemukan kita dapat multithread kode yang dihasilkan lebih mudah, sekarang efek samping dan aliran kontrol telah mengambil sifat yang seragam dan lebih sederhana ini. Lebih jauh, setiap loop dapat dibuat lebih ramah-cache daripada melintasi grafik yang terhubung dan menyebabkan efek samping saat berjalan (mis: gunakan bit paralel yang disetel untuk menandai apa yang perlu dilalui sehingga kita dapat melakukan pass yang ditangguhkan dalam urutan berurutan yang diurutkan) menggunakan bitmasks dan FFS). Tetapi yang paling penting, saya menemukan versi kedua jauh lebih mudah untuk dipikirkan dalam hal kebenaran serta perubahan tanpa menyebabkan bug. Yang seperti itu'

Lagi pula, kita perlu efek samping terjadi di beberapa titik, atau kita hanya akan memiliki fungsi yang menghasilkan data tanpa tempat. Seringkali kita perlu merekam sesuatu ke file, menampilkan sesuatu ke layar, mengirim data melalui soket, sesuatu seperti ini, dan semua ini adalah efek samping. Tetapi kita pasti dapat mengurangi jumlah efek samping berlebihan yang terjadi, dan juga mengurangi jumlah efek samping yang terjadi ketika kontrol mengalir sangat rumit, dan saya pikir akan jauh lebih mudah untuk menghindari bug jika kita melakukannya.


sumber
-1

Itu tidak jahat. Pendapat saya, perlu untuk membedakan dua jenis fungsi - dengan efek samping dan tanpa. Fungsi tanpa efek samping: - mengembalikan selalu sama dengan argumen yang sama, jadi misalnya fungsi tersebut tanpa argumen tidak masuk akal. - Itu juga berarti, bahwa urutan fungsi yang disebut beberapa fungsi tidak dimainkan - harus dapat dijalankan dan dapat di-debug hanya sendiri (!), Tanpa kode lain. Dan sekarang, lol, lihat apa yang dibuat JUnit. Sebuah fungsi dengan efek samping: - memiliki semacam "kebocoran", yang dapat disorot secara otomatis - sangat penting dengan men-debug dan mencari kesalahan, yang umumnya disebabkan oleh efek samping. - Setiap fungsi dengan efek samping juga memiliki "bagian" dari dirinya sendiri tanpa efek samping, yang juga dapat dipisahkan secara otomatis. Jadi kejahatan adalah efek sampingnya,

pengguna225623
sumber
ini tampaknya tidak menawarkan sesuatu yang substansial atas poin yang dibuat dan dijelaskan dalam 12 jawaban sebelumnya
nyamuk