İşlevsel programlamada neden yan etkiler kötü kabul edilir?


69

Yan etkilerin doğal bir fenomen olduğunu hissediyorum. Ama fonksiyonel dillerde tabu gibi bir şey. Sebepler neler?

Benim sorum işlevsel programlama stiline özgüdür. Tüm programlama dilleri / paradigmaları değil.


6
Yan etkisi olmayan bir program işe yaramaz, bu nedenle yan etkiler ne kötülük ne de tabu değildir. Ancak, kodu yan etkilerle sınırlayan FP istilaları, kodun mümkün olduğunca büyük bir kısmı yan etki göstermeyen fonksiyonlardır. Bu teşvik edilir, çünkü yan etki göstermeyen fonksiyonların ve alt sistemlerin anlaşılması, analiz edilmesi, test edilmesi ve optimize edilmesi daha kolaydır.
JacquesB,

@JacquesB Neden anlaşılmaları, analiz etmeleri, test etmeleri ve optimize etmeleri daha kolay olduklarını açıklamak için iyi bir cevap olacaktır.
16'da

Yanıtlar:


72

İşlevlerinizi / yöntemlerinizi yan etkiler olmadan yazma - bu yüzden bunlar saf işlevlerdir - programınızın doğruluğu hakkında düşünmeyi kolaylaştırır.

Ayrıca, yeni davranışlar oluşturmak için bu fonksiyonları oluşturmayı kolaylaştırır.

Ayrıca, derleyicinin örneğin işlevlerin sonuçlarını hafızada tutabileceği veya Common Subexpression Elimination özelliğini kullanabildiği bazı optimizasyonları mümkün kılar.

Düzenleme: Benjol'un isteği üzerine: Eyaletinizin çoğu yığında depolandığından (Jonas'ın burada çağırdığı gibi veri akışı, kontrol akışı değil ), hesaplamanızın bağımsız olan bölümlerinin yürütülmesini paralelleştirebilir veya başka şekilde yeniden sıralayabilirsiniz. herbiri. Birini diğerine girdi sağlamadığı için bu bağımsız parçaları kolayca bulabilirsiniz.

Yığını geri almanıza ve bilgisayar işlemine devam etmenize izin veren (Smalltalk gibi) hata ayıklayıcıların bulunduğu ortamlarda, saf işlevlere sahip olmak, önceki durumların denetim için uygun olması nedeniyle bir değerin nasıl değiştiğini kolayca görebileceğiniz anlamına gelir. Yüksek mutasyonlu bir hesaplamada, yapınıza veya algoritmanıza açıkça eylemler / geri alma eylemleri eklemiyorsanız, hesaplamanın geçmişini göremezsiniz. (Bu, ilk paragrafa bağlanır: saf işlevler yazmak , programınızın doğruluğunu denetlemeyi kolaylaştırır .)


4
Belki de cevabınıza eşzamanlılık hakkında bir şeyler eklemeyi düşünebilirsiniz?
Benjol

5
Yan etkisi olmayan fonksiyonların test edilmesi ve yeniden kullanılması daha kolaydır.
LennyProgramcılar

@ Lenny222: yeniden kullanmak, fonksiyon bileşimi hakkında konuşarak ima ettiğim şeydi.
Frank Shearar

@ Frank: Ah, tamam, çok sığ tarama. :)
LennyProgrammers 28:10

@ Lenny222: Sorun değil; muhtemelen hecelemek iyi bir şey.
Frank Shearar

23

İşlevsel programlama hakkında bir makaleden :

Uygulamada, uygulamaların bazı yan etkileri olması gerekir. Fonksiyonel programlama diline Haskell'in katkısı olan Simon Peyton-Jones şunları söyledi: “Sonunda, herhangi bir programın durumu manipüle etmesi gerekir. Herhangi bir kara kutu ne olursa olsun yan etkisi olmayan bir program. Bu kutu daha da ısınır. " ( http://oscon.blip.tv/file/324976 ) Anahtar, yan etkileri sınırlamak, net bir şekilde tanımlamak ve kod boyunca saçılmasından kaçınmaktır.



23

Yanlış anladınız, fonksiyonel programlama, programların anlaşılmasını ve optimize edilmesini kolaylaştırmak için sınırlı yan etkileri teşvik ediyor. Haskell bile dosyalara yazmanıza izin verir.

