Küresel değişkenler neden kötüdür? [kapalı]


122

globalPython'da (ve genel olarak programlamada) kullanımının neden kötü bir uygulama olarak kabul edildiğini bulmaya çalışıyorum . Biri açıklayabilir mi? Daha fazla bilgi içeren bağlantılar da takdir edilecektir.


Yeniden açılması için oylama - Odağı açıklamalara ve saha dışındaki kaynaklardan uzaklaştırmak için soruyu düzenledim. (Ben kapatıldığı yüzden varsayalım, ama her ihtimale karşı kötü uygulama hakkında soru olmak ile ilgisi 's şey, hala açık kötü uygulama hakkında bu soruları karşılaştırmak: eval, import *, dize birleştirme , değişkenid , özellik gölgeler )
wjandrea

Yanıtlar:


156

Bunun Python ile ilgisi yoktur; genel değişkenler herhangi bir programlama dilinde kötüdür.

Ancak, genel sabitler kavramsal olarak küresel değişkenlerle aynı değildir ; küresel sabitler tamamen zararsızdır. Python'da ikisi arasındaki ayrım tamamen gelenekseldir: CONSTANTS_ARE_CAPITALIZEDve globals_are_not.

Küresel değişkenlerin kötü olmasının nedeni, işlevlerin gizli (açık olmayan, şaşırtıcı, tespit edilmesi zor, teşhis edilmesi zor) yan etkilere sahip olmasını sağlayarak karmaşıklıkta bir artışa yol açması ve potansiyel olarak Spagetti koduna yol açmasıdır .

Bununla birlikte, küresel durumun mantıklı kullanımı (yerel durum ve değişkenlik gibi), ya algoritma optimizasyonu, azaltılmış karmaşıklık, önbelleğe alma ve hafızaya alma ya da ağırlıklı olarak zorunlu bir kod tabanından kaynaklanan taşıma yapılarının pratikliği için işlevsel programlamada bile kabul edilebilir.

Sonuç olarak, sorunuz birçok şekilde yanıtlanabilir, bu nedenle yapabileceğiniz en iyi şey, "global değişkenler neden kötüdür" diye google'da bulunmaktır. Bazı örnekler:

Daha derine inmek ve neden yan etkilerin ve diğer birçok aydınlatıcı şeyin neden olduğunu öğrenmek istiyorsanız, İşlevsel Programlamayı öğrenmelisiniz:


35

Evet, teoride , küreseller (ve genel olarak "devlet") kötüdür. Pratikte, python'un paketler dizinine bakarsanız, oradaki modüllerin çoğunun bir grup genel bildirimle başladığını göreceksiniz. Açıkçası, insanların onlarla bir sorunu yok.

Özellikle python ile ilgili olarak, küresellerin görünürlüğü bir modülle sınırlıdır, bu nedenle tüm programı etkileyen "gerçek" küreseller yoktur - bu da onları daha az zararlı yapar. Başka bir nokta: yok const, bu yüzden bir sabite ihtiyacınız olduğunda bir global kullanmanız gerekir.

Uygulamamda, bir fonksiyondaki bir globali değiştirirsem global, teknik olarak buna gerek olmasa bile, aşağıdaki gibi her zaman ile beyan ederim :

cache = {}

def foo(args):
    global cache

    cache[args] = ...

Bu, küresellerin manipülasyonlarının izini sürmeyi kolaylaştırır.


3
birçok yönden, python'daki bir modül bir singleton sınıfına benzer ve modül globalleri sınıf özelliklerine benzer.
Corley Brigman

9
@CorleyBrigman: singleton sınıfları aslında genellikle küresellere atfedilen aynı sorunlardan muzdarip :)
Erik Kaplun

4
python modüllerinin görünürlüğü bir modülle sınırlı değildir. Tercümanın tamamında mevcuttur ve (burada önemli olan) buradaki değişiklikler tüm tercümanı etkiler. Örnekleri yarattığınız bir dizge gibi değildir ... tüm dizge örneklerini değiştirmek gibidir. Maymun yamalı kokusu.
graffic

2
Çoğu modül, sabitler dışında globalleri tanımlamaya başlamaz . Küreseller kötü, değişkenler / küresel durum sabitler değil demektir .
BlackJack

2
Globals kullanmak korkunç bir fikirdir, bunun bir nedeni, "bir yerde" var olan bazı gelişigüzel sözlüğü güncelleyen işlevlerin düzgün şekilde test edilememesi olabilir. Küreselleri olan bir kod tabanının gerçekten işlevsel olduğu kanıtlanamaz.
Tomasz Sosiński

10

Konuyla ilgili kişisel bir görüş, bir işlev mantığında kullanılan global değişkenlere sahip olmanın, başka bir kodun bu işlevin mantığını ve beklenen çıktısını değiştirebileceği anlamına geldiği ve bu da hata ayıklamayı çok zorlaştıracağı (özellikle büyük projelerde) ve testi zorlaştıracağıdır. yanı sıra.

