“Yan etki” nedir?


Yanıtlar:


108

Bir yan etki basitçe bir tür devletin değiştirilmesine atıfta bulunur - örneğin:

  • Bir değişkenin değerini değiştirme;
  • Diske bazı veriler yazmak;
  • Kullanıcı Arayüzündeki bir düğmeyi etkinleştirme veya devre dışı bırakma.

Bazı insanların söylediklerinin aksine :

  • Bir yan etkisi yok değil gizlenmesine veya beklenmeyen var (o olabilir, ama bu bilgisayar bilimleri için uygulandığı gibi tanımıyla ilgisi yoktur);

  • Bir yan etkinin boşunlukla ilgisi yok. Bir idempotent işlevi yan etkilere sahip olabilir ve bir idempotent olmayan işlevin hiçbir yan etkisi olmayabilir (mevcut sistem tarihini ve saatini almak gibi).

Gerçekten çok basit. Yan etki = bir yerde bir şeyi değiştirmek.

Not: Benjol'un belirttiği gibi, birkaç kişi yan etkinin tanımını saf işlev tanımı ile (a) idempotent ve (b) hiçbir yan etkisi olmayan bir işlev ile sınırlandırıyor olabilir. Biri genel bilgisayar biliminde diğerini ima etmiyor, ancak işlevsel programlama dilleri genellikle her iki kısıtlamayı da uygulama eğiliminde olacak.


38
"Yan etki" ifadesi , kastedilenden başka bir şeyin değişmiş gibi görünmesini sağlar . Tıpta bir ilacın ağrıyı azaltmada temel bir etkisi olur ve bazen burun kanaması, baş dönmesine, vb. Neden olan yan etkisi olur ... İlacın amacı burun kanamasına neden olmak değil, bazen istenmeyen ilave sonuç.
SinirliFormsDesigner'la

15
@ Düzeltildi: +1. Ne zaman bu terimi görürsem yardım edemem ama FP savunucuları tarafından tam anlamıyla sinsi çağrışım yaratan çağrışım yaratmak için seçilip seçilmediğini merak ediyorum.
Mason Wheeler

6
@Mason Wheeler. FP'den çok önce vardı. Ve bu zarif bir uğursuz çağrışım değil. Yassı bir kötülük ve her zaman olmuştur. Kodladığım 30 yıl boyunca, "kripto tahsisi" ifadesi - yan etki - insanları rahatsız ediyordu. Eski bir ödev ifadesinin üstesinden gelmek çok daha kolaydır.
S.Lott

7
@Mason Wheeler: C olarak ++a. Atama gibi görünmüyor. b = ++a;iki yan etkisi var. Açık olanı ve kripto atama a. (Bazılarına) arzu edilen bir yan etki olan şey budur. Ancak tüm kariyerimin onu ince yapmamasına yan etki denildi.
S.Lott

5
@Zhary, lütfen cevabımdaki son madde işaretine bakın. Bahsettiğiniz şey belirsiz davranışlar (veya bunların eksikliği). Bu size yan etkileri hakkında hiçbir şey söylemez. Sistem saatini kontrol etme olduğunu değil bir yan etki; Aslında, "get" sözcüğü ile önceden işaretlenmiş herhangi bir işlev veya yöntem, herhangi bir yan etkisi olmamasını beklemeniz gereken bir yöntemdir.
Aarona,

36

Bilgisayarın durumunu değiştiren veya dış dünyayla etkileşime giren herhangi bir işlemin bir yan etkisi olduğu söyleniyor. Yan Etki hakkında Wikipedia'ya bakın .

Örneğin, bu fonksiyonun hiçbir yan etkisi yoktur. Sonuç yalnızca girdi argümanlarına dayanır ve programın veya ortamının durumu hakkında hiçbir şey çağrıldığında değişmez:

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

Buna karşılık, bu işlevleri çağırmak, onları çağırdığınız sıraya bağlı olarak size farklı sonuçlar verecektir, çünkü bilgisayarın durumu hakkında bir şeyler değiştirirler:

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

