Bir programcıya referans şeffaflığının faydaları nelerdir?


18

Programlamada, referans şeffaflığının faydaları nelerdir?

RT, işlevsel ve zorunlu paradigmalar arasındaki en büyük farklardan birini yapar ve genellikle fonksiyonel paradigmanın savunucuları tarafından zorunlu olana göre açık bir avantaj olarak kullanılır; fakat tüm çabalarında, bu savunucular bir programcı olarak bana neden fayda sağladığını asla açıklamazlar .

Elbette, bunun ne kadar "saf" ve "zarif" olduğuna ilişkin akademik açıklamaları olacak, ancak daha az "saf" bir koddan daha iyi hale nasıl getirecekler? Günlük programımda bana nasıl fayda sağlar?

Not: Bu , referans şeffaflığı nedir? İkincisi RT'nin ne olduğu konusunu ele alırken, bu soru faydalarını (bu kadar sezgisel olmayabilir) ele alır.




3
Referans şeffaflığı, aşağıdakiler için denklemsel akıl yürütme kullanmanıza izin verir : 1) Kodun özelliklerini kanıtlamak ve 2) yazma programları. Haskell hakkında yazarların tamfil fonksiyonunu istediğiniz bazı denklemlerden nasıl başlayabileceği ve sadece denklemsel akıl yürütmeyi kullanarak nerede olmanız gerektiğini söyleyen birkaç kitap vardır. Şimdi bu "günlük" programlamada ne kadar uygulanabilir muhtemelen bağlama bağlıdır ...
Bakuriu

2
@err Bir işlevi iki kez çağırmanın değerini bir değişkende saklayıp sonra bahsedilen değişkeni iki kez kullanmakla aynı olup olmadığını bildiğiniz için yeniden düzenlenmesi daha kolay olan kodu sever misiniz? Bunun günlük programlamanız için bir fayda olduğunu söyleyebilir misiniz?
Andres F.

Bunun yararı, referandumda şeffaflık hakkında düşünmek için zaman kaybetmenize gerek olmamasıdır. Değişkenlerin faydaları, kayıt tahsisi hakkında düşünmek için zaman kaybetmenize gerek olmaması gibi.
user253751

Yanıtlar:


37

Bunun yararı, saf işlevlerin kodunuzun akıl yürütmesini kolaylaştırmasıdır. Veya başka bir deyişle, yan etkiler kodunuzun karmaşıklığını artırır.

Bir computeProductPriceyöntem örneği alın .

Saf bir yöntem sizden ürün miktarı, para birimi vb. İster. Yöntem aynı argümanlarla çağrıldığında her zaman aynı sonucu üreteceğini bilirsiniz .

  • Hatta önbelleğe alabilir ve önbelleğe alınmış sürümü kullanabilirsiniz.
  • Tembel yapabilir ve gerçekten ihtiyaç duyduğunuzda çağrısını erteleyebilirsiniz, değerin bu arada değişmeyeceğini bilerek.
  • Yan etkileri olmayacağını bilerek yöntemi birden çok kez çağırabilirsiniz.
  • İhtiyaç duyulan her şeyin argüman olduğunu bilerek, yöntemin kendisini dünyadan soyutlanarak akıl edebilirsiniz.

Saf olmayan bir yöntemin kullanımı ve hata ayıklaması daha karmaşık olacaktır. Değişkenler dışındaki değişkenlerin durumuna bağlı olduğu ve muhtemelen değiştirildiği için, birden çok kez çağrıldığında farklı sonuçlar üretebileceği veya hiç çağrılmadığında veya çok erken veya çok geç çağrıldığında aynı davranışa sahip olamayacağı anlamına gelir.

Misal

Çerçevede bir sayıyı ayrıştıran bir yöntem olduğunu düşünün:

decimal math.parse(string t)

Referans şeffaflığı yoktur, çünkü şunlara bağlıdır:

  • Numaralandırma sistemini belirten ortam değişkeni, yani Taban 10 veya başka bir şey.

  • mathKitaplık içindeki, ayrıştırılacak sayıların kesinliğini belirten değişken . Yani değeri ile 1, dizeyi ayrıştırmak "12.3456"verir 12.3.

  • Beklenen biçimlendirmeyi tanımlayan kültür. Örneğin fr-FR, ayrıştırma "12.345"verir 12345, çünkü ayırma karakteri olmamalıdır ,,.

