Apa itu "efek samping?"

88

Saya belum mengerti konsep efek samping.

  • Apa efek samping dalam pemrograman?
  • Apakah tergantung pada bahasa pemrograman?
  • Adakah efek samping eksternal dan internal?

Tolong beri beberapa contoh penyebab yang menciptakan efek samping.

Amir Rezaei
sumber
7
Kedengarannya sangat mirip pekerjaan rumah.
gnasher729
3
@ gnasher729 yang peduli ini sangat berguna :)
Charlie Parker

Jawaban:

108

Sebuah efek samping mengacu hanya untuk modifikasi semacam negara - misalnya:

  • Mengubah nilai variabel;
  • Menulis beberapa data ke disk;
  • Mengaktifkan atau menonaktifkan tombol di Antarmuka Pengguna.

Bertentangan dengan apa yang dikatakan beberapa orang:

  • Efek samping yang tidak harus disembunyikan atau tak terduga (itu bisa, tapi itu tidak ada hubungannya dengan definisi yang berlaku untuk ilmu komputer);

  • Efek samping tidak ada hubungannya dengan idempotensi. Fungsi idempoten dapat memiliki efek samping, dan fungsi non-idempoten mungkin tidak memiliki efek samping (seperti mendapatkan tanggal dan waktu sistem saat ini).

Ini sangat sederhana. Efek samping = mengubah sesuatu di suatu tempat.

PS Seperti yang ditunjukkan komentator benjol, beberapa orang mungkin menggabungkan definisi efek samping dengan definisi fungsi murni , yang merupakan fungsi yang (a) idempoten dan (b) tidak memiliki efek samping. Satu tidak menyiratkan yang lain dalam ilmu komputer umum, tetapi bahasa pemrograman fungsional biasanya akan cenderung menegakkan kedua kendala.

Aaronaught
sumber
38
Ungkapan "efek samping" membuatnya terdengar seperti sesuatu yang lain sedang diubah selain apa yang dimaksudkan. Dalam kedokteran, obat akan memiliki efek utama mengurangi rasa sakit, dan kadang-kadang efek samping dari menyebabkan pendarahan hidung, pusing, dll ... tujuan dari obat ini bukan untuk menyebabkan pendarahan pada hidung tetapi kadang-kadang itu terjadi sebagai hasil tambahan yang tidak diinginkan .
FrustratedWithFormsDesigner
15
@Frustrated: +1. Setiap kali saya melihat istilah itu saya tidak bisa tidak bertanya-tanya apakah itu tidak dipilih oleh advokat FP untuk menciptakan konotasi yang secara halus menyeramkan.
Mason Wheeler
6
@Mason Wheeler. Itu ada jauh sebelum FP. Dan itu bukan konotasi yang menyeramkan. Itu benar-benar jahat dan selalu terjadi. Selama 3 dekade saya mengkodekan, pernyataan "crypto-assignment" - efek samping - telah meresahkan orang. Pernyataan tugas lama yang sederhana jauh lebih mudah untuk diatasi.
S.Lott
7
@Mason Wheeler: Dalam C ++a.. Tidak terlihat seperti tugas. b = ++a;memiliki dua efek samping. Yang jelas dan tugas crypto a. Itulah jenis efek samping yang diinginkan (bagi sebagian orang). Tetapi telah disebut efek samping untuk seluruh karier saya agar tidak halus.
S.Lott
5
@ Zakary, silakan lihat poin terakhir dalam jawaban saya. Yang Anda maksud adalah perilaku idempoten (atau ketiadaan). Itu tidak memberi tahu Anda apa-apa tentang efek samping. Memeriksa jam sistem bukan efek samping; sebenarnya, fungsi atau metode apa pun yang diawali dengan kata "get" adalah salah satu yang seharusnya Anda harapkan tidak memiliki efek samping.
Aaronaught
36

Setiap operasi yang mengubah keadaan komputer atau yang berinteraksi dengan dunia luar dikatakan memiliki efek samping. Lihat Wikipedia tentang Efek Samping .

Misalnya, fungsi ini tidak memiliki efek samping. Hasilnya hanya bergantung pada argumen inputnya, dan tidak ada apa pun tentang keadaan program atau lingkungannya yang berubah ketika dipanggil:

int square(int x) { return x * x; }