Temel olarak söylediğim şudur ki, işlevsel programcılar yan etkilerin kötü olduğunu düşünmezler, yalnızca yan etki kullanımını sınırlamanın iyi olduğunu düşünürler. Bunun kadar basit bir ayrım gibi görünebileceğini biliyorum ama her şeyi değiştiriyor.


Bu yüzden “tabu gibi bir şey” - FPL'ler yan etkileri sınırlamanızı teşvik ediyor.
Frank Shearar

Yaklaşım için +1. yan etkiler hala var. gerçekten, onlar sınırlıdır
Belun

Açıklamak için, 'neden işlevsel olarak programlamada yan etkiye izin verilmediğini' ya da 'neden yan etkiye ihtiyaç duyulmadığını' söylemedim. İşlevsel dillerde izin verildiğini ve bazen şart olduğunu biliyorum. Ancak, işlevsel programlamada çok önerilmektedir. Neden? Benim sorum buydu.
Gulshan

@Gulshan - Çünkü yan etkiler programların anlaşılmasını ve optimize edilmesini zorlaştırıyor.
ChaosPandion

Haskell durumunda, asıl nokta "yan etkileri sınırlamak" değildir. DİL'de yan etkileri ifade etmek imkansızdır. Ne gibi fonksiyonlar readFileyapmak bir dizi eylem tanımlamaktır. Bu dizi, fonksiyonel olarak saf ve ne yapılacağını açıklayan soyut bir ağaç gibidir. gerçek kirli yan etkiler daha sonra çalışma zamanı tarafından gerçekleştirilir.
sara

13

Birkaç not:

  • Yan etkisi olmayan fonksiyonlar önemsiz bir şekilde yürütülürken, yan etkisi olan fonksiyonlar tipik olarak bir tür senkronizasyon gerektirir.

  • Yan etkisi olmayan işlevler daha agresif bir optimizasyona izin verir (örneğin sonuç önbelleği kullanarak şeffaf olarak), çünkü doğru sonucu aldığımız sürece, işlevin gerçekten gerçekleştirilip gerçekleştirilmediği önemli değildir.


Çok ilginç nokta: işlevin gerçekten yerine getirilip gerçekleştirilmediği önemli değil . Eşdeğer parametreler verilen yan etkisiz fonksiyonlara yapılan sonraki çağrılardan kurtulabilen bir derleyici ile sonlandırmak ilginç olurdu .
Noel Widmer

1
@NoelWidmer Böyle bir şey zaten var. Oracle'ın PL / SQL, deterministicyan etkisi olmayan fonksiyonlar için bir madde sunar , bu yüzden gereğinden fazla çalıştırılmazlar.
user281377

Vaov! Bununla birlikte, dillerin anlamsal olarak ifade edilmesi gerektiğini düşünüyorum, böylece derleyici açık bir bayrak belirtmek zorunda kalmadan kendi başına anlayabiliyor (bir maddenin ne olduğundan emin değilim). Bir çözüm, değişken / değişken olacak parametreleri belirlemek olabilir. Genel olarak, bu, derleyici tarafından yan etkiler hakkında varsayımların yapılabileceği güçlü bir tipte bir sistem gerektirecektir. Ve istenirse özelliğin kapatılabilmesi gerekir. Kaydolma yerine, vazgeçme. Bu sadece benim düşüncem, cevabınızı okuduğumdan beri edindiğim sınırlı bilgiye dayanarak :)
Noel Widmer

deterministicFıkra sadece bu nasıl karşılaştırılabilir bir belirleyici fonksiyon olan derleyici bildiren bir anahtar kelimedir finalJava anahtar değişken değiştiremezsiniz derleyici söyler.
user281377

11

Öncelikle şimdi işlevsel kodda çalışıyorum ve bu açıdan gözle görülür derecede açık görünüyor. Yan etkiler , kod okumaya ve anlamaya çalışan programcılar üzerinde büyük bir zihinsel yük oluşturur . Bu yükü bir süre için serbest kalana kadar fark etmiyorsunuz, sonra aniden yan etkileri olan kodu tekrar okumak zorundasınız.

Bu basit örneği düşünün:

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?

İşlevsel bir dilde hala 42 olduğunu biliyorum . fooAradaki koda bakmak , daha az anlamak veya aradığı fonksiyonların uygulamalarına bakmak bile zorunda değilim .