Böyle bir yöntemle çalışmanın ne kadar kolay veya zor olacağını düşünün. Aynı girişle, yöntemi çağırdığınız ana bağlı olarak radikal olarak farklı sonuçlara sahip olabilirsiniz, çünkü bir şey, bir yerde ortam değişkenini değiştirdi veya kültürü değiştirdi veya farklı bir hassasiyet ayarladı. Yöntemin deterministik olmayan karakteri daha fazla hataya ve daha fazla hata ayıklamaya neden olan kabusa yol açar. Bazı paralel kod sekizlik sayıları ayrıştırdığı için çağrı yapmak math.parse("12345")ve 5349cevap almak hoş değildir.

Açıkçası kırık olan bu yöntem nasıl düzeltilir? Referans şeffaflığı getirerek. Başka bir deyişle, küresel durumdan kurtulup her şeyi yöntemin parametrelerine taşıyarak:

decimal math.parse(string t, base=10, precision=20, culture=cultures.en_us)

Şimdi yöntem saf olduğuna göre, yöntemi çağırdığın önemli değil, her zaman aynı argümanlar için aynı sonucu üreteceğini biliyorsun.


4
Yalnızca bir zeyilname: bilgi şeffaflığı, yalnızca işlevler için değil, bir dildeki tüm ifadeler için geçerlidir.
gardenhead

3
Ne kadar şeffaf olabileceğiniz konusunda sınırlamalar olduğunu unutmayın. packet = socket.recv()Referans olarak saydam yapmak , işlevin noktasını yener.
Mark

1
Kültür = kültür olmalı. Değişmez. Eğer sürece istediğiniz yanlışlıkla sadece ABD'de düzgün çalışan yazılımları oluşturun.
user253751

@immibis: hm, güzel soru. Ayrıştırma kuralları ne için olurdu invariant? Ya onlar ile aynı en_us, bu durumda, neden rahatsız, ya da başka bir ülkeye karşılık geliyorlar, bu durumda, hangisi ve neden bunun yerine en_us, ya da yine de herhangi bir ülkeyle eşleşmeyen özel kuralları var işe yaramaz. Arasında gerçekten hayır “gerçek cevap” yoktur 12,345.67ve 12 345,67: herhangi bir “varsayılan kuralları” Birkaç ülke için çalışmak, ve diğerleri için çalışma olmaz edecektir.
Arseni Mourzenko

3
@ArseniMourzenko Genellikle bir "en düşük ortak payda" ve birçok programlama dilinin kullandığı sözdizimine benzer (aynı zamanda kültür değişmez). 1234512345 olarak ayrıştırmak için, 12 345ya da 12,345ya da 12.345bir hatadır. 12.345değişmez bir kayan noktalı sayı olarak ayrıştırıldığında, programlama dili kullanım kuralına uygun olarak daima 12.345 elde edilir. ondalık ayırıcı olarak. Dizeler Unicode kod noktalarına ve büyük / küçük harfe duyarlı olarak sıralanır. Ve bunun gibi.
user253751

11

Ne olduğunu çözmek için kodunuzdaki bir noktaya sık sık bir kırılma noktası ekler ve uygulamayı hata ayıklayıcıda çalıştırır mısınız? Bunu yaparsanız, bunun nedeni büyük ölçüde tasarımlarınızda referans şeffaflığı (RT) kullanmamanızdır. Ve bu yüzden ne işe yaradığını çözmek için kodu çalıştırmak zorunda.

RT'ye bütün mesele, kodun son derece belirleyici olmasıdır, yani kodu okuyabilir ve aynı girdi seti için her seferinde ne yaptığını öğrenebilirsiniz. Bazıları tek bir işlevin ötesinde kapsamı olan değişkenleri değiştirmeye başladığınızda, kodu okuyamazsınız. Gerçekte nasıl çalıştığını anlamak için bu kodun kafanızda veya hata ayıklayıcıda yürütülmesi gerekir.

Kod ne kadar basit okunursa ve nedense, hatalar o kadar kolay korunur ve tespit edilir, böylece sizin ve işvereniniz için zaman ve para tasarrufu sağlar.