Sebaliknya, memanggil fungsi-fungsi ini akan memberi Anda hasil yang berbeda tergantung pada urutan Anda memanggilnya, karena mereka mengubah sesuatu tentang keadaan komputer:

int n = 0;
int next_n() { return n++; }
void set_n(int newN) { n = newN; }      

Fungsi ini memiliki efek samping dari penulisan data ke keluaran. Anda tidak memanggil fungsi karena Anda ingin nilai pengembaliannya; Anda menyebutnya karena Anda menginginkan efeknya terhadap "dunia luar":

int Write(const char* s) { return printf("Output: %s\n", s); }
Kristopher Johnson
sumber
1
Ini adalah definisi yang baik, tapi saya tidak tergila-gila dengan elaborasi - seperti dalam jawaban Thorbjørn, sebagian dari itu tampaknya mengacaukan masalah efek samping dengan fungsi idempoten; sebagai Writecontoh Anda menunjukkan, memiliki efek samping tidak menyiratkan bahwa fungsi tersebut pernah mengubah outputnya sehubungan dengan inputnya, atau bahkan bahwa outputnya tergantung pada input sama sekali.
Aaronaught
6
Ini bukan tentang menjadi idempoten. Fakta bahwa ia menghasilkan keluaran berarti ia memiliki efek samping.
Kristopher Johnson
Dalam beberapa sistem, memohon square(x)dapat menyebabkan modul di mana fungsi didefinisikan untuk diambil dari disk. Haruskah ini dianggap efek samping? Lagi pula, ini mensyaratkan bahwa panggilan (pertama) memakan waktu lama secara tak terduga, bahwa penggunaan RAM naik, dll.
Hagen von Eitzen
1
@HagenvonEitzen Setiap operasi benar-benar membuat perubahan pada status komputer (register CPU, memori, konsumsi daya, panas, dll.). "Efek samping" biasanya merujuk pada lingkungan eksekusi yang diidealkan imajiner di mana tidak ada perubahan lingkungan kecuali jika program secara eksplisit mengubahnya. Tetapi jika Anda menelepon square(x) karena Anda ingin keadaan komputer eksternal itu berubah, Anda dapat menganggap itu sebagai efek samping.
Kristopher Johnson
Bagi saya ilustrasi pertama sangat masuk akal. Namun, yang kedua kurang begitu. Saya percaya efek samping harus didefinisikan dalam kaitannya dengan lingkungan / lingkup tertentu. Jika Anda mempertimbangkan seluruh alam semesta, tidak ada yang namanya efek samping. Bahkan jika Anda mengurungnya di komputer, fungsi Anda akan memengaruhi proses lain karena CPU tidak akan berlaku sama. Jika Anda membatasi ruang lingkup hal-hal yang dapat diakses dalam ruang lingkup fungsi lokal, maka kami memiliki sesuatu untuk dibicarakan.
funct7
21

Saya pikir jawaban yang ada cukup bagus. Saya ingin menguraikan beberapa aspek bahwa IMO belum cukup ditekankan.

Dalam matematika, fungsi hanyalah pemetaan dari sejumlah nilai ke nilai. Jadi, diberi fungsi fdan nilai x, f(x)akan selalu hasil yang sama y. Anda dapat mengganti f(x)dengan ydi mana saja dalam ekspresi dan tidak ada yang akan berubah.

Apa yang disebut fungsi (atau prosedur) dalam banyak bahasa pemrograman adalah konstruksi (potongan kode) yang dapat dieksekusi karena:

  1. Ini menghitung fungsi dalam arti matematika, yaitu nilai input yang diberikan, mengembalikan hasil, atau
  2. Ini menghasilkan beberapa efek, misalnya mencetak sesuatu ke layar, mengubah nilai pada database, meluncurkan rudal, tidur selama 10 detik, mengirim SMS.

Jadi efek dapat dikaitkan dengan keadaan tetapi juga dengan aspek lain seperti menembakkan rudal atau menjeda eksekusi selama beberapa detik.

Istilah efek samping mungkin terdengar negatif tetapi biasanya efek memanggil fungsi adalah tujuan utama dari fungsi itu sendiri. Saya mengira bahwa, karena istilah fungsi awalnya digunakan dalam Matematika, menghitung nilai dianggap sebagai efek utama dari suatu fungsi sedangkan efek lainnya dianggap efek samping . Beberapa bahasa pemrograman menggunakan istilah prosedur untuk menghindari kebingungan dengan fungsi dalam arti matematika.