Aynı anda eşzamanlılık ve paralelleştirme ve optimizasyon ile ilgili her şey güzel, ama bilgisayar bilimcilerinin broşürde kullandığı şey bu. Değişkeninizi kimin değiştirdiğini merak etmeme gerek yok ve günlük pratikte gerçekten ne zevk aldığım ne.


6

Hiçbir dilden az kişi yan etkilere neden olmayı imkansız kılar. Tamamen yan etkisiz olan dillerin kullanımı, çok sınırlı bir kapasiteden başka, yasaklanması zor (imkansız).

Neden yan etkiler kötü kabul edilir?

Çünkü bir programın tam olarak ne yaptığını düşünmeyi ve yapmasını beklediğiniz şeyi yaptığını kanıtlamayı çok daha zorlaştırıyorlar.

Çok yüksek bir düzeyde, tüm 3 katmanlı bir web sitesini yalnızca kara kutu testi ile test etmeyi hayal edin. Tabii, ölçeğe bağlı olarak yapılabilir. Ama kesinlikle çok fazla çoğaltma oluyor. Orada eğer olduğunu bir hata (yani bir yan etkisi ile ilgilidir) hata teşhis ve sabit ve düzeltme test ortamına dağıtıldığı kadar, o zaman potansiyel olarak başka testler için tüm sistemi kırılabilir.

Yararları

Şimdi, aşağı ölçeklendir. Yan etkili serbest kod yazma konusunda oldukça başarılı olsaydınız, varolan bazı kodların ne kadar hızlı olduğunu düşünüyorsunuz? Birim testlerini ne kadar hızlı yazabilirsin? Nasıl emin hiçbir yan etkileri ile kod hata içermeyen garantili olduğunu ve kullanıcıların herhangi bir hata maruz kaldıkları sınırlayabilir hissederiz mi var?

Kodun yan etkisi yoksa, derleyici de gerçekleştirebileceği ek optimizasyonlara sahip olabilir. Bu optimizasyonları uygulamak çok daha kolay olabilir. Yan etkili serbest kod için bir optimizasyonun kavramsallaştırılması bile daha kolay olabilir; bu, derleyici satıcınızın yan etkilerde kodda imkansız olan optimizasyonları uygulayabileceği anlamına gelir.

Aynı anda eşzamanlılık, kodun yan etkileri olmadığında uygulamak, otomatik olarak oluşturmak ve optimize etmek için son derece basittir. Bunun nedeni, tüm parçaların herhangi bir sırayla güvenli bir şekilde değerlendirilebilmesidir. Programcıların aynı anda yüksek kod yazmasına izin vermek, Computer Science'ın uğraşması gereken bir sonraki büyük zorluk ve Moore Yasasına karşı kalan az sayıdaki çitlerden biri olarak kabul edilir .


1
Ada, yan etkilere neden olmayı çok zorlaştırıyor. Yine de imkansız değil, ama o zaman ne yaptığını açıkça biliyorsun.
mouviciel

@mouviciel: Dışarıda yan etkileri çok zorlaştıran ve onları Monad'lara devretmeye çalışan en az birkaç yararlı dil olduğunu düşünüyorum.
Merlyn Morgan-Graham

4

Yan etkiler, kodunuzda daha sonra ya sizin tarafınızdan ya da bazı şüphesiz çalışanlar tarafından ele alınması gereken “sızıntılar” gibidir.

İşlevsel diller, kodu daha az bağlama bağımlı ve daha modüler yapmanın bir yolu olarak durum değişkenlerini ve değişken verileri önler. Modülerlik, bir geliştiricinin çalışmasının diğerinin çalışmasını etkilememesini / baltalamasını önler.

Ekip büyüklüğüyle gelişme oranını ölçeklendirmek, günümüzde yazılım geliştirmenin “kutsal kâsesi” dir. Diğer programcılar ile çalışırken, birkaç şey modülerlik kadar önemlidir. En basit mantıksal yan etkiler bile işbirliğini son derece zorlaştırıyor.


+1 - "ya da bazı hakaret eden iş arkadaşı"
Merlyn Morgan-Graham

1
Yan etkilerin "ele alınması gereken sızıntılar" olması nedeniyle -1. "Yan etkiler" (tamamen işlevsel olmayan kod) oluşturmak, önemsiz olmayan herhangi bir bilgisayar programını yazmanın amacıdır.
Mason Wheeler

