Global değişkenler kötü mü? [kapalı]


247

C / C ++ 'da, küresel değişkenler profesörümün düşündüğü kadar kötü mü?


17
Bir şaka anlatmaya çalışması durumunda ısırırım ... "ne kadar kötüler?"
Zach Scrivena

13
Bu sorunun oldukça ilginç olduğunu düşünüyorum! Yazılım geliştirme, başlangıçtan beri hala aynı eski tuzaklarla karşı karşıyadır ve programcılar genellikle küresel değişkenler, gotolar, kısa adlandırılmış değişken kullanmanın sorun OLMADIĞINI bilmemektedir. Kötü kod her gün kullanılmadan yazılır. +1
Sylvain Rodrigue

69
Nasıl cevap verebiliriz? Bize profesörünün ne kadar kötü olduğunu düşündüğünü söylemedi. :)
Steve Fallows

9
@Juan Mendes I% 100 sana katılıyorum! Bahsettiğim sorun, birçok geliştiricinin küresel değişkenleri kullanmamaları gerektiğini bilmeleri, ancak nedenini bilmiyor olmalarıdır! Ve böylece, her fonksiyonun +100 alan içeren aynı mega yapıyı aldığı birçok büyük yazılım gördüm - Bak anne, küresel değişken yok! "İyi uygulamalar" olarak adlandırılanla aynı sorun: bazı bağlamlarda değil, BAZI bağlamlarda iyi uygulamalardır. Bunları kullanmak, bakım gerektirmeyen kod oluşturabilir. Şerefe.
Sylvain Rodrigue

3
Global değişkenler için çok az iyi kullanım vardır. Olası ama tartışmalı bir kullanım, başlangıçta bir kez yapılandırma dosyasında okunan global bir "yapılandırma" nesnesi olacaktır.
Siler

Yanıtlar:


257

Global değişkenlerle ilgili sorun, her fonksiyonun bunlara erişimi olduğundan, hangi fonksiyonların bu değişkenleri gerçekten okuyup yazdığını anlamak giderek zorlaşmaktadır.

Uygulamanın nasıl çalıştığını anlamak için, küresel durumu değiştiren her işlevi dikkate almanız gerekir. Bu yapılabilir, ancak uygulama büyüdükçe neredeyse imkansız (ya da en azından tam bir zaman kaybı) noktasına zorlaşacaktır.

Global değişkenlere güvenmiyorsanız, gerektiğinde farklı işlevler arasında durum iletebilirsiniz. Bu şekilde, küresel durumu hesaba katmanıza gerek olmadığından, her bir işlevin ne yaptığını anlama şansınız daha yüksektir.


10
Bu cevap gerçekten çok iyi. Bunu 'değişken kapsamı en aza
indir

17
'Global' için 'application' ve 'object state' yerine 'class' yazın ve sınıflarda üye değişkenleri (aka alanları) kullanmamanız için tam olarak aynı argümanı yapın. Gerçek cevap, uygun olduğunda onları kullanmaktır.
Ian Goldby

2
Birkaç (belki de aptalca) soru: 1) Bu değişkenleri hangi işlevlerin okuyup yazacağını bilmek istiyorsanız, bu değişkenlerdeki değerlerin değiştirildiği durumları tespit etmek için bir düzenleyicideki "find" işlevini kullanamaz mıydınız? 2) "Bu yapılabilir, ... tam bir zaman kaybı)." Bir örnek verebilir misin? 3) "Global değişkenlere güvenmiyorsanız ... küresel durumu dikkate almanıza gerek yoktur." Bunun nasıl bir avantaj olduğunu anlamıyorum. Belki bunun bir örneği benim için işe yarar.
Andrei

2
@bobobobo bozuk bağlantı, sizden bir ekran görüntüsü alabilir miyiz, 10k + kullanıcı?
noɥʇʎԀʎzɐɹƆ

3
@ noɥʇʎԀʎzɐɹƆ İşte başlıyoruz! i.imgur.com/RwRgJLZ.jpg
Mateen Ulhaq

85

Önemli olan genel hedefi hatırlamaktır: netlik

"Global değişken yok" kuralı oradadır, çünkü çoğu zaman global değişkenler kodun anlamını daha az netleştirir.

Bununla birlikte, birçok kural gibi, insanlar kuralın ne yapmak istediğini değil, kuralı hatırlar.

Ben sadece küresel değişkenlerin kötülük önlemek için etrafında çok sayıda parametre geçirerek kod boyutunu iki katına gibi görünen programlar gördüm. Sonunda, küreselleri kullanmak programı okuyanlara daha açık hale getirecektir . Kuralsız bir şekilde kuralın sözüne bağlı kalarak, orijinal programcı kuralın niyetinde başarısız olmuştu.

Evet, küreseller genellikle kötüdür. Ama sonunda, programlayıcının amacının küresel değişkenlerin kullanımı ile daha net hale getirildiğini düşünüyorsanız, devam edin. Ancak, ilk parçanın nasıl çalıştığını anlamak için birini ikinci bir kod parçasına (globaller) erişmeye zorladığınızda otomatik olarak ortaya çıkan netlik düşüşünü unutmayın.


8
Değişkenleri geçmek yerine bir global kullanmayı önermek, kodunuzu tekrar kullanılamaz hale getirmek için bir reçetedir ve çoklu iş parçacığı için güvenli değildir
Juan Mendes

16
Globalleri doğru koşullarda önermek, daha net ve daha yüksek performanslı kod için bir reçetedir. "Passing" sabit yığın dinamik bellek tahsisi gerektirir ve bu, gelen soket verileri için global tampon gibi global olması gereken bir şey için saçma olur. Örneğin, Winsock recv () 'i okuyan bir işleviniz varsa, neden bu arabellek her çağrıda sürekli oluşturulur ve yeniden sıralanır? Tamponu global yapın. Birden çok iş parçacığı zaten okumuyor.
James