Bu fonksiyon, veriyi çıktıya yazma yan etkisine sahiptir. Fonksiyonu çağırmazsınız çünkü dönüş değerini istersiniz; Buna “dış dünya” üzerindeki etkisinin olmasını istediğiniz için diyorsunuz:

int Write(const char* s) { return printf("Output: %s\n", s); }

1
Bu iyi bir tanım, ama detaylandırma için delirmiyorum - tıpkı Thorbjørn'un cevabında olduğu gibi, bir kısmı yan etkiler konusunu iddiasız fonksiyonlarınkiyle birleştiriyor gibi görünüyor; senin kadar Writeörnek gösteriyor yan etkileri olan fonksiyon şimdiye çıkış hiç girişine bağlıdır bile onun girişlerine göre çıkışını değiştirir veya anlamına gelmez.
Aaron

6
Asılsız olmakla ilgili değil. Çıktı üretmesi, bir yan etkisi olduğu anlamına gelir.
Kristopher Johnson

Bazı sistemlerde, çağırmak square(x)işlevin tanımlandığı modüle diskten yüklenmesine neden olabilir. Bu yan etki olarak kabul edilmeli mi? Ne de olsa, (ilk) çağrının beklenmedik şekilde uzun sürdüğü, RAM kullanımının yükseldiği vb. Bu
adam

1
@HagenvonEitzen Her işlem aslında bilgisayarın durumunu değiştirir (CPU kayıtları, bellek, güç tüketimi, ısı vb.). "Yan etki", program açıkça değiştirilmediği sürece, bu ortamla ilgili hiçbir şeyin değişmediği hayali bir idealize edilmiş yürütme ortamı anlamına gelir. Aradığınız Ama eğer square(x) çünkü harici bilgisayar devlet değiştirmek bunu istiyorum, bunu bir yan etkisi olarak düşünebiliriz.
Kristopher Johnson,

Benim için ilk illüstrasyon mükemmel mantıklı. Ancak, ikincisi daha az. Yan etkinin belirli bir çevre / kapsam ile ilgili olarak tanımlanması gerektiğine inanıyorum. Tüm evreni göz önünde bulundurursanız, yan etki diye bir şey yoktur. Bilgisayarla sınırlandırsanız bile, işleviniz CPU'nun aynı şekilde davranmayacağı bir başka işlemi etkileyecektir. Kapsamı yerel işlev kapsamında erişilebilir olanlarla sınırlandırırsanız, konuşmamız gereken bir şey var.
funct7

20

Mevcut cevapların oldukça iyi olduğunu düşünüyorum. IMO'nun yeterince stresedilmediği bazı yönlerden bahsetmek istiyorum.

Matematikte bir fonksiyon sadece bir değer dizisinden bir değere eşlemedir. Böylece, bir işlev fve bir değer verildiğinde x, f(x)her zaman aynı sonuç elde edilir y. Her yerde bir ifadede yerini alabilirsin f(x), yhiçbir şey değişmeyecek.

Birçok programlama dilinde işlev (veya prosedür) olarak adlandırılan şey, çünkü çalıştırılabilen bir yapıdır (kod parçası):

  1. Bir işlevi matematiksel anlamda hesaplar, yani girdi değerleri verilen, bir sonuç döndürür veya
  2. Bazı efektler yaratır, örneğin ekrana bir şey basar, veritabanında bir değer değiştirir, füzeler fırlatır, 10 saniye uyur, SMS gönderir.

Dolayısıyla etkiler, durumla ilgili olabilir, aynı zamanda füze ateşleme veya birkaç saniye boyunca yürütmeyi duraklatma gibi diğer hususlarla ilgili olabilir.

Yan etki terimi olumsuz gelebilir, ancak normal olarak bir işlev çağırma etkisi işlevin kendisinin amacıdır. Sanırım, fonksiyon terimi başlangıçta Matematik'te kullanıldığından, bir değerin hesaplanmasının bir fonksiyonun birincil etkisi olarak kabul edilirken, diğer etkiler yan etkiler olarak kabul edilir . Bazı programlama dilleri , matematiksel anlamda işlevlerle karışıklığı önlemek için yordam terimini kullanır .