Bu yorum altı yıl sonra geliyor, ancak yan etkileri var ve sonra yan etkileri var. Yan etkileri, I / O'yu yapıyor ve kullanıcıya sonuçlarınızı vermek gerekir, çünkü böylece, herhangi bir programa gerçekten gerekli bir arzu tür nasılsa kodunuzu durumunu değiştirir ama yan etkileri diğer tür, - olmadan iyi bir G / Ç yapmak gibi nedenlerden dolayı gerçekten daha sonra kullanılması gereken bir "sızıntı" vardır. Temel fikir, komut-sorgu ayrımıdır : bir değer döndüren bir fonksiyonun bir yan etkisi olmamalıdır.
17:17

4

IMHO, bu oldukça ikiyüzlü. Kimse yan etkilerden hoşlanmaz, ama herkes onlara ihtiyaç duyar.

Yan etkiler konusunda bu kadar tehlikeli olan şey, bir işlev çağırırsanız, bu durumun yalnızca bir dahaki sefere çağrıldığında işlevin davranış biçiminde değil, diğer işlevlerde de bu etkisinin olması muhtemeldir. Bu nedenle yan etkiler öngörülemeyen davranış ve önemsiz bağımlılıklar ortaya çıkarmaktadır.

OO ve fonksiyonel gibi programlama paradigmaları bu sorunu ele alır. OO, endişelerin ayrılmasını empoze ederek sorunu azaltır. Bu, çok fazla değişken veri içeren uygulama durumunun, her biri yalnızca kendi durumunu korumaktan sorumlu olan nesneler içine alındığı anlamına gelir. Bu şekilde bağımlılık riski azalır ve problemler çok daha izole edilir ve izlenmesi kolaydır.

İşlevsel programlama, uygulama durumunun programlayıcı açısından basitçe değiştirilemediği çok daha radikal bir yaklaşım izlemektedir. Bu iyi bir fikir, ancak dili kendi başına işe yaramaz hale getiriyor. Neden? Çünkü HERHANGİ BİR G / Ç işleminin yan etkileri vardır. Herhangi bir giriş akışından okuduğunuzda, uygulama durumunun değişmesi muhtemeldir, çünkü aynı işlevi bir daha başlattığınızda, sonuç farklı olabilir. Farklı verileri okuyorsunuz ya da - bir olasılık da - işlem başarısız olabilir. Aynısı çıktı için de geçerlidir. Çıktı bile yan etkileri olan bir işlemdir. Bu, bugünlerde sıkça fark ettiğiniz bir şey değildir, ancak çıktınız için yalnızca 20K'nın olduğunu ve daha fazla çıktı alırsanız uygulamanızın disk alanı yetersiz olduğundan veya başka bir şey yapılmadığından çöktüğünü hayal edin.

Yani evet, yan etkiler bir programcının bakış açısından tehlikeli ve tehlikelidir. Hataların çoğu, uygulama durumunun belirli bölümlerinin neredeyse belirsiz ve çoğu zaman gereksiz yan etkiler yoluyla neredeyse belirsiz bir şekilde kilitlenmesinden kaynaklanmaktadır. Bir kullanıcının bakış açısından, yan etkiler, bir bilgisayarı kullanma noktasıdır. İçeride ne olduğu ve nasıl organize olduğu umurunda değil. Bir şey yaparlar ve bilgisayarın buna göre değişmesini beklerler.


ilginç bir şekilde mantıksal programlama yalnızca işlevsel yan etkilere sahip değildir; ancak atandığında bir değişkenin değerini bile değiştiremezsiniz.
Ilan

@Ilan: Bu, bazı fonksiyonel diller için de geçerlidir ve benimsemesi kolay bir stildir.
back2dos

“İşlevsel programlama, uygulama durumunun programcının bakış açısından basitçe değiştirilemediği çok daha radikal bir yaklaşım benimsiyor. Bu iyi bir fikir, ancak dili kendi başına işe yaramaz hale getiriyor. Neden? Çünkü HERHANGİ BİR G / Ç işleminin bir tarafı var Etkileri ": FP yan etkileri yasaklamamakta, gerekmediğinde onları kısıtlamaktadır. Örneğin (1) G / Ç -> yan etkiler gereklidir; (2) bir toplam fonksiyonun bir dizi -> yan etkiden hesaplanması (örneğin, akümülatör değişkeni olan döngü için) gerekli değildir.
Giorgio

