Yan etki kavramını açıkça anlamadım.
- Programlamanın yan etkisi nedir?
- Programlama dili bağımlı mı?
- Dış ve iç yan etkiler diye bir şey var mı?
Lütfen yan etkiler yaratan nedenlere bir örnek verin.
Yan etki kavramını açıkça anlamadım.
Lütfen yan etkiler yaratan nedenlere bir örnek verin.
Yanıtlar:
Bir yan etki basitçe bir tür devletin değiştirilmesine atıfta bulunur - örneğin:
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.
++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.
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); }
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.
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
square(x)
çünkü harici bilgisayar devlet değiştirmek bunu istiyorum, bunu bir yan etkisi olarak düşünebiliriz.
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 f
ve bir değer verildiğinde x
, f(x)
her zaman aynı sonuç elde edilir y
. Her yerde bir ifadede yerini alabilirsin f(x)
, y
hiç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ı):
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
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 None
ya unit
ya ()
ya ... basitçe hesaplama doğru sonlandırılması gerektiğini belirten hangi.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 .
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.
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.
İş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.
x++
değişkeni değiştirdiği gerçeğinin x
genellikle 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.
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.