10
"Bazıları tek bir işlevin ötesinde olan mutasyona uğrayan değişkenleri eklemeye başladığınızda, kodu sadece okuyamazsınız, gerçekten nasıl çalıştığını anlamak için bunu başınızda veya hata ayıklayıcıda yürütmeniz gerekir. ": İyi bir nokta. Başka bir deyişle, referans şeffaflığı sadece bir kod parçasının aynı girdiler için her zaman aynı sonucu üreteceği anlamına gelmez, aynı zamanda üretilen sonucun bu kod parçasının tek etkisi olduğu, başka gizli bir taraf olmadığı anlamına gelir. başka bir modülde çok uzakta tanımlanmış bir değişkeni değiştirmek gibi.
Giorgio

Bu iyi bir nokta. Ben bir sorun var biraz daha basit kod okumak / neden bağımsız değişken, çünkü okumak daha basit veya nedeni biraz belirsiz ve öznel bir kod özniteliği.
Eyal Roth

Bazıları tek bir işlevin ötesinde kapsamı olan değişkenleri eklemeye başladıktan sonra , değişken kapsamı işlev için yerel olsa bile atama işlemi neden önerilmez?
rahulaga_dev

9

İnsanlar "mantık yürütmek daha kolay" terimini atarlar, ama bunun ne anlama geldiğini asla açıklamazlar. Aşağıdaki örneği düşünün:

result1 = foo("bar", 12)
// 100 lines of code
result2 = foo("bar", 12)

Are result1ve result2aynı ya da farklı? Referans şeffaflığı olmadan, hiçbir fikriniz yoktur. Aslında fooemin olmak için vücudunu okumalısınız ve muhtemelen herhangi bir fonksiyonun vücudunu fooçağırır, vb.

İnsanlar bu yükü fark etmezler çünkü buna alışkındırlar, ancak bir ya da iki ay boyunca tamamen işlevsel bir ortamda işe giderseniz, geri dönün, hissedeceksiniz ve bu çok büyük bir anlaşma .

İnsanların referans şeffaflığı eksikliği üzerinde çalışmak için yaptıkları birçok savunma mekanizması vardır. Küçük örneğim için, result1bellekte kalmak isteyebilirim , çünkü değişip değişmeyeceğini bilemezdim. Sonra iki durum ile kod var: önce result1depolanmış ve sonra. Referans şeffaflığı ile, yeniden hesaplama zaman alıcı olmadığı sürece kolayca yeniden hesaplayabilirim.


1
Referans şeffaflığının, foo () çağrılarının sonucu hakkında mantık yürütmenizi result1ve result2aynı olup olmadığını ve bilmenizi sağladığından bahsettiniz . Bir başka önemli husus, eğer foo("bar", 12)referans olarak saydamsa, kendinize bu çağrının başka bir yerde bazı efektler üretip üretmediğini sormanıza gerek yoktur (bazı değişkenleri ayarlayın? Bir dosyayı sildiniz mi?
Giorgio

Bildiğim tek "referans bütünlüğü", ilişkisel veritabanlarını içerir.
Mark

1
@ Mark Bu bir yazım hatası. Karl cevabının geri kalanından da anlaşılacağı gibi referans şeffaflığı demekti.
Andres F.

6

Şunu söyleyebilirim: referans şeffaflığı sadece fonksiyonel programlama için değil, işlevlerle çalışan herkes için de iyi çünkü en az şaşkınlık ilkesine bağlı.

Bir işleve sahipsiniz ve ne yapması gerektiği konusunda daha iyi bir neden olabilir, çünkü dikkate almanız gereken harici faktörler yoktur, belirli bir giriş için çıktı her zaman aynı olacaktır. Zorunlu dilimde bile bu paradigmayı olabildiğince takip etmeye çalışıyorum, temelde otomatik olarak bundan sonra gelen bir sonraki şey: bazen koştuğum korkunç 1000+ çizgi fonksiyonları yerine anlaşılması kolay küçük fonksiyonlar.

Bu büyük işlevler sihir yapar ve onlara dokunmaktan korkarım çünkü muhteşem yollarla kırılabilirler.

Bu yüzden saf fonksiyonlar sadece fonksiyonel programlama için değil, her program için bir şeydir.

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.