Ayrıca, kodunuzu okuyan diğer insanları (açık kaynak topluluğu, meslektaşları vb.) Düşünürseniz, küresel değişkenin nerede ayarlandığını, nerede değiştirildiğini ve bunun tersine bu küresel değişkenden ne bekleyeceklerini anlamakta zorlanacaklardır. izole edilmiş bir işleve, işlevselliğinin işlev tanımının kendisini okuyarak belirlenebileceği.

(Muhtemelen) Saf İşlev tanımını ihlal ediyor

Temiz ve (neredeyse) hatasız bir kodun olabildiğince saf işlevlere sahip olması gerektiğine inanıyorum (bkz. Saf işlevler ). Saf işlev, aşağıdaki koşullara sahip olandır:

  1. İşlev , aynı bağımsız değişken değeri / değerleri verildiğinde her zaman aynı sonuç değerini değerlendirir . Fonksiyon sonuç değeri, program yürütülürken veya programın farklı yürütmeleri arasında değişebilecek herhangi bir gizli bilgiye veya duruma bağlı olamaz veya G / Ç cihazlarından gelen herhangi bir harici girişe bağlı olamaz (genellikle - aşağıya bakın).
  2. Sonucun değerlendirilmesi, değiştirilebilir nesnelerin mutasyonu veya G / Ç cihazlarına çıkış gibi anlamsal olarak gözlemlenebilir herhangi bir yan etkiye veya çıktıya neden olmaz .

Global değişkenlere sahip olmak yukarıdakilerden en az birini ihlal ediyor değilse de, harici bir kod muhtemelen beklenmedik sonuçlara neden olabilir.

Saf işlevlerin başka bir net tanımı: "Saf işlev, tüm girdilerini açık bağımsız değişkenler olarak alan ve tüm çıktılarını açık sonuçlar olarak üreten bir işlevdir ." [1] . Global değişkenlere sahip olmak, bir girdi ve belki de çıktılardan biri (global değişken) açıkça verilmediği veya verilemediği için saf fonksiyon fikrini ihlal eder.

(Muhtemelen) İhlal Eden Birim testi İLK ilkesi

Eğer birim test ve İLK prensibini göz önüne alırsak Dahası bu konuda, ( F ast testleri, ben ndependent testler, R epeatable, S elf Sınamayan ve T imely) Bağımsız (ilke testleri ihlal muhtemelen hangi testler bağımlı olmayan araçlar her birine).

Küresel bir değişkene sahip olmak (her zaman değil), ancak çoğu durumda (en azından şimdiye kadar gördüklerimin) sonuçları hazırlamak ve diğer işlevlere aktarmaktır. Bu da bu prensibi ihlal ediyor. Global değişken bu şekilde kullanılmışsa (yani, X fonksiyonunda kullanılan global değişken önce bir Y fonksiyonunda ayarlanmalıdır), bu, X fonksiyonunu test etmek için önce test / çalıştır fonksiyonunu çalıştırmanız gerektiği anlamına gelir.

Sabit olarak küreseller

Öte yandan ve diğer insanların daha önce de bahsettiği gibi, global değişken "sabit" bir değişken olarak kullanılırsa, dil sabitleri desteklemediği için biraz daha iyi olabilir. Bununla birlikte, ben her zaman sınıflarla çalışmayı ve "sabitleri" sınıf üyesi olarak kullanmayı ve global bir değişken kullanmamayı tercih ederim. İki farklı sınıfın global bir değişkeni paylaşmak için gerektirdiği bir kodunuz varsa, muhtemelen çözümünüzü yeniden düzenlemeniz ve sınıflarınızı bağımsız hale getirmeniz gerekir.

Küresellerin kullanılmaması gerektiğine inanmıyorum. Ancak kullanılırlarsa, yazarlar daha temiz ve neredeyse hatasız bir kod için bazı ilkeleri (yukarıda belirtilenler ve diğer yazılım mühendisliği ilkeleri ve iyi uygulamalar) dikkate almalıdır.


1
"Sabit olarak küreseller bir sorundur" ... çünkü OO tasarımı yapıyorsanız ... gerçekten öyledir. Neden IdCreator sınıfı dışında kimsenin ID_LEN'i bilmesi gerekiyor?
Erik Aronesty

3

Bunlar çok önemlidir, ekran iyi bir örnektir. Bununla birlikte, çok iş parçacıklı bir ortamda veya birçok geliştiricinin dahil olduğu uygulamada sıklıkla şu soru ortaya çıkar: bunu kim (yanlış bir şekilde) ayarladı veya temizledi? Mimariye bağlı olarak, analiz maliyetli olabilir ve sıklıkla gerekli olabilir. Global değişkeni okurken uygun olabilir, ona yazma, örneğin tek bir iş parçacığı veya iş parçacığı güvenli bir sınıf tarafından kontrol edilmelidir. Bu nedenle, küresel çapta, kendileri için kötü olarak değerlendirilen sonuçların olası yüksek geliştirme maliyetleri korkusu ortaya çıkar. Bu nedenle, genel olarak, küresel değişkenlerin sayısını düşük tutmak iyi bir uygulamadır.

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.