Catat itu

  1. Beberapa prosedur berguna untuk nilai pengembalian dan efek sampingnya.
  2. Beberapa prosedur hanya menghitung nilai hasil dan tidak memiliki efek lain. Mereka sering disebut fungsi murni karena semua yang mereka lakukan adalah menghitung fungsi dalam arti matematika.
  3. Beberapa prosedur, misalnya sleep()dengan Python, hanya berguna untuk efek (sisi) mereka,. Ini sering dimodelkan sebagai fungsi yang mengembalikan nilai khusus None, unitatau ()atau ..., yang hanya menunjukkan bahwa perhitungan telah diakhiri dengan benar.
Giorgio
sumber
2
Menurut pendapat saya yang sederhana, ini harus menjadi jawaban yang diterima. Konsep efek samping hanya masuk akal dalam hal fungsi matematika. Suatu prosedur dirancang untuk hanya mengelompokkan satu set instruksi dengan cara yang terstruktur sambil memungkinkan Anda untuk melompat ke set itu dari mana saja dan kembali dengan mudah. Tidak ada efek dan efek samping yang dituju. Anda mungkin bisa mengatakan melempar pengecualian adalah efek samping dari suatu prosedur, karena itu melanggar maksud dari prosedur yang membuat Anda kembali ke tempat Anda tinggalkan dan melanjutkan formulir eksekusi di sana.
Didier A.
4

Efek samping adalah ketika operasi memiliki efek pada variabel / objek yang berada di luar penggunaan yang dimaksud.

Itu bisa terjadi ketika Anda membuat panggilan ke fungsi kompleks yang memiliki efek samping mengubah beberapa variabel global, meskipun itu bukan alasan Anda menyebutnya (mungkin Anda memanggilnya untuk mengekstrak sesuatu dari database).

Saya akui saya mengalami masalah dengan contoh sederhana yang tidak terlihat dibuat-buat, dan contoh dari hal-hal yang telah saya kerjakan terlalu lama untuk dikirim di sini (dan karena ini terkait dengan pekerjaan, saya mungkin tidak seharusnya demikian. ).

Salah satu contoh yang pernah saya lihat (beberapa waktu lalu) adalah fungsi yang membuka koneksi database jika koneksi dalam keadaan tertutup. Masalahnya adalah bahwa itu seharusnya menutup koneksi di akhir fungsi, tetapi pengembang lupa untuk menambahkan kode itu. Jadi di sini, ada efek samping yang tidak diinginkan : memanggil prosedur seharusnya hanya melakukan kueri dan efek sampingnya adalah koneksi tetap terbuka dan jika fungsinya dipanggil dua kali berturut-turut, akan muncul kesalahan mengatakan koneksi itu sudah terbuka.


Ok, jadi karena semua orang memberikan contoh sekarang, saya pikir saya juga akan;)

/*code is PL/SQL-styled pseudo-code because that's what's on my mind right now*/

g_some_global int := 0; --define a globally accessible variable somewhere.

function do_task_x(in_a in number) is
begin
    b := calculate_magic(in_a);
    if b mod 2 == 0 then
        g_some_global := g_some_global + b;
    end if;
    return (b * 2.3);
end;

Fungsi ini do_task_xmemiliki efek utama mengembalikan hasil beberapa perhitungan, dan efek samping dari kemungkinan memodifikasi variabel global.

Tentu saja, mana yang utama dan mana efek sampingnya bisa terbuka untuk interpretasi dan mungkin tergantung pada penggunaan aktual. Jika saya menyebut fungsi ini untuk tujuan memodifikasi global dan saya membuang nilai yang dikembalikan daripada saya akan mengatakan bahwa memodifikasi global adalah efek utama.