2

Herhangi bir yan etki, test ederken göz önünde bulundurulması gereken ekstra giriş / çıkış parametreleri sunar.

Bu, kod doğrulamasının çok daha karmaşık olmasını sağlar çünkü ortam sadece onaylanan kodla sınırlı kalamaz, ancak çevredeki ortamın bir kısmını veya tamamını getirmelidir (güncellenen global, o kodda yaşar, bu da buna bağlıdır) tam bir Java EE sunucusu içinde yaşamaya bağlı olan kod ....)

Yan etkilerden kaçınmaya çalışırken, kodu çalıştırmak için gereken dışsallık miktarını sınırlarsınız.


1

Tecrübelerime göre Nesne Yönelimli programlamadaki iyi tasarım, yan etkileri olan fonksiyonların kullanımını zorunlu kılar.

Örneğin, basit bir UI masaüstü uygulaması edinin. Öbek üzerinde, programımın etki alanı modelinin geçerli durumunu gösteren bir nesne grafiği olan çalışan bir programım olabilir. Mesajlar, bu grafikteki nesnelere ulaşır (örneğin, UI katman denetleyicisinden çağrılan yöntem çağrıları yoluyla). Öbek üzerindeki nesne grafiği (etki alanı modeli) iletilere yanıt olarak değiştirilir. Modelin gözlemcileri herhangi bir değişiklik, UI ve belki de diğer kaynaklar hakkında bilgilendirilir.

Kötü olmaktan ötürü, bu yığın modifiye edici ve ekran modifiye edici yan etkilerin doğru düzenlenmesi, OO tasarımının merkezindedir (bu durumda MVC modeli).

Tabii ki, bu yöntemlerin keyfi yan etkileri olması gerektiği anlamına gelmez. Ve yan etki göstermeyen işlevler, kodunuzun okunabilirliğini ve bazen performansını artıracak bir yere sahiptir.


1
Gözlemciler (UI dahil), nesnenizin gönderdiği mesajlara / olaylara abone olarak değişiklikler hakkında bilgi edinmelidir. Nesne doğrudan gözlemciyi değiştirmediği sürece bu bir yan etki değildir - ki bu kötü bir tasarım olacaktır.
ChrisF

1
@ChrisF Çoğu zaman bir yan etkisi var. Gözlemciye iletilen mesaj (büyük olasılıkla bir arabirimde bir yöntem çağrısı yapan bir OO dilinde), yığın değişiminde UI bileşeninin durumuna yol açar (ve bu yığın nesneleri programın diğer bölümleri tarafından görülebilir). UI bileşeni, ne metodun parametresi ne de geri dönüş değeri değildir. Resmi bir anlamda, bir fonksiyonun yan etkiden arınmış olması için kesin olması gerekir. MVC düzenindeki bildirim değildir, örneğin UI aldığı mesajların bir listesini görüntüleyebilir - konsol - iki kez çağırmak farklı bir program durumunda sonuçlanır.
flamingpenguin

0

Kötülük biraz üstte ... hepsi dilin kullanımının içeriğine bağlı.

Bahsedilenlerin bir başka düşüncesi, herhangi bir işlevsel yan etki yoksa, bir programın doğruluğunun ispatlarını daha basit hale getirmesidir.


0

Yukarıdaki soruların işaret ettiği gibi, işlevsel diller kodun yan etkilere sahip olmasını engellemez ; çünkü bize belirli bir kod parçasında ve hangi yan etkilerin gerçekleşebileceğini yönetmek için araçlar sağlar.