Sadece merak ediyorum, hangi program küresel değişkenlerden kaçınmak için parametreleri aktararak kodun boyutunu iki katına çıkarır? Deneyimlerime göre, global değişkenleri kullanmak veri maruziyeti sorunlarını çözebilir, ancak genellikle bu sihirli değişkenlerin düzgün davranmasını sağlamak için eklemeniz gereken ek karmaşık mantık vardır.
user2167582

3
Birisi yaklaşık 100 değişkeni geçiyorsa, bir nesnenin ne olduğunu öğrenmediler. Bu nesneye yapılan başvuruyu kullanmak, daha sonra bir işaretçiyi en kötü şekilde geçirir. Kuralın sadece açıklık değil, aynı zamanda test edilebilirlik olduğunu da söyleyebilirim - ve küresel olmayan bir şeyi kullanmak, işleri test etmeyi çok daha kolay hale getirir.
UKMonkey

2
"Birisi yaklaşık 100 değişkeni geçiyorsa, bir nesnenin ne olduğunu öğrenmediler." Kabul etti, ancak tüm dünya nesne yönelimli değil. Kod boyutunu ikiye katlama konusundaki kişisel örneğim 1986 dolaylarında büyük bir Fortran programıydı. Üniversite çalışanlarından yeni bir kişi olarak, her çağrıyı yaklaşık 30 parametre ekleyerek tüm globalleri ortadan kaldırarak "geliştirdim". Sonra, ne yaptığımı fark ettiğimde gelişimimi çözdüm.
Tom West

64

Profesörüm şöyle bir şey söylerdi: bunları doğru kullanırsanız global değişkenleri kullanmak iyidir. Onları doğru bir şekilde kullanmakta iyi olduğumu sanmıyorum, bu yüzden nadiren kullandım.


25
Çok doğru. Goto gibiler, eğer onları ne zaman kullanacağınızı bilmiyorsanız, asla yapmayın.
David Holm

5
Şu anki şirketimde staticküresel değişkenleri çok kullanıyorlar, dil C. Nispeten küçük çeviri birimleriyle sınırlı olduklarında, C ++ nesnelerinin sınıf değişkenlerine benzemeye başlıyorlar.
Ocak'ta Vorac

1
@Vorac statik değişkenleri global değişkenler değil, yerel değişkenlerdir. Global değişken, programın her yerinde kullanılabilen bir değişkendir (dolayısıyla "global", duh). Herhangi bir işlevin dışında bildirilen değişkenler olan dosya kapsamı değişkenleriyle karıştırılmamalıdır . Statik dosya kapsam değişkeni genel bir değişken değil.
Lundin

1
Kendimi düzeltmek için program lifetime, file scope variables. Ve değişkene dış dünyaya (otomatik değişkenlerle imkansız) bir işaretçi geçtikten sonra oldukça küresel hale gelirler.
Vorac

@Lundin Kabul ediyorum, staticGlobal değişkenlerin kapsamı aynı çeviri birimiyle sınırlı. Ancak programın sonuna kadar herhangi bir küresel değişken olarak kullanım ömürleri vardır.
akhilesh1988

38

Global değişkenler yalnızca alternatifiniz olmadığında kullanılmalıdır. Ve evet, Singletons da buna dahil. Zamanın% 90'ı, bir parametreyi geçirme maliyetinden tasarruf etmek için global değişkenler tanıtılır. Ve sonra çoklu iş parçacığı / birim testi / bakım kodlaması gerçekleşir ve bir sorununuz vardır.

Yani evet, durumların% 90'ında küresel değişkenler kötüdür. İstisnaların üniversite yıllarınızda görülmesi olası değildir. Başımın üstünden düşünebileceğim bir istisna, kesme tabloları gibi doğal olarak küresel nesnelerle uğraşmaktır. DB bağlantısı gibi şeyler küresel görünmektedir , ancak değildir.


2
Bunun tek istisnası olduğunu ben üniversite yıllarında testere grafikleri geri arama fonksiyonları oldu. XWindows da, fare geri aramaları programın devletin keyfi parçalarını etrafında geçmesine izin void * veri argümanları ... yoktu (değil ... Küresel oldu Neyse daha çok daha iyi olmak kadar o biter)
Brian Postow

10
+1 için "DB bağlantısı gibi şeyler global görünüyor , ancak değil."
R .. GitHub BUZA YARDIMCI DURDUR

1
Kesme tabloları genel değildir, işlemci başına bir tane vardır - ancak işlemci başına programınızın bir örneği de vardır, böylece "iptal eder".
user253751

1
Herkes lütfen DB bağlantılarının neden küresel olmadığına (ve iyi bir alternatif olabilir) aydınlatabilir mi? Bağlantıları her zaman küresellerin kabul edilebilir olduğu nadir durumlardan biri olarak düşündüm.
Floella

33

Global değişkenlerin programcı için yarattığı sorun, global değişkenleri kullanan çeşitli bileşenler arasında bileşenler arası bağlantı yüzeyini genişletmesidir . Bunun anlamı, küresel bir değişken kullanan bileşenlerin sayısı arttıkça, etkileşimlerin karmaşıklığının da artabileceğidir. Bu artan bağlantı genellikle değişiklik yaparken hataların sisteme enjekte edilmesini kolaylaştırır ve ayrıca arızaların teşhis edilmesini ve düzeltilmesini zorlaştırır. Bu artış bağlantısı, değişiklik yaparken mevcut seçeneklerin sayısını da azaltabilir ve değişikliklerin sonucunu belirlemek için küresel değişkeni kullanan çeşitli modüller üzerinden sık sık izlenmesi gereken değişiklikler için gerekli çabayı artırabilir.

Amacı Temel olarak küresel değişkenleri kullanmanın tersi olan kapsüllemenin , kaynağın daha kolay ve daha güvenli ve daha kolay test edilmesini sağlamak ve değiştirmek için kuplajı azaltmaktır. Global değişkenler kullanılmadığında birim testi kullanmak çok daha kolaydır .