FrustratedWithFormsDesigner
sumber
2
Saya tidak berpikir bahwa ini adalah definisi universal yang bagus. Banyak programmer yang sengaja menggunakan konstruk khusus untuk efek sampingnya.
CB Bailey
@ Charles: Cukup adil. Dalam hal itu, bagaimana Anda mendefinisikannya?
FrustratedWithFormsDesigner
2
Saya pikir @KristopherJohnson memiliki definisi paling jelas. Apa pun yang mengubah keadaan program atau lingkungannya atau menghasilkan efek dunia nyata seperti menghasilkan output.
CB Bailey
@ Charles Bailey: Itu tidak mengubah definisi. Menggunakan hal-hal untuk efek samping itu baik-baik saja. Selama Anda mengerti bahwa ada efek sampingnya. Itu tidak mengubah apa pun tentang definisi ini.
S.Lott
1
@SLott: Definisi dalam jawaban ini (yaitu paragraf pertama) mencakup klausa: "di luar penggunaan yang dimaksudkan". Saya pikir komentar saya adil.
CB Bailey
3

Dalam ilmu komputer, suatu fungsi atau ekspresi dikatakan memiliki efek samping jika ia memodifikasi beberapa keadaan atau memiliki interaksi yang dapat diamati dengan fungsi panggilan atau dunia luar.

Dari Wikipedia - Efek Samping

Fungsi, dalam pengertian matematika, adalah pemetaan dari input ke output. Efek yang dimaksudkan dari memanggil suatu fungsi adalah memetakan input ke output yang dikembalikan. Jika fungsi melakukan hal lain, itu tidak masalah apa, tetapi jika ia memiliki perilaku yang tidak memetakan input ke output, perilaku itu dikenal sebagai efek samping.

Dalam istilah yang lebih umum, efek samping adalah efek yang bukan merupakan efek yang dimaksudkan oleh perancang konstruksi.

Efek adalah segala sesuatu yang memengaruhi seorang aktor. Jika saya memanggil fungsi yang mengirimkan pesan teks perpisahan kepada pacar saya, yang memengaruhi banyak aktor, saya, dia, jaringan perusahaan telepon seluler, dll. Satu-satunya efek yang dimaksudkan untuk memanggil fungsi bebas efek samping, adalah untuk fungsi tersebut untuk mengembalikan saya pemetaan dari input saya. Jadi untuk:

   public void SendBreakupTextMessage() {
        Messaging.send("I'm breaking up with you!")
   }

Jika ini dimaksudkan sebagai fungsi, maka satu-satunya hal yang harus dilakukan adalah mengembalikan batal. Jika efek sampingnya gratis, seharusnya tidak benar-benar mengirim pesan teks.

Dalam sebagian besar bahasa pemrograman, tidak ada konstruksi untuk fungsi matematika. Tidak ada konstruksi yang dimaksudkan untuk digunakan. Itu sebabnya sebagian besar bahasa mengatakan Anda memiliki metode atau prosedur. Secara desain, itu dimaksudkan untuk dapat melakukan lebih banyak efek. Dalam bahasa pemrograman yang umum, tidak ada yang benar-benar peduli tentang maksud dari apa metode atau prosedur itu, jadi ketika seseorang mengatakan fungsi ini memiliki efek samping, maksudnya secara efektif, konstruk ini tidak berperilaku seperti fungsi matematika. Dan ketika seseorang mengatakan fungsi ini bebas efek samping, maksudnya, konstruk ini secara efektif berperilaku seperti fungsi matematika.

Fungsi murni selalu efek samping gratis, menurut definisi. Fungsi murni, adalah cara untuk mengatakan, fungsi ini, meskipun menggunakan konstruk yang memungkinkan lebih banyak efek, hanya memiliki efek yang sama dengan fungsi matematika.

Saya menantang siapa pun untuk memberi tahu saya ketika fungsi bebas efek samping tidak akan murni. Kecuali efek yang dimaksudkan utama dari konteks kalimat menggunakan istilah murni dan efek samping bebas bukanlah efek matematika yang dimaksudkan dari suatu fungsi, maka mereka selalu sama.

Karena itu, kadang-kadang, meskipun lebih jarang, dan saya percaya ini adalah perbedaan yang kurang dan juga menyesatkan orang (karena itu bukan asumsi yang paling umum) dalam jawaban yang diterima, tetapi kadang-kadang diasumsikan bahwa efek yang dimaksudkan dari fungsi pemrograman adalah untuk memetakan input ke output, di mana input tidak dibatasi pada parameter fungsi yang eksplisit, tetapi output dibatasi pada nilai balik eksplisit. Jika Anda menganggap itu adalah efek yang dimaksudkan, maka fungsi membaca file dan mengembalikan hasil berbeda berdasarkan apa yang ada dalam file tersebut masih bebas efek samping, karena Anda mengizinkan input datang dari tempat lain dalam efek yang Anda maksudkan.