Bu çok ilginç sonuçlara yol açtı. Öncelikle ve en açık şekilde, zaten açıklanmış olan, yan etkisi olmayan kodlarla yapabileceğiniz birçok şey var. Ancak, yan etkileri olan kodlarla çalışırken bile yapabileceğimiz başka şeyler var:

  • Değişken durum kodunda, devletin kapsamını, verilen bir işlevin dışına sızmamasını sağlayacak şekilde statik olarak yönetebiliriz; bu, referans sayımı veya işaretleme ve tarama stili düzenleri olmadan çöp toplamamıza olanak tanır. Yine de hiçbir referansın hayatta kalmadığından emin olun. Aynı garantiler aynı zamanda gizliliğe duyarlı bilgilerin korunması vb. İçin de kullanışlıdır.
  • Birden fazla iş parçacığındaki paylaşılan durumu değiştirirken, değişiklikleri izleyerek ve işlemin sonunda bir atomik güncelleme gerçekleştirerek ya da işlemi başka bir iş parçacığı çelişkili bir değişiklik yaptıysa işlemi geri alıp tekrarlayarak kilitleme ihtiyacından kaçınabiliriz. Bu, ancak kodun durum modifikasyonlarından (mutlu bir şekilde bırakabileceğimiz) başka bir etkisinin olmamasını sağlayabilmemiz nedeniyle gerçekleştirilebilir. Bu, Haskell'deki STM (Yazılım İşlem Belleği) monad tarafından gerçekleştirilir.
  • Kodun etkilerini izleyebilir ve önemsiz bir şekilde kutulandırabiliriz, güvenli olduğundan emin olmak için gerçekleştirmesi gereken tüm efektleri filtreleyebiliriz, böylece (örneğin) kullanıcı tarafından girilen kodun bir web sitesinde güvenli bir şekilde yürütülmesine izin verebiliriz

0

Karmaşık kod tabanlarında, yan etkilerin karmaşık etkileşimleri, hakkında düşünmem gereken en zor şeydir. Kişisel olarak sadece beynimin çalıştığı şekilde konuşabiliyorum. Yan etkiler, ısrarcı durumlar ve mutasyona giren girdiler ve diğerleri, her bir işlevde sadece “ne” olduğunu değil, doğrulukla ilgili şeylerin “ne zaman” ve “nerede” olduğu hakkında düşünmeme neden oluyor.

Sadece "neye" odaklanamıyorum. Arayanlar hala yanlış zamanda, yanlış iş parçacığından, yanlış işyerinde yanlış zamanda çağırarak kötüye kullanabileceğinden, yan etkilere neden olan bir işlevi iyice test ettikten sonra tamamlayamam. sipariş. Bu arada, hiçbir yan etkiye neden olmayan ve sadece bir giriş verilen (girişe dokunmadan) yeni bir çıkış döndüren bir fonksiyonun, bu şekilde yanlış kullanılması oldukça imkansızdır.

Ama ben pragmatik bir türüm, sanırım ya da en azından olmaya çalışıyorum ve kodumuzun doğruluğunu düşünmek için en az tüm yan etkileri en bariz şekilde damgalamak zorunda olduğumuzu sanmıyorum (en azından) Bunu C) gibi dillerde yapmak çok zor bulur. Doğruluk konusunda mantıklı olmanın çok zor bulduğu nokta, karmaşık kontrol akışları ve yan etkiler kombinasyonuna sahip olduğumuz zamandır.