Örneğin, çeşitli bileşenlerin durum makinesi olarak kullandığı numaralandırılmış bir gösterge olarak kullanılan basit bir küresel tamsayı değişkeniniz varsa ve daha sonra yeni bir bileşen için yeni bir durum ekleyerek bir değişiklik yaparsanız, diğer tüm öğeleri izlemelisiniz. Değişikliklerin bunları etkilemeyeceğinden emin olmak için Olası bir soruna örnek olarak switch, numaralandırma genel değişkeninin değerinicase , geçerli değerlerin her biri için çeşitli yerlerde kullanılıyorsa ve bazı switchifadelerin defaultişlenecek bir vakası yoksa küresel için beklenmedik bir değer aniden uygulama söz konusu olduğunda tanımlanmamış davranışınız var.

Öte yandan, paylaşılan bir veri alanının kullanımı, uygulama boyunca referans verilen bir dizi küresel parametreyi içermek için kullanılabilir. Bu yaklaşım genellikle küçük bellek alanlarına sahip gömülü uygulamalarda kullanılır.

Bu tür uygulamalarda global değişkenler kullanılırken, tipik olarak veri alanına yazma sorumluluğu tek bir bileşene tahsis edilir ve diğer tüm bileşenler alanı constasla olarak yazmaz, alan olarak görür ve okur. Bu yaklaşımı uygulamak gelişebilecek sorunları sınırlar.

Üzerinde çalışılması gereken küresel değişkenlerden birkaç sorun

Yapı gibi genel bir değişkenin kaynağı değiştirildiğinde, değişkeni kullanan her şeyin gerçek boyutunu ve bellek şablonunu bilmesi için onu kullanan her şey yeniden derlenmelidir.

Birden fazla bileşen genel değişkeni değiştirebilirse, genel değişkente tutarsız verilerin bulunmasıyla ilgili sorunlarla karşılaşabilirsiniz. Çok iş parçacıklı bir uygulamada, bir kerede yalnızca bir iş parçacığının genel değişkeni değiştirebilmesi ve bir iş parçacığı değişkeni değiştirdiğinde, tüm değişikliklerin tamamlanması için bir yol sağlamak için muhtemelen bir tür kilitleme veya kritik bölge eklemeniz gerekecektir. ve diğer iş parçacıkları değişkeni sorgulamadan veya değiştirmeden önce taahhütte bulunur.

Genel değişken kullanan çok iş parçacıklı bir uygulamada hata ayıklamak daha zor olabilir. Yarış koşullarına girebilirsiniz çoğaltmak zor olan kusurları oluşturabilir. Küresel bir değişken üzerinden iletişim kuran birkaç bileşenle, özellikle çok iş parçacıklı bir uygulamada, değişkeni hangi bileşenin değiştirdiğini ve değiştiğini nasıl değiştirdiğini bilmek çok zor olabilir.