Jadi, mengapa ini semua penting?

Ini semua tentang kontrol dan menjaganya. Jika Anda memanggil fungsi, dan ia melakukan sesuatu yang lain lalu mengembalikan nilai, sulit untuk beralasan tentang perilakunya. Anda perlu melihat ke dalam fungsi untuk kode aktual untuk menebak apa yang dilakukannya dan menegaskan kebenarannya. Situasi yang ideal adalah sangat jelas dan mudah untuk mengetahui apa input yang digunakan fungsi dan tidak melakukan hal lain kemudian mengembalikan output untuk itu. Anda dapat sedikit merilekskan hal ini, dan mengatakan bahwa mengetahui persis apa input yang digunakannya tidak membantu seperti memastikan itu tidak melakukan hal lain yang Anda mungkin tidak sadari kemudian mengembalikan nilai, jadi mungkin Anda puas dengan hanya menegakkan bahwa itu tidak melakukan apa pun selain memetakan input, tidak peduli dari mana mendapatkannya, ke output.

Dalam hampir semua kasus, tujuan program adalah untuk memiliki efek selain memetakan hal-hal yang masuk ke hal-hal yang keluar. Gagasan mengendalikan efek samping adalah Anda dapat mengatur kode dengan cara yang lebih mudah dipahami dan dipikirkan. Jika Anda menempatkan semua efek samping bersama-sama, di tempat yang sangat eksplisit dan sentral, mudah untuk mengetahui ke mana harus mencari dan percaya bahwa ini semua yang terjadi, tidak lebih. Jika Anda memiliki input yang sangat eksplisit juga, ini membantu menguji perilaku untuk input yang berbeda, dan lebih mudah digunakan, karena Anda tidak perlu mengubah input di banyak tempat yang berbeda, beberapa yang mungkin tidak jelas, hanya saja untuk mendapatkan apa yang Anda inginkan.

Karena yang paling membantu untuk memahami, menalar dan mengendalikan perilaku suatu program adalah membuat semua input dikelompokkan secara jelas dan eksplisit, serta semua efek samping dikelompokkan bersama dan secara eksplisit, inilah yang biasanya dibicarakan orang ketika mereka mengatakan efek samping, murni, dll.

Karena yang paling membantu adalah pengelompokan efek samping dan kesaksian mereka, kadang-kadang orang hanya akan memaksudkan itu, dan membedakannya dengan mengatakan itu tidak murni, tetapi masih "efek samping" bebas. Tetapi efek sampingnya relatif terhadap asumsi "efek utama yang dituju", jadi itu adalah istilah kontekstual. Ini saya temukan kurang sering digunakan, meskipun secara mengejutkan ini banyak dibicarakan di utas ini.

Akhirnya, idempoten berarti memanggil fungsi ini berkali-kali dengan input yang sama (tidak masalah dari mana asalnya) akan selalu menghasilkan efek yang sama (efek samping atau tidak).

Didier A.
sumber
Saya pikir masalah besar dengan menjelaskan efek samping adalah bahwa sampai Anda telah menggunakan bahasa seperti Ocaml atau Haskell, itu bisa sangat sulit untuk dipikirkan tentang pemrograman bebas efek samping (hampir!).
Jamie Strauss
2

Dalam pemrograman efek samping adalah ketika suatu prosedur mengubah variabel dari luar ruang lingkupnya. Efek samping tidak tergantung pada bahasa. Ada beberapa kelas bahasa yang bertujuan untuk menghilangkan efek samping (bahasa fungsional murni), tetapi saya tidak yakin apakah ada yang memerlukan efek samping, tetapi saya bisa saja salah.

Sejauh yang saya tahu, tidak ada efek samping internal dan eksternal.