Bunu not et

  1. Bazı prosedürler hem geri dönüş değerleri hem de yan etkileri için kullanışlıdır.
  2. Bazı prosedürler sadece bir sonuç değeri hesaplar ve başka hiçbir etkisi olmaz. Genellikle saf fonksiyonlar denir, çünkü tek yaptıkları matematiksel anlamda bir fonksiyon hesaplamaktır.
  3. Bazı prosedürler, örneğin sleep()Python'da, yalnızca (yan) etkileri için faydalıdır. Bunlar genellikle özel bir değer döndüren işlevler olarak modellenmiştir Noneya unitya ()ya ... basitçe hesaplama doğru sonlandırılması gerektiğini belirten hangi.

2
Benim düşünceme göre, bu kabul edilen cevap olmalıdır. Yan etki kavramı yalnızca matematiksel işlevler açısından bile anlamlıdır. Bir prosedür, bir talimat setini yapılandırılmış bir şekilde basitçe gruplandırırken, o sete herhangi bir yerden ve geriye rahatça atlamanızı sağlar. Öncelikli amaç ve yan etki yoktur. Bir istisna atmanın, bir işlemin bir yan etkisi olduğunu söyleyebiliriz, çünkü işlemin amacını bozduğundan, kaldığınız yere geri dönmenizi ve orada yürütme formuna devam etmenizi sağlar.
Didier A.,

4

Yan etki, bir işlemin amaçlanan kullanım dışında olan bir değişken / nesne üzerinde bir etkiye sahip olmasıdır.

Bu, bir global değişkeni değiştirme yan etkisi olan karmaşık bir fonksiyona çağrı yaptığınızda ortaya çıkabilir, bunun nedeni, sizin çağrılma sebebiniz olmasa bile (belki bir veritabanından bir şeyi çıkartmak için çağırdınız).

Tamamen tartışmalı görünmeyen basit bir örnekle gelmekte zorlanıyorum ve çalıştığım şeylerden örnekler buraya göndermek için çok uzun (ve işle ilgili olduğu için muhtemelen hiç olmamalıyım) ).

Gördüğüm örneklerden biri (bir süre önce), bağlantı kapalı durumdaysa bir veritabanı bağlantısı açan bir işlevdi. Sorun, fonksiyonun sonunda bağlantıyı kapatması gerekiyordu, ancak geliştirici bu kodu eklemeyi unuttu. Yani burada, istenmeyen bir yan etki vardı: bir prosedürü çağırmak sadece bir sorgu yapmalıydı ve yan etki, bağlantının açık kalmasıydı ve eğer fonksiyon arka arkaya iki defa çağrıldıysa, bağlantının açık olduğunu söyleyen bir hata ortaya çıkacaktı. Zaten açık.


Tamam, şimdi herkes örnek verdiğinden beri, ben de yaparım;