Ad çakışması, global değişkenlerin kullanımı ile ilgili bir sorun olabilir. Genel değişkenle aynı ada sahip yerel bir değişken genel değişkeni gizleyebilir. C programlama dilini kullanırken de adlandırma kuralı sorunuyla karşılaşırsınız. Çözüm, sistemi aynı ilk üç harfle başlayan belirli bir alt sistem için küresel değişkenlerle alt sistemlere ayırmaktır (bu, hedef C'deki ad alanı çarpışmalarının çözümlenmesi için bkz .). C ++, ad alanları sağlar ve C ile, üyeleri çeşitli veri öğeleri ve bir dosyada statik olarak sağlanan veri ve işlevlere yalnızca veri görünürlüğü ile sağlanan, böylece yalnızca başvuruda bulunabilmeleri için sağlanan, genel olarak görünür bir yapı oluşturarak bu sorunu çözebilirsiniz. küresel olarak görülebilir yapı.

Bazı durumlarda, özgün uygulama amacı, tek bir iş parçacığının durumunu sağlayan genel değişkenlerin birkaç yinelenen iş parçacığının çalışmasına izin verecek şekilde değiştirileceği şekilde değiştirilir. Bir örnek, durum için global değişkenleri kullanan tek bir kullanıcı için tasarlanmış basit bir uygulama olabilir ve daha sonra uzak uygulamaların sanal kullanıcı gibi davranmasına izin vermek için REST arabirimi eklemek için yönetimden bir istek gelir . Böylece artık tek değişkenlerin ve uzak uygulamalardaki sanal kullanıcıların her birinin kendi, benzersiz küresel değişkenler kümesine sahip olması için genel değişkenleri ve durum bilgilerini çoğaltmak zorunda kalıyorsunuz.

C ++ namespaceve C için structTekniği Kullanma

C ++ programlama dili için namespaceyönerge, ad çakışması olasılığını azaltmada çok yardımcıdır. namespaceile birlikte classve çeşitli erişim anahtar kelimeler ( private, protectedve public) sen kapsülü değişkenleri gereken araçların çoğunu sağlarlar. Ancak C programlama dili bu yönergeyi sağlamaz. Bu yığın akışı akışı, C'deki Ad Alanları, C için bazı teknikler sağlar.

Yararlı bir teknik, structküresel görünürlüğe sahip olarak tanımlanan ve bunun içinde structmaruz kalınan çeşitli küresel değişkenlere ve işlevlere işaret eden tek bir bellek yerleşik veri alanına sahip olmaktır. Global değişkenlerin gerçek tanımlarına staticanahtar kelime kullanılarak dosya kapsamı verilir . Ardından const, hangisinin salt okunur olduğunu belirtmek için anahtar kelimeyi kullanırsanız, derleyici salt okunur erişimi zorlamanıza yardımcı olabilir.

Tekniği kullanmak, structküresel olanı da kapsayabilir, böylece küresel olan bir paket veya bileşen haline gelir. Bu tür bir bileşene sahip olarak, küresel olanı ve küreselliği kullanan işlevselliği etkileyen değişiklikleri yönetmek daha kolay hale gelir.

Bununla birlikte namespaceveya structteknik, isim çatışmalarını yönetmeye yardımcı olabilirken, küresellerin kullanımının özellikle modern çok iş parçacıklı bir uygulamada ortaya koyduğu bileşenler arası kuplajın altında yatan problemler hala mevcuttur.


Bu eller aşağı en iyi exaplanation, orada her şeyi açıklıyor. Kudos!
johndoevodka

Dilinizde çok fazla sınıf bağlantısı kullanmanıza engel olacak bir kod kuralı olmalıdır.
Melbourne Developer

19

Evet, ancak global değişkenleri kullanan kodda çalışmayı bırakıp global değişkenleri kullanan kodu kullanan başka bir şey yazmaya başlayıncaya kadar global değişkenlerin maliyetine maruz kalmazsınız. Ama maliyet hala orada.

Diğer bir deyişle, uzun vadeli dolaylı bir maliyettir ve bu nedenle çoğu insan bunun kötü olmadığını düşünür.


19

Eğer bir Yüksek Mahkeme davası sırasında kodunuzun yoğun bir incelemeye girmesi mümkünse, global değişkenlerden kaçınmak istediğinizden emin olmak istersiniz.

Bu makaleye bakın: Buggy alkol ölçer kodu kaynak incelemesinin önemini yansıtıyor

Her iki çalışma tarafından tespit edilen kod stiliyle ilgili bazı sorunlar vardı. Hakemleri ilgilendiren stilistik konulardan biri, korunmasız küresel değişkenlerin yaygın kullanımıydı . Bu zayıf form olarak kabul edilir, çünkü program durumunun tutarsız hale gelmesi veya değerlerin yanlışlıkla değiştirilmesi veya üzerine yazılması riskini arttırır. Araştırmacılar ayrıca, ondalık hassasiyetin kod boyunca tutarlı bir şekilde sürdürülmemesiyle ilgili bazı endişeleri de dile getirdiler.

Dostum, bahse girerim bu geliştiriciler küresel değişkenler kullanmamalarını istiyorlar!


6
Bir süredir yaşadığım en iyi gülüş buydu. Kar için kapalı kaynak geliştirmenin kötü olmasının gerçek bir örneği ve küresel değişkenlere iyi bir örnek yanlış gitti!
Evil Spork

Burada kurulan küresel değişkenlerin küçümseme ile görülmesidir. Burada global değişkenlerin kodda gerçek bir sorun olduğunu gösteren hiçbir şey yoktur. SysTest, kodun "olağan yazılım tasarımı en iyi uygulamalarıyla tutarlı bir şekilde yazılmadığı" halde, yine de "güvenilir bir şekilde tutarlı test sonuçları üreteceğini" söyledi. Yani küresellerden hiçbir zarar belgelenmemiştir. Gördüğüm kadarıyla, "Eh, bu geliştiriciler ana akım dünyanın geri kalanıyla aynı kodlama dinini uygulamadılar."
LionKimbro

19

Global değişkenler sizin yaptığınız kadar kötü, daha az değil.

Tamamen kapsüllenmiş bir program oluşturuyorsanız, globalleri kullanabilirsiniz. Globalleri kullanmak bir "günah" ama programlama günahları büyük ölçüde felsefi.

L.in.oleum'u kontrol ederseniz , değişkenleri yalnızca global olan bir dil göreceksiniz. Bu ölçeklenemez çünkü kütüphanelerin hepsinin globalleri kullanmaktan başka seçeneği yoktur.

Bununla birlikte, eğer seçenekleriniz varsa ve programcı felsefesini görmezden gelebilirseniz, küreseller o kadar da kötü değildir.

Eğer doğru kullanırsanız, Gotos da değildir.

Büyük "kötü" sorun, onları yanlış kullanırsanız, insanlar çığlık atıyor, mars lander çöküyor ve dünya patladı .... ya da böyle bir şey.


17
Şaşkın bir öğrenciye küreselleri kullanma problemlerini küçümsemek iyi bir fikir IMO değildir.
GEOCHET

3
Tasarım Felsefesi nesnel değildir. Hiçbir şekilde. Çoğu programcı bir şeyi sevmediği için, birisinin asla bir şeye bakmaması gerektiği anlamına gelmez. Dünya sona ermeden küreselleri genel olarak kullanmak kolaydır. Bırakın onu yapsın, mücadele etsin (olacağını biliyordu) ve nasıl yapıldığını öğren.
user54650

7
Zengin haklı. Bu cevap, neyin kötü olduğu / neyin kötü olduğu (veya küresellerin nasıl güvenli bir şekilde kullanılabileceği) hakkında bir şey söylemiyor, sadece "hepsi kadar kötü değiller. Bu nedenle, sadece sorunları önemsiz gösteriyor.
jalf

4
Global değişkenlerin sadece "yaptığınız kadar kötü" olduğunu kabul etmiyorum. Özellikle bu çok geliştirici, birbirine bağlı dünyada çoğumuzun yaşadığı, çalıştığı ve programlandığı ana sorunlardan birinin küresel değişkenlere ELSE'e kodunuzu kötü yapma fırsatı vermesidir.
gariepy

@gariepy, konuşmanın statik hakkında olmasına rağmen: Tamam, bu yüzden ... ve uygulamamın sadece bir veya iki küresel değişkeni var, bu normalde kullanmadığımız Visual Studio, DEBUG ve TRACE ile geliyor: D
deadManN

17

Bu soruya başka bir soru ile cevap verirdim: Singelton kullanıyor musunuz / Singeltons kötü mü?

Çünkü (neredeyse tamamı) singelton kullanımı yüceltilmiş bir küresel değişkendir.


11
"Onları tek başına küresel olarak adlandırırsanız kötüdürler" diyerek akıllı bir yorum yayınlamak üzereydim, ama beni dövüyordunuz.
smo

Hala ne tekil LOL olduğunu anlamaya çalışıyorum.
GeoffreyF67

1
@Geoffrey: İşte bazı iyi SO açıklamaları - stackoverflow.com/questions/11831/… ve bazı iyi bağlantılar için: stackoverflow.com/questions/11831/…
Gavin Miller

10
Kayıt için, singleton, meşru görünmesini sağlamak için yüceltilmiş Tasarım Desenleri (tm) (lol) adına sahip global bir değişkendir. Aynı nedenlerle aynı derecede kötü.
R .. GitHub BUZA YARDIMCI DURDUR

@GavinMiller Simpleton ... ooops, singleton euphemism'i kullanmanın sorun olmadığını mı söylüyorsunuz?
Juan Mendes

14

Sorun kötü olduklarından daha az, tehlikeli olduklarından daha fazla . Kendi artıları ve eksileri var ve belirli bir görevi başarmanın en verimli veya tek yolu oldukları durumlar var. Ancak, bunları her zaman doğru şekilde kullanmak için adımlar atsanız bile yanlış kullanımları çok kolaydır.

Birkaç artı:

  • Herhangi bir işlevden erişilebilir.
  • Birden çok iş parçacığından erişilebilir.
  • Program bitene kadar kapsam dışı kalmayacak.

Birkaç eksileri:

  • Herhangi bir işlevden, parametre olarak açıkça sürüklenmeye ve / veya belgelenmeye gerek kalmadan erişilebilir.
  • İplik güvenli değildir.
  • Küresel ad alanını kirletir ve bunu önlemek için önlemler alınmadıkça potansiyel olarak ad çakışmalarına neden olur.

Unutmayın, listelediğim ilk iki artı ve ilk iki eksiler, sadece farklı ifadelerle aynı şeydir. Bunun nedeni, küresel bir değişkenin özelliklerinin gerçekten yararlı olabilmesidir, ancak onları faydalı kılan özellikler, tüm sorunlarının kaynağıdır.

Bazı sorunlara birkaç potansiyel çözüm:

  • Sorun için gerçekten en iyi ya da en etkili çözüm olup olmadığını düşünün. Varsa herhangi daha iyi çözümler, bunun yerine kullanın.
  • (İyi bir örnek olacağını benzersiz bir adla bir ad [C ++] veya tekil yapı [C, C ++] koyun Globalsya GlobalVars) ya gibi (küresel değişkenler için bir standart adlandırma kuralını kullanın global_[name]veya g_module_varNameStyle(yorumlarda underscore_d tarafından belirtildiği gibi )). Bu, hem kullanımlarını belgeleyecektir (ad alanını / yapı adını arayarak genel değişkenleri kullanan kodu bulabilirsiniz) ve genel ad alanı üzerindeki etkiyi en aza indirebilirsiniz.
  • Genel değişkenlere erişen herhangi bir işlev için, hangi değişkenleri okuduğunu ve hangi değişkenleri yazdığını açıkça belgeleyin. Bu sorun gidermeyi kolaylaştıracaktır.
  • Bunları kendi kaynak dosyalarına koyun externve ilişkili başlıkta bildirin, böylece kullanımları bunlara erişmesi gereken derleme birimleriyle sınırlandırılabilir. Kodunuz çok sayıda global değişkene dayanıyorsa, ancak her bir derleme biriminin yalnızca bir avuç dolusu erişime ihtiyacı varsa, bunları birden çok kaynak dosyaya ayırmayı düşünebilirsiniz, bu nedenle her dosyanın global değişkenlere erişimini sınırlamak daha kolaydır.
  • Kilitlemek ve kilidini açmak için bir mekanizma kurun ve / veya kodunuzu mümkün olduğunca az fonksiyonun küresel değişkenleri gerçekten değiştirmesi gerekecek şekilde tasarlayın . İş parçacığı yarışları yine de çok iş parçacıklı programlarda sorunlara neden olsa da, bunları okumak onları yazmaktan çok daha güvenlidir.
  • Temel olarak, onlara erişimi en aza indirin ve ad benzersizliğini en üst düzeye çıkarın. Ad çakışmalarından kaçınmak ve herhangi bir değişkeni potansiyel olarak değiştirebilecek kadar az işleve sahip olmak istiyorsunuz.

İyi ya da kötü olmaları onları nasıl kullandığınıza bağlıdır. Çoğunluk onları kötü kullanma eğilimindedir, bu nedenle onlara karşı genel savaşçılık. Düzgün kullanılırsa, büyük bir nimet olabilirler; kötü kullanılırsa, ancak, ve olabilir olacak size ısırmaya geri geldiğimde ve hiç beklemediğiniz nasıl.

Buna bakmanın iyi bir yolu, kendilerinin kötü olmamalarıdır, ancak kötü tasarımı etkinleştirir ve kötü tasarımın etkilerini katlanarak çoğaltabilirler.


Bunları kullanmak istemeseniz bile, bunları nasıl güvenli bir şekilde kullanacağınızı bilmediğinizden, bunları nasıl kullanacağınızı bilmek ve kullanmamayı seçmek daha iyidir. Kendinizi global değişkenlere dayanan önceden var olan kodu korumanız gereken bir durumda bulursanız, bunları nasıl doğru kullanacağınızı bilmiyorsanız zorluk yaşayabilirsiniz.


1
Pragmatizm için +1. Bir singleton genellikle örneği & refactor'u üyelere dönüştürmek için boilerplate ekler ve sonuçta ... farklı bir adla maskelenen global değişkenlerle sonuçlanırsınız. Globals Sin'sini sadece teknik bir teknikten kaçınmak dışında neden rahatsız oluyorsunuz? İsim alanları bir engel kadar güzel, ama basit bir g_module_varNameStyleşekilde okunaklı buluyorum . Açıkça söylemek gerekirse, kolayca kaçabilirsem globalleri kullanmıyorum - anahtar kelime kolayca , çünkü kaçınılması gerektiğine inanmayı bıraktığım - ya da daha doğrusu gizlenmiş - her ne pahasına olursa olsun, çok daha iyi zamanım var & kodu (şok!) çok daha düzenli
underscore_d

@underscore_d Genel olarak, küresel ve yerel değişkenleri daha kolay ayırt edebilmenin bir yolunu bulmak ve ayrıca bir değişkenin küresel mi yerel mi / yerel mi olduğu konusundaki karışıklığı önlemek amacıyla, kodunuzu ararken global değişkenleri bulmayı kolaylaştırmaktır. parametre / üye / vb. Sizinki gibi standart bir adlandırma kuralı tutarlı olduğu sürece de aynı şekilde çalışır. Cevabımı standart adlandırma kuralı fikriyle düzenlediğim için teşekkürler.
Justin Zaman - Eski Monica

1
"Herhangi bir işlev için ... açıkça hangi değişkenleri belgelemek" - bu geçişli bir ilişki olduğunu unutmayın. A işlevi B ve C işlevlerini çağırırsa, her ikisinin de yazdığı değişkenleri okur ve yazar (artı doğrudan vücudundaki değişkenleri)
Caleth

11

Birisinin başka bir iş parçacığında söylediği gibi (başka kelimelerle yazıyorum) "Bunu yapmanın sonuçlarını tam olarak anlayana kadar bunun gibi kurallar çiğnenmemelidir."

Global değişkenlerin gerekli olduğu veya en azından çok yararlı olduğu zamanlar vardır (Örneğin sistem tanımlı geri aramalarla çalışma). Öte yandan, size söylenen tüm nedenlerden dolayı da çok tehlikelidirler.

Programlamanın muhtemelen uzmanlara bırakılması gereken birçok yönü vardır. Bazen çok keskin bir bıçağa İHTİYACINIZ VAR. Ama hazır olana kadar birini kullanamazsın ...


1
Katılıyorum, sonuçları anlarsanız, kuralları çiğnemek sorun olmaz, ancak sık sık bunu yaparken kendinizi yakalarsanız, yanlış bir şey yapıyorsunuz
Juan Mendes

9

Genel değişkenler genellikle kötüdür, özellikle de diğer insanlar aynı kod üzerinde çalışıyorsa ve değişkenin başvurduğu tüm yerleri aramak için 20 dakika harcamak istemiyorsa. Ve değişkenleri değiştiren iş parçacıkları eklemek yepyeni bir baş ağrısı seviyesi getirir.

Tek bir çeviri biriminde kullanılan anonim bir ad alanındaki global sabitler, profesyonel uygulamalarda ve kitaplıklarda iyi ve her yerde bulunur. Ancak veriler değiştirilebilir ve / veya birden fazla TU arasında paylaşılması gerekiyorsa, onu kapsüllemek isteyebilirsiniz - eğer tasarım uğruna değilse, kodunuzda hata ayıklayan veya çalışan herkes uğruna.


9

Küresel değişkenleri kullanmak, bir halının altındaki kiri süpürmeye benzer. Hızlı bir düzeltme ve kısa vadede temizlemek için bir toz tava veya vakum almaktan çok daha kolay. Ancak, daha sonra halıyı hareket ettirirseniz, altında büyük bir sürpriz yaşayacaksınız.


tembel metafor bağlam yok! = cevap
underscore_d

1
@underscore_d: Katılmıyorum. Bu, (muhtemelen yaşı nedeniyle) etiketlenmemiş olsa bile bir tartışma sorusudur ve bu nedenle bu gibi cevaplar mükemmel şekilde geçerlidir ve OP sorusunu ele alan bir noktaya işaret eder.
gariepy

7

Bir programın yalnızca yerel olarak değiştirilmesi gereken yönlerini değiştirmenize izin veriyorsa, genel değişkenler kötüdür. OOP'de küreseller genellikle kapsülleme fikriyle çatışır.


7

Bence profesörünüz kötü bir alışkanlığı daha başlamadan durdurmaya çalışıyor.

Küresel değişkenlerin yeri vardır ve birçok insanın söylediği gibi bunları nerede ve ne zaman kullanacağını bilmek karmaşık olabilir. Bence profesörünüzün neden, nasıl, ne zaman ve nerede küresel değişkenlerin yasaklamaya karar verdiğinin cesur cesaretine girmek yerine. Kim bilir, gelecekte onları yasaklayabilir.


7

Kesinlikle hayır. Ama onları kötüye kullanmak ... bu kötü.

Akılsızca onları uğruna kaldırmak sadece ... akılsız. Avantajları ve dezavantajları bilmediğiniz sürece, açık bir şekilde yönlendirmek ve öğretildiği / öğrenildiği gibi yapmak en iyisidir, ancak küresel değişkenlerle örtülü olarak yanlış bir şey yoktur. Artıları ve eksileri anladığınızda kendi kararınızı daha iyi verin.


3
-1 Global değişkenlere karşı dikkatli olmanın sayısız nedeni var: benim için en büyük olanı gizli bağımlılıkların ve global test kodunu tahmin edilebilir herhangi bir şekilde zorlaştırıyor. Kodunuzu otomatik bir şekilde test etme yeteneğine değer vermedikçe, global değişkenlerin size acıdan başka bir şeye neden olmayacağını öneririm. Ayrıca, iyi yapılandırılmış bir programda her zaman alternatifler vardır.
jkp

1
Büyük bir aşırı genelleştirme, küresel durumun dikkatli kullanımı otomatik testi engellemiyor - aslında, iyi korunmuş nesnelerin veya tamamen maruz kalan statik verilerin dinamik olarak ayrılmış örnekleri olarak sarılmış olsun, neredeyse tüm uygulamalar küresel duruma sahip kavramsal olarak hiçbir fark yaratmaz, hala bağımlılıklar vardır - sadece nasıl kodlandıklarıyla ilgilidir.
jheriko

1
Kesinlikle. Temel olarak, "kolayca kırılabilir" oldukları için çok "kötü" değiller. Onları hiçbir şey kırmadan nasıl kullanacağınızı ve alternatif yerine ne zaman kullanacağınızı biliyorsanız , yardımcı olabilirler. Aksi halde ... çok değil.
Justin Time - Monica'yı

4

Küresel değişkenler küçük programlarda iyidir, ancak büyük programlarda aynı şekilde kullanılırsa korkunçtur.

Bu, öğrenirken bunları kullanma alışkanlığına kolayca sahip olabileceğiniz anlamına gelir. Profesörünüz sizi korumaya çalışıyor.

Daha deneyimli olduğunuzda, iyi olduklarını öğrenmek daha kolay olacaktır.


4

Hayır, hiç de fena değiller. Bu belirlemeyi yapmak için derleyici tarafından üretilen (makine) koduna bakmanız gerekir, bazen bir yerel kullanmak bir küreselden çok daha kötüdür. Ayrıca, yerel değişkene "statik" koymanın onu temelde küresel hale getirdiğini (ve gerçek bir globalin çözeceği diğer çirkin problemleri yarattığını) unutmayın. "yerel küreseller" özellikle kötüdür.

Globaller, bellek kullanımınız üzerinde de temiz kontrol sağlar, yerel halkla yapmak çok daha zor bir şeydir. Günümüzde sadece belleğin oldukça sınırlı olduğu gömülü ortamlarda önemlidir. Gömülü yazılımın diğer ortamlarla aynı olduğunu ve programlama kurallarının kartta aynı olduğunu varsaymadan önce bilmeniz gereken bir şey.

Öğretilen kuralları sorgulamanız iyi, çoğu size anlatılan nedenlerden değil. Bununla birlikte en önemli ders, bunun sonsuza dek sizinle birlikte taşınacak bir kural olmadığı, ancak bu sınıfı geçmek ve ilerlemek için onurlandırmak için gerekli bir kuraldır. Hayatta XYZ şirketi için maaş almaya devam etmek için sonunda onurlandırmanız gereken başka programlama kurallarına sahip olacağını göreceksiniz. Her iki durumda da kuralı tartışabilirsiniz, ancak bence bir işte okuldan çok daha iyi şansınız olacak. Siz birçok öğrenciden sadece birisiniz, koltuğunuz yakında değiştirilecek, profesörler alışkanlık kazanmayacak, bir işte bu ürünü sonuna kadar görmek zorunda olan küçük bir oyuncu takımından birisiniz ve bu ortamda geliştirilen kurallar ekip üyelerinin yanı sıra ürün ve şirketin faydası, herkes düşünüyorsa veya belirli bir ürün için kolejde öğrendiğiniz bir şeyi veya genel programlama hakkında bir kitabı ihlal etmek için iyi bir mühendislik sebebi varsa, fikrinizi ekibe satın ve tercih edilen yöntem değilse geçerli olarak yazın . Her şey gerçek dünyada adil bir oyundur.

Okulda veya kitaplarda size öğretilen tüm programlama kurallarına uyursanız, programlama kariyeriniz son derece sınırlı olacaktır. Muhtemelen hayatta kalabilir ve verimli bir kariyere sahip olabilirsiniz, ancak kullanabileceğiniz ortamların genişliği ve genişliği son derece sınırlı olacaktır. Kuralın nasıl ve neden orada olduğunu ve onu savunabileceğini biliyorsanız, bu iyi, eğer tek sebep "öğretmenim öyle dedi" ise, o kadar iyi değil.

Bunun gibi konuların genellikle işyerinde tartışıldığını ve derleyiciler ve işlemciler (ve diller) geliştikçe, bu tür kuralları geliştirdiklerini ve pozisyonunuzu savunmadan ve muhtemelen başka bir fikre sahip olmadığınız bir kişi tarafından bir ders verildiğini unutmayın. ileri git.

Bu arada, o zaman en yüksek sesle konuşan veya en büyük sopayı taşıyan her şeyi yapın (en yüksek sopayı veren ve en büyük sopayı taşıyan siz oluncaya kadar).


4
Bu, "hiç kimse IBM'i satın almak için kovulmadı" demenin başka bir yolu mu?
Gordon Potter

1
Global değişkenleri kullanan bazı uygulamalar için işi daha kolay hale getirebileceği iyi bir nokta. Genel olarak global değişkenlerin kullanılması, kaynak bölümleri arasındaki gizli bağlantı yollarıyla ilgili bir sorun kaynağıdır. Ancak, genel olarak başvurulan paylaşılan bir bellek alanına sahip olmak, aygıt arabirimleri veya belki de çeşitli türlerdeki sabitleri veya atlama tablosunu içeren bir global parametre tablosu gibi bir dizi uygulama için kullanılır.
Richard Chambers

4

Ben çok iş parçacığı daha zor veya imkansız kılan bu iş parçacığı boyunca yapılan noktaya karşı tartışmak istiyorum. Küresel değişkenler paylaşılan durumdur, ancak küresellere alternatifler (örneğin etrafta işaretçiler geçmek) durumu da paylaşabilir. Çoklu iş parçacığındaki sorun, bu durumun global bir değişkenle veya başka bir şeyle paylaşılıp paylaşılmadığı değil, paylaşılan durumun nasıl doğru şekilde kullanılacağıdır.

Çoğu zaman çoklu iş parçacığı oluştururken bir şey paylaşmanız gerekir. Örneğin, bir üretici-tüketici modelinde, iş birimlerini içeren iş parçacığı açısından güvenli bir kuyruk paylaşabilirsiniz. Ve bu veri yapısı iş parçacığı için güvenli olduğu için paylaşmanıza izin verilir. İş parçacığı güvenliği söz konusu olduğunda, bu kuyruğun küresel olup olmadığı tamamen önemsizdir.

Bu iş parçacığı boyunca, bir programı tek iş parçacığından çok iş parçacığına dönüştürmenin globalleri kullanmamak naif olduğunda daha kolay olacağını ima eden zımni umut. Evet, küreseller kendinizi ayağınızı vurmayı kolaylaştırır, ancak kendinizi vurmanın birçok yolu vardır.

Ben küreselleri savunmuyorum, diğer noktalar hala duruyor gibi, benim amacım sadece bir programda iş parçacığı sayısı değişken kapsamı ile ilgisi yoktur.


3

Evet, çünkü yetersiz programcıların bunları kullanmasına izin verirseniz (özellikle% 90'ı okuyun) 20+ dosyaya yayılan 600+ küresel değişken ve işlevlerin% 80'inin geçersiz olduğu, geri dönüşü olduğu ve çalıştığı 12.000 satırlık bir proje ile sonuçlanırsınız. tamamen küresel devlet üzerinde.

Tüm projeyi bilmediğiniz sürece, herhangi bir noktada neler olduğunu anlamak imkansız hale gelir.


2

Kullanımı Küresel değişkenler aslında gereksinimlerine bağlıdır. Avantajı, değerleri tekrar tekrar geçirme yükünü azaltmasıdır.

Ancak profesörünüz haklı çünkü güvenlik sorunlarını gündeme getiriyor, bu nedenle küresel değişkenlerin kullanımından mümkün olduğunca kaçınılmalıdır. Global değişkenler de bazen hata ayıklaması zor olan problemler yaratırlar .

Örneğin:-

Durumlar değişkenler değerler elde edildiğinde modifiye üzerine çalışma zamanı . O anda, kodun hangi bölümünün onu ve hangi koşullarda değiştirdiğini belirlemek zordur.


2

Konfigürasyon söz konusu olduğunda Global iyidir . Yapılandırmamızın / değişikliklerin tüm proje üzerinde küresel bir etkiye sahip olmasını istediğimizde .

Böylece bir konfigürasyonu değiştirebiliriz ve değişiklikler tüm projeye yönlendirilir . Ama küreselleri kullanmak için çok akıllı olmanız gerektiği konusunda uyarmalıyım.


1

Er ya da geç bu değişkenin nasıl ayarlandığını ya da erişildiğinde ne olacağını değiştirmelisiniz ya da sadece değiştirildiği yeri bulmanız gerekir.

Küresel değişkenlere sahip olmamak neredeyse her zaman daha iyidir. Sadece baraj alma ve ayarlama yöntemleri yazmak ve bir gün, hafta veya ay sonra onlara ihtiyacınız olduğunda bez olmak.


1

Genellikle dinamik olarak yüklenen kitaplıktaki işlevlere tek tek veya işlev işaretçileri gibi nadiren değiştirilen değerler için globaller kullanıyorum. Çok iş parçacıklı uygulamalarda mutable global'leri kullanmak, izlenmesi zor olan hataya yol açar, bu yüzden genel bir kural olarak bundan kaçınmaya çalışırım.

Bir argümanı geçmek yerine global kullanmak genellikle daha hızlıdır, ancak günümüzde sıklıkla yaptığınız çok iş parçacıklı bir uygulama yazıyorsanız, genellikle çok iyi çalışmaz (iş parçacığı statiklerini kullanabilirsiniz, ancak performans kazancı tartışmalıdır) .


1

Bir enterprize içindeki web uygulamalarında, optimizasyon nedeniyle oturum / pencere / iş parçacığı / kullanıcıya özgü verileri sunucuda tutmak ve bağlantının kararsız olduğu yerlerde iş kaybına karşı korumak için kullanılabilir. Belirtildiği gibi, yarış koşullarının ele alınması gerekir. Bu bilgi için bir sınıfın tek bir örneğini kullanıyoruz ve dikkatle yönetiliyor.


1

Günün sonunda, programınız veya uygulamanız hala çalışabilir, ancak düzenli olma ve neler olup bittiğini tam olarak anlama meselesi. Tüm işlevler arasında değişken bir değer paylaşırsanız, hangi işlevin değeri değiştirdiğini (işlev böyle yaparsa) izlemek zorlaşır ve hata ayıklamayı milyon kez daha zorlaştırır


0

Güvenlik daha azdır, eğer herhangi biri küresel olarak ilan edilmişse değişkenleri manipüle edebileceği anlamına gelir, bunun için açıklamak için banka programınızda global bir değişken olarak bakiyeniz varsa, kullanıcı fonksiyonu bunu manipüle edebilir ve banka memuru da manipüle edebilir Bu yüzden bir sorun var. sadece kullanıcıya salt okunur ve çekilme fonksiyonu verilmelidir, ancak bankanın katibi, kullanıcı masaya şahsen nakit verdiğinde bu tutarı ekleyebilir.


-1

Çok iş parçacıklı bir uygulamada, bir yarış koşulundan kaçınmak için global değişkenler yerine yerel değişkenleri kullanın.

Birden çok iş parçacığı, paylaşılan bir kaynağa eriştiğinde, en az bir iş parçacığının verilere yazma erişimi olduğunda bir yarış durumu oluşur. Daha sonra, programın sonucu tahmin edilemez ve farklı iş parçacıkları tarafından verilere erişim sırasına bağlıdır.

Bununla ilgili daha fazla bilgi için https://software.intel.com/tr-tr/articles/use-intel-parallel-inspector-to-find-race-conditions-in-openmp-based-multithreaded-code


Gelecek nesiller için: bu en iyi ihtimalle kısmen doğrudur. Bu yanıttaki "yerel değişkenler" , OP'nin başvurduğu daha yaygın kapsam-yerel değişkenlerden ziyade thread -local değişkenlerine karşılık gelir. Global değişkenleri güvenli olmayan bir şekilde değiştirmenin yan etkileri, eşzamanlı olmayan bir şekilde küresel durumu değiştirenlerden çok farklıdır.
Jules
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.