indyK1ng
sumber
Untuk lebih tepatnya, bahasa fungsional murni jelas memisahkan kode bebas efek samping dari kode lain, sedangkan bahasa lain tidak memiliki mekanisme untuk membedakan antara kode murni dan tidak murni. Sebagian besar program perlu memiliki efek samping agar dapat digunakan.
Giorgio
Saya pikir beberapa bahasa pemrograman pra-gui seperti MS-BASIC dan QBasic mungkin sudah sedekat mungkin dengan bahasa 'efek samping' seperti yang Anda dapatkan. Dan ya, Anda dapat memiliki efek samping internal dan eksternal.
James K
0

Ini adalah contoh sederhana:

int _totalWrites;
void Write(string message)
{
    // Invoking this function has the side effect of 
    // incrementing the value of _totalWrites.
    _totalWrites++;
    Debug.Write(message);
}

Definisi efek samping tidak spesifik untuk pemrograman, jadi bayangkan saja efek samping obat-obatan Anda atau makan terlalu banyak makanan.

Kekacauan Kekacauan
sumber
Tetapi jika pesan masuk sebagai referensi dan Anda mengubah pesan dalam metode Anda, itu mungkin akan menjadi efek samping. Apakah saya benar?
Amir Rezaei
Fakta bahwa ekspresi x++memodifikasi variabel xbiasanya dianggap sebagai efek samping. Nilai ekspresi itu adalah nilai pra-kenaikan x; ini adalah bagian efek non-sisi dari ekspresi.
CB Bailey
@ Charles - Saya setuju, meskipun contoh aslinya tidak sejelas yang sekarang.
ChaosPandion
@ Amir - Yah, itu benar-benar tergantung pada bahasanya. Jika ini adalah C # ini tidak akan dianggap sebagai efek samping.
ChaosPandion
@ChaosPandion: Secara pribadi, saya tidak setuju. Contoh aslinya jauh lebih sederhana dan lebih jelas.
CB Bailey
-2

Efek samping adalah hal-hal yang terjadi dalam kode yang tidak jelas terlihat.

Misalnya katakanlah Anda memiliki kelas ini

public class ContrivedRandomGenerator {
   public int Seed { get; set; }

   public int GetRandomValue()
   {
      Random(Seed);
      Seed++;
   }
}

Saat Anda awalnya membuat kelas, Anda memberinya seed.

var randomGenerator = new ContrivedRandomGenerator();
randomGenerator.Seed = 15;
randomGenerator.GetRandomValue();

Anda tidak tahu internal, Anda hanya berharap untuk mendapatkan nilai acak, dan Anda akan mengharapkan generalGenerator. Memang masih 15 ... tapi tidak.

Panggilan fungsi memiliki efek samping mengubah nilai Seed.

CaffGeek
sumber
10
Efek samping tidak harus disembunyikan. Anda memikirkan penggunaan sehari-hari atau medis; dalam pemrograman, efek samping hanya merujuk pada memodifikasi beberapa keadaan.
Aaronaught
1
Mencetak ke konsol adalah efek samping. Itu tidak tersembunyi. Dari Wikipedia : "Dalam ilmu komputer, suatu fungsi atau ekspresi dikatakan memiliki efek samping jika, selain mengembalikan nilai, itu juga memodifikasi beberapa keadaan atau memiliki interaksi yang dapat diamati dengan fungsi panggilan atau dunia luar ."
Efek samping adalah bagaimana tidak berfungsinya (yaitu prosedur) menyelesaikan pekerjaan. X = 1; X = Y (10) adalah dua fungsi murni. Ketika Anda melangkah keluar dari ranah "x = apa pun", apakah akan menulis output ke layar | drive | printer | memimpin atau membaca input di luar format "x = y" atau hanya mengubah nilai variabel dari satu hal ke hal lain , itu efek samping.
James K
Saya pikir dengan 'tersembunyi', maksudnya tidak jelas. Seperti dalam x = f (y, z) x dapat diasumsikan berdasarkan pada y dan z. Sedangkan proc (x, y, z) tidak memberi tahu Anda tentang apa yang terjadi. Setiap varable dapat diubah, atau tidak ada. Proc dapat berupa analog dengan f, atau sama sekali tidak terkait. Fungsi murni memiliki satu jawaban: 'x'. Lebih dari itu, itu adalah efek samping. Ditujukan sepenuhnya, tetapi efek samping.
James K
Sama seperti memahami 0, Anda harus terlebih dahulu memahami 1: Untuk memahami efek samping, Anda harus terlebih dahulu memahami fungsi.
James K