Karmaşık kontrol akışları bana doğada grafik benzeri, genellikle özyinelemeli veya özyinelemeli (örneğin, olayları doğrudan özyinelemeli olarak aramayan ancak doğada özyinelemeli "olan), belki bazı şeyleri yapan akışlardır. gerçek bir bağlantılı grafik yapısını geçme sürecinde ya da bizi kodbazın her türlü farklı parçasına ve hepsi farklı yan etkilere neden olacak şekilde işlemek için eklektik bir olaylar karışımı içeren homojen olmayan bir olay kuyruğunu işlerken. Nihayetinde kodun sonunda çıkacağınız tüm yerleri çizmeye çalıştıysanız, karmaşık bir grafiğe benzeyebilirdi ve potansiyel olarak asla beklemeyeceğiniz grafikteki düğümlerle, o anda orada bulunmuş olacaktı ve hepsinin aynı olduğu düşünülürse yan etkilere neden olmak,

İşlevsel diller son derece karmaşık ve özyinelemeli kontrol akışlarına sahip olabilir, ancak sonuçta doğruluk açısından anlaşılması çok kolaydır çünkü süreçte her türlü eklektik yan etki yoktur. Sadece karmaşık kontrol akışları, neler olup bittiğini ve her zaman doğru olanı yapıp yapmayacağını anlamak için baştan çıkarıcı bulduğu eklektik yan etkilerle karşılaştığında.

Bu yüzden, bu davaları aldığımda, bu kodun doğruluğu konusunda kendinden emin hissetmek imkansız olmasa da, beklenmedik bir şey açmadan bu kod üzerinde değişiklikler yapabileceğim konusunda kendime güvendiğim için çok zor buluyorum. Bu yüzden benim için çözüm ya kontrol akışını basitleştirmek ya da yan etkileri en aza indirgemek / birleştirmek. (Birleştirerek, demek istediğim, iki ya da üç ya da bir değil. düzine). Simpleton beynimin var olan kodun doğruluğu ve tanıttığım değişikliklerin doğruluğu konusunda kendinden emin hissetmesini sağlamak için bu iki şeyden birine ihtiyacım var. Eğer yan etkiler kontrol akışı ile birlikte aynı ve basit ise, yan etkileri ortaya çıkaran kodun doğruluğundan emin olmak oldukça kolaydır:

for each pixel in an image:
    make it red

Bu tür bir kodun doğruluğunu düşünmek oldukça kolaydır, ancak temel olarak yan etkiler çok tekdüze olduğundan ve kontrol akışı çok basit olduğu için. Ama diyelim ki böyle bir kodumuz var:

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

O zaman bu, gülünç derecede basitleştirilmiş sahte koddur ve tipik olarak çok daha fazla fonksiyon ve iç içe döngüler ve devam etmesi gereken çok daha fazla şey içerir (çoklu doku haritalarını, kemik ağırlıklarını, seçim durumlarını vb. Güncellemek), ancak sözde kodu bile zorlaştırır. karmaşık grafik benzeri kontrol akışının etkileşimi ve devam eden yan etkiler nedeniyle doğruluk nedeni. Bu yüzden bunu basitleştirmek için bir strateji, işlemi ertelemek ve bir seferde sadece bir tür yan etkiye odaklanmaktır:

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

... bir sadeleştirme yinelemesi olarak bu etkiye bir şey. Bu, kesinlikle bir hesaplama maliyetine neden olan veriyi defalarca ilettiğimiz anlamına gelir, ancak çoğu zaman bu sonuç kodunu daha kolay okuyabildiğimizi, artık yan etkiler ve kontrol akışlarının bu tek biçimli ve daha basit doğada gerçekleştiğini görüyoruz. Ayrıca, her ilmek bağlanmış grafiğin üzerinden geçmek ve ilerlerken yan etkilere neden olmaktan ötürü önbellek dostu hale getirilebilir (örneğin: ertelenen geçişleri sıralı sırayla yapabilmemiz için geçilmesi gerekenleri işaretlemek için paralel bir bit seti kullanın) bit maskesi ve FFS kullanarak). Fakat en önemlisi, ikinci versiyonun hatasızlık ve hatalara neden olmadan değişiklik anlamında sebep olması çok daha kolay. Böylece'

Ve sonuçta, bir noktada meydana gelmek için yan etkilere ihtiyacımız var, yoksa sadece gidecek hiçbir yerde veri çıkaran işlevlere sahip değiliz. Çoğunlukla bir şeyi bir dosyaya kaydetmemiz, bir ekrana bir şey göstermemiz, verileri bir soket üzerinden göndermemiz, bu türden bir şey ve bunların hepsi yan etkilerdir. Ancak devam eden gereksiz yan etkilerin sayısını azaltabilir ve kontrol akışları çok karmaşık olduğunda ortaya çıkan yan etkilerin sayısını azaltabiliriz ve eğer yaparsak hataları önlemenin çok daha kolay olacağını düşünüyorum.


-1

Bu kötü değil. Kanımca, yan etkileri olan ve olmayan iki fonksiyon tipini ayırt etmek gerekir. Yan etkisi olmayan işlev: - her zaman aynı argümanlarla aynı olur, yani herhangi bir argüman içermeyen bu işlev bir anlam ifade etmez. - Bu aynı zamanda, bu gibi bazı işlevlerin adlandırılma sırasının hiçbir rol oynamaması anlamına gelir - başka bir kod olmadan sadece tek başına (!) Çalıştırılabilir ve hata ayıklanabilir. Ve şimdi, lol, bak JUnit'in ne yaptığı. Yan etkileri olan bir fonksiyon: - otomatik olarak vurgulanabilen bir çeşit "sızıntı" vardır - genellikle yan etkilerden kaynaklanan hataların ayıklanması ve aranması çok önemlidir. - Yan etkileri olan herhangi bir fonksiyon, yan etkileri olmayan, ayrıca otomatik olarak ayrılabilen "bir parçasına" sahiptir. Yani kötülük bu yan etkilerdir.


bu, önceki 12
cevapta
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.