/*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;

İşlev do_task_x, bazı hesaplamaların sonucunu döndürmede birincil etkiye ve genel değişkeni değiştirmenin bir yan etkisine sahiptir.

Tabii ki, hangisi birincil ve hangisi yan etki ise yorumlara açık olabilir ve fiili kullanıma bağlı olabilir. Eğer bu işlevi genelde değişiklik yapmak için çağırırsam ve geri döndürülen değeri, genelde değiştirmenin birincil etki olduğunu söyleyeceğim değerden atarsam .


2
Bunun iyi bir evrensel tanım olduğunu sanmıyorum. Birçok programcı kasıtlı olarak yan etkileri için yapıları kullanır.
CB Bailey

@Charles: Yeterince adil. Bu durumda, nasıl tanımlarsınız?
SinirliFormsDesigner'la

2
@ KristopherJohnson'un en net tanımı olduğunu düşünüyorum. Programın durumunu veya çevresini değiştiren veya çıktı üretmek gibi gerçek bir dünya etkisi yaratan herhangi bir şey.
CB Bailey

@ Bailey Bailey: Bu tanımı değiştirmez. Yan etki için bir şeyler kullanmak iyidir. Bir yan etkisi olduğunu anladığın sürece. Bu tanımla ilgili hiçbir şeyi değiştirmez.
S.Lott

1
@SLott: Bu cevaptaki tanım (yani ilk paragraf) şu maddeyi içerir: "amaçlanan kullanımın dışında". Benim yorumumun adil olduğunu düşünüyorum.
CB Bailey

3

Bilgisayar bilimlerinde, bir işlevi veya ifadenin, eğer bir durumu değiştirirse veya çağıran işlevlerle veya dış dünyayla gözlemlenebilir bir etkileşimi varsa, yan etkisinin olduğu söylenir.

Gönderen Vikipedi - Yan Etkisi

Bir fonksiyon matematiksel anlamda girdiden çıktıya bir eşlemedir. Bir işlevi çağırmanın amaçlanan etkisi, girdiyi döndürdüğü çıktıya eşlemesidir. İşlev başka bir şey yaparsa, ne olduğu önemli değildir, ancak girişi çıktıyla eşleştirmeyen herhangi bir davranışı varsa, bu davranışın bir yan etki olduğu bilinmektedir.

Daha genel bir terimde, bir yan etki, yapının tasarımcısının amaçlanan etkisi olmayan herhangi bir etkidir.

Etki, bir aktörü etkileyen herhangi bir şeydir. Kız arkadaşıma, bir grup oyuncuyu, ben, onu, cep telefonu şirketinin ağını vb. Etkileyen bir parçalanma mesajı gönderen bir işlev çağırırsam, yan etkisiz bir işlev çağırmanın tek amaçlanan etkisi işlevdir. girişimden bana bir harita döndürmek için. İçin böylece:

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

Bunun bir fonksiyon olması amaçlanıyorsa, yapması gereken tek şey boşluğa dönmek. Yan etkisizse, kısa mesaj göndermemelidir.

Çoğu programlama dilinde, matematiksel bir işlev için yapı yoktur. Hiçbir yapının böyle kullanılması amaçlanmamıştır. Bu nedenle çoğu dilde yöntem veya prosedürlerin olduğunu söylüyor. Tasarım gereği, bunlar çok daha fazla etki yapabilmek için tasarlanmıştır. Yaygın programlamada, hiç kimse bir yöntemin ya da prosedürün ne olduğunu gerçekten umursamıyor, bu yüzden birisi bu fonksiyonun yan etkisi olduğunu söylerken, etkili bir şekilde demek istiyorlarsa, bu yapı matematiksel bir fonksiyon gibi davranmıyor. Birisi bu fonksiyonun yan etki olmadığını söylediğinde, bu yapının matematiksel bir fonksiyon gibi etkin bir şekilde davrandığını söyler.

Saf bir işlev tanım gereği her zaman yan etki değildir. Saf işlev, bu işlevi söylemenin bir yoludur, daha fazla etkiye izin veren bir yapı kullanmasına rağmen, yalnızca matematiksel bir işleve eşit bir etkiye sahiptir.

Bir kimsenin yan etkisiz bir fonksiyonun ne zaman saf olmayacağını bana söylemesini istiyorum. Saf ve yan etki terimini kullanan cümle bağlamının birincil amaçlanan etkisi, bir işlevin matematiksel amaçlanan etkisine ait değilse, o zaman bunlar her zaman eşittir.

Bu nedenle, bazen, daha nadiren olsa da, bunun kabul edilen cevapta eksik olan ve aynı zamanda insanları (en yaygın varsayım olmadığı gibi) yanlış yönlendiren ayrım olduğuna inanıyorum, ancak bazen bir programlama fonksiyonunun amaçlanan etkisinin olduğu varsayılmaktadır. girdiyi çıktıya eşlemek için, girişin fonksiyonun açık parametreleri ile sınırlı olmadığı, ancak çıktı açık dönüş değeriyle sınırlandığı. Bunun amaçlanan etkinin olduğunu varsayarsanız, o zaman bir dosyayı okuyan ve dosyadakilere göre farklı bir sonuç veren bir işlev, girdilerin istediğiniz etkideki diğer yerlerden gelmesine izin verdiğiniz için, hala yan etkide değildir.

Peki, neden bu kadar önemli?

Her şey kontrol etmek ve saklamakla ilgili. Bir işlevi çağırırsanız ve başka bir şey yaparsa, o zaman bir değer döndürürsünüz, davranışını düşünmek zordur. Gerçek kodun ne yaptığını tahmin etmesi ve doğruluğunu kanıtlaması için fonksiyonun içine bakmanız gerekir. İdeal durum, işlevin kullandığı girdiyi bilmek ve bunun için bir çıktı döndürmek yerine başka bir şey yapmadığını bilmek çok açık ve kolaydır. Bunu biraz rahatlatabilir ve hangi girdiyi kullandığını tam olarak bilmek, bir değer döndürmekle farkına varamayacağınız başka bir şey yapmadığından emin olmak kadar faydalı olmadığını söyleyebilir, bu yüzden belki sadece uygulamaktan memnun olabilirsiniz. başka bir şey yapmaz, daha sonra nereden girdi olursa olsun çıktıya eşlemek için giriş.

Neredeyse tüm durumlarda, programın amacı, ortaya çıkan şeyleri haritalandırmaktan başka etkilere sahip olmaktır. Yan etkiyi kontrol etme fikri, kodu daha kolay anlaşılması ve mantıklı bir şekilde düzenlemesidir. Tüm yan etkiyi bir arada, çok açık ve merkezi bir yere koyarsanız, bunun olup bittiğine, artık olanın nereye bakacağını ve güvenebileceğini bilmek kolaydır. Girdide çok açık olması durumunda, farklı girdiler için davranışları sınamaya yardımcı olur ve kullanımı daha kolaydır, çünkü girişi çok farklı yerlerde değiştirmek zorunda kalmazsınız, bazıları açık olmayabilir. istediğini elde etmek için.

Bir programın davranışını anlamak, neden ve kontrol etmek için en yararlı olan, tüm girdilerin açıkça bir arada gruplandırılmış ve açık olması ve tüm yan etkilerin bir arada ve açık bir şekilde gruplandırılmış olmasıdır; yan etki, saf vs.

En yararlısı, yan etkilerin gruplandırılması ve açıklık olmalarıdır, bazen insanlar yalnızca bunun anlamına gelir ve saf olmadığını, ama yine de "yan etki" özgür olduğunu söyleyerek ayırt ederler. Ancak, yan etki varsayılan "amaçlanan birincil etki" ile ilişkilidir, yani bağlamsal bir terimdir. Bulduğum bu daha az sıklıkla kullanılıyor, ancak şaşırtıcı bir şekilde bu konu hakkında çokça konuşuluyor.

Son olarak, idempotent, bu işlevi aynı girdilerle (nereden geldiklerinin önemi yoktur) birçok kez çağırmak, her zaman aynı etkilere (yan etki ya da olmamak) neden olur.


Yan etkileri açıklamada büyük bir sorun olduğunu düşünüyorum, Ocaml veya Haskell gibi bir dil kullanana kadar, yan etkili ücretsiz (neredeyse!) Programlama hakkında akıl için çok zor olabilir.
Jamie Strauss

2

Programlamada bir yan etki, bir prosedürün kapsamı dışından bir değişkeni değiştirmesidir. Yan etkiler dile bağlı değildir. Yan etkileri ortadan kaldırmayı amaçlayan bazı dil sınıfları vardır (saf işlevsel diller), ancak yan etki gerektiren herhangi bir şey olup olmadığından emin değilim, ama yanılıyor olabilirim.

Bildiğim kadarıyla, iç ve dış yan etkileri yoktur.


Daha kesin olmak gerekirse, saf işlevsel diller yan etki serbest kodunu diğer kodlardan açıkça ayırırken, diğer dillerin saf ve saf kod arasında ayrım yapma mekanizması yoktur. Çoğu programın herhangi bir kullanımı için yan etkileri olması gerekir.
Giorgio

MS-BASIC ve QBasic gibi ön-gui programlama dillerinden bazılarının, olabildiğince 'sadece' yan etki 'diline yakın olabileceğini düşünüyorum. Ve evet, hem iç hem de dış yan etkilere sahip olabilirsiniz.
James K,

0

İşte basit bir örnek:

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

Yan etkinin tanımı, programlamaya özgü değildir, bu nedenle ilaçlarınızın yan etkilerini veya çok fazla yemek yediğinizi hayal edin.


Ancak mesaj referans olarak gelirse ve yönteminizde mesajı değiştirirseniz, bu yan etkisi olabilir. Doğrumuyum?
Amir Rezaei

İfadenin x++değişkeni değiştirdiği gerçeğinin xgenellikle bir yan etki olduğu kabul edilir. İfadenin bu değeri, artırma öncesi değeridir x; bu, ifadenin yan etkisi olmayan kısmıdır.
CB Bailey

@Charles - Orijinal örnek şu anki kadar net olmasa da aynı fikirdeyim.
ChaosPandion

@Amir - Bu gerçekten dile bağlı. Bu C # olsaydı, bu bir yan etki olarak kabul edilmezdi.
ChaosPandion

@ ChaosPandion: Şahsen ben aynı fikirde değilim. Orijinal örnek çok daha basit ve netti.
CB Bailey

-2

Yan etkisi, kodda açıkça görülmeyen şeylerdir.

Örneğin, bu sınıfa sahip olduğunuzu söyleyelim.

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

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

Başlangıçta sınıfı oluşturduğunuzda ona bir tohum verirsiniz.

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

İnternalleri tanımıyorsunuz, sadece rastgele bir değer elde etmeyi umuyorsunuz ve randomGenerator.Seed'in hala 15 olmasını bekliyorsunuz ... ama değil.

İşlev çağrısı, Tohum değerini değiştirmenin yan etkisine sahipti.


10
Yan etkilerin gizlenmesi gerekmez. Konuşma veya tıbbi kullanım düşünüyorsunuz; programlamada, bir yan etki basitçe bazı durumları değiştirmeyi ifade eder.
Aaron

1
Konsola baskı yapmak yan etkisidir. Gizli değil. Gönderen Wikipedia : "Bilgisayar bilimleri, bir fonksiyon ya da ifade bir değer döndüren yanı sıra, aynı zamanda bazı durumunu değiştirir veya sahiptir, eğer bir yan etkiye sahip olduğu söylenir çağıran fonksiyonlara veya gözlemlenebilir etkileşimi dış dünya ."

Yan etkiler, işlevsizlerin (yani prosedürlerin) herhangi bir işi yapmasıdır. X = 1; X = Y (10) iki saf fonksiyondur. "X = ne olursa olsun" aleminin dışına çıktığınızda, çıktıyı ekrana | sürücü | yazıcı | led veya "x = y" biçiminin dışına çıkarıp yazmayın ya da değişkenin değerini bir şeyden diğerine değiştirin , bu bir yan etki.
James K,

Bence 'gizlenmiş' demek, açık olmadığı anlamına gelir. X = f (y, z) 'de olduğu gibi, x'in y ve z'ye dayandığı varsayılabilir. Oysa proc (x, y, z) olup bitenler hakkında size hiçbir şey söylemez. Her değişken değiştirilebilir ya da hiç değişmemiş olabilir. Proc, f'ye analog veya tamamen ilgisiz olabilir. Saf fonksiyonun tek bir cevabı vardır: 'x'. Bunun ötesine geç, bu bir yan etki. Tamamen kasıtlı, ancak yan etkileri.
James K,

Tıpkı 0'ı anlamak gibi, önce 1'i anlamalısınız: Yan etkileri anlamak için önce fonksiyonları anlamalısınız.
James K,
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.