Statik değişkenler neden kötü olarak kabul edilir?


635

Kurumsal dünyada yeni olan bir Java programcısıyım. Son zamanlarda Groovy ve Java kullanarak bir uygulama geliştirdim . Yazdığım kod boyunca oldukça iyi sayıda statik kullanıldı. Üst düzey teknik partiden, kullanılan statik sayısını azaltmam istendi. Aynı şeyleri araştırdım ve birçok programcının statik değişkenleri kullanmaya oldukça karşı olduğunu düşünüyorum.

Statik değişkenlerin kullanımını daha uygun buluyorum. Ve onların da verimli olduklarını varsayıyorum (eğer yanılıyorsam lütfen beni düzeltin), çünkü bir sınıf içindeki bir işleve 10.000 çağrı yapmak zorunda kalsaydım, yöntemi statik yapmaktan ve Class.methodCall()bunun yerine basit bir şekilde kullanmaktan memnuniyet duyarım . hafızayı sınıfın 10.000 örneği ile karıştırmak, değil mi?

Dahası statik, kodun diğer kısımlarındaki bağımlılıkları azaltır. Mükemmel devlet sahipleri olarak hareket edebilirler. Buna ek olarak, statikin Smalltalk ve Scala gibi bazı dillerde yaygın olarak uygulandığını görüyorum . Peki bu statik baskısı programcılar arasında (özellikle Java dünyasında) neden yaygındır?

Not: Statikle ilgili varsayımlarım yanlışsa lütfen beni düzeltin.


43
Sadece söylemek gerekirse, Smalltalk veya Scala'da statik değişkenler veya yöntemler yoktur, çünkü statik yöntemler ve değişkenler OOP ilkelerine aykırıdır.
Maurício Linhares

87
Yaptığınız en az bir ifade oldukça meraklıdır: "statik, kodun diğer kısımlarındaki karşılıklı bağımlılıkları azaltır". Genel olarak bağımlılıkları sıkılaştırırlar. Çağrının yapıldığı kod, çağrılan koda çok sıkı bir şekilde bağlıdır. Doğrudan bağımlılık arasında soyutlama yok.
Arne Deutsch

11
İyi soru ... bir Programcıdan daha fazlası.
WernerCD

26
İkinci paragrafınız tamamen farklı bir konuyla, yani statik yöntemlerle ilgilidir .
Paul

8
Fonksiyonel programlama aynı zamanda küresel duruma da yatmaktadır. Eğer varsa hiç (ve gereken bir gün FP içine almak), küresel devlet nosyonunu hendek hazır olun.
yeni123456

Yanıtlar:


689

Statik değişkenler küresel durumu temsil eder. Bunun akıl yürütmesi zor ve test edilmesi zor: Eğer bir nesnenin yeni bir örneğini yaratırsam, testler içindeki yeni durumunu düşünebilirim. Statik değişkenler kullanan bir kod kullanırsam, herhangi bir durumda olabilir ve herhangi bir şey onu değiştirebilir.

Uzun bir süre devam edebilirdim, ama düşünülecek daha büyük konsept, bir şeyin kapsamı ne kadar sıkı olursa, akıl yürütmek o kadar kolay olur. Küçük şeyleri düşünmekte iyiyiz, ancak modülerlik yoksa bir milyon hat sisteminin durumu hakkında düşünmek zor. Bu, sadece statik değişkenler için değil, her türlü şey için geçerlidir.


57
Son zamanlarda, bu kod test edilebilir olsun veya olmasın, bir argüman gibi görünüyor. Oldukça kusurlu bir akıl yürütme. Argüman 'iyi tasarım' olmalı ve genellikle iyi tasarım test edilebilir. Ama bunun tersi değil: "Bunu test edemiyorum, çünkü kötü tasarım olmalı." Yine de beni yanlış anlamayın, genel olarak mesajınıza katılıyorum.
M Platvoet

144
@ M Platvoet: Eşit derecede geçerli iki tasarım arasında bir seçim yapıldığında, test edilebilir olanın daha üstün olduğunu söyleyebilirim. Test edilebilir olmak kesinlikle iyi tasarlanmış olmakla eşdeğer değildir, ancak nadiren test edilemeyen iyi tasarımlarla karşılaşıyorum ve bence test edilebilirliği iyi bir tasarıma genel amaçlı katkıda bulunan bir gösterge yapmakta sorun yaşamadığım için yeterince nadir olduklarını düşünüyorum .
Jon Skeet

9
@M Platvoet - Test edilebilirlik hem sürdürülebilirliği hem de güvenilirliği etkiler ve tasarım kalitesindeki bu önemli faktörleri göz önünde bulundururum. Elbette tek faktör değiller, ancak IMHO'nun herhangi bir kodun maliyeti, makine döngüleri, geliştirici döngüleri ve kullanıcı döngülerinin bir kombinasyonudur. Ahlaksızlık bu üç taneden ikisine çarpıyor.
Justin Morgan

5
@M Platvoet - Ayrıştırılabilirlik sınıfının yeniden kullanımı genellikle daha kolay olduğu için, test edilebilirlik tekrar kullanılabilirliği etkileme eğilimindedir.
TrueWill

13
M Platvoet - Buradaki ilk yorumunuza katılmıyorum. Bir şey test edilemezse, o zaman kötü tasarım olduğunu düşünüyorum; çünkü eğer test edemezsem, işe yaradığını bilmiyorum. Satış temsilcisi size "Bu modelin tasarımı test edilmesini engeller, bu yüzden gerçekten çalışıp çalışmadığını bilmiyorum" derse bir araba alır mıydınız? Test edilebilirlik yazılım için olduğu kadar otomobiller için de çok önemlidir, bu da yetkin bir tasarım dahil edilmesini gerektirir.
Dawood ibn Kareem

277

Çok nesne yönelimli değil: Statiklerin bazı insanlar tarafından "kötü" olarak kabul edilmesinin bir nedeni, nesne yönelimli paradigmaya aykırı olmalarıdır . Özellikle, verilerin nesnelerde kapsüllenmesi (genişletilebilecek, bilgi gizleme vb.) İlkesini ihlal eder. Statik, bunları nasıl tanımladığınız gibi, temelde kapsam gibi sorunlarla uğraşmaktan kaçınmak için bunları küresel bir değişken olarak kullanmaktır. Bununla birlikte, küresel değişkenler "iyi" nesne yönelimli kodun bir özelliği değil, prosedürel veya zorunlu programlama paradigmasının belirleyici özelliklerinden biridir. Bu, prosedür paradigmasının kötü olduğu anlamına gelmez, ancak amirinizin "iyi nesne yönelimli kod" yazmanızı beklediği izlenimini edinirsiniz ve gerçekten yazmak istiyorsunuz "

Java'da her zaman hemen belirgin olmayan statikleri kullanmaya başladığınızda birçok gotchya vardır. Örneğin, programınızın aynı VM'de çalışan iki kopyası varsa, statik değişkenin değerini düşürecek ve birbirlerinin durumu ile karışacaklar mı? Veya sınıfı genişlettiğinizde, statik üyeyi geçersiz kılabilir misiniz? Çok sayıda statik bilginiz olduğundan ve bu bellek gerekli diğer örnek nesneleri için geri alınamayacağından VM'nizin belleği tükeniyor mu?

Nesne Ömrü: Ek olarak, statik programın tüm çalışma zamanı ile eşleşen bir ömre sahiptir. Bu, sınıfınızı kullandıktan sonra bile, tüm bu statik değişkenlerden gelen bellek çöp toplanamayacağı anlamına gelir. Örneğin, bunun yerine, değişkenlerinizi statik olmayan bir hale getirdiyseniz ve main () işlevinizde sınıfınızın tek bir örneğini oluşturduysanız ve daha sonra bu 10.000 çağrı yapıldıktan sonra sınıfınızdan belirli bir işlevi 10.000 kez yürütmesini istediyseniz ve tek bir örneğe olan referanslarınızı silerseniz, tüm statik değişkenleriniz çöp toplanabilir ve yeniden kullanılabilir.

Belirli bir yeniden kullanımı önler: Ayrıca, bir arabirimi uygulamak için statik yöntemler kullanılamaz, bu nedenle statik yöntemler belirli nesne yönelimli özelliklerin kullanılabilir olmasını engelleyebilir.

Diğer seçenekler: Verimlilik birincil kaygınızsa, hız sorununu çözmenin, yalnızca çağrmanın avantajının genellikle yaratımdan daha hızlı olduğunu düşünmekten daha iyi başka yollar olabilir. Geçici veya uçucu değiştiricilerin herhangi bir yerde gerekli olup olmadığını düşünün. Satır içi olabilme yeteneğini korumak için, bir yöntem statik yerine son olarak işaretlenebilir. Yöntem parametreleri ve diğer değişkenler, bu değişkenleri neyin değiştirebileceğine dair varsayımlara dayanarak belirli derleyici optimizasyonlarına izin vermek için son olarak işaretlenebilir. Bir örnek nesnesi, her seferinde yeni bir örnek oluşturmak yerine birden çok kez yeniden kullanılabilir. Genel olarak uygulama için açılması gereken compliler optimizasyon anahtarları olabilir. Belki de tasarım, 10.000 çalışmanın çok iş parçacıklı olabileceği ve çok işlemcili çekirdeklerden yararlanabileceği şekilde ayarlanmalıdır. Taşınabilirlik değilse '

Herhangi bir nedenle bir nesnenin birden fazla kopyasını istemiyorsanız, tekli tasarım deseni, iplik güvenliği (singleton'unuzun iyi kodlandığını varsayarak), tembel başlatmaya izin veren, nesnenin kullanıldığında düzgün bir şekilde başlatıldığını garanti eden, alt sınıflandırma, kodunuzu test etme ve yeniden düzenleme avantajları gibi statik nesnelere göre avantajları vardır, bahsetmemek gerekirse, bir noktada bir nesnenin yalnızca bir örneğini istemeye ilişkin fikrinizi değiştirirseniz, yinelenen örnekleri önlemek için kodu kaldırmak, tüm değişken değişkenlerini kullanmak için tüm statik değişken kodunuzu yeniden düzenlemekten daha kolaydır. Bunu daha önce yapmak zorunda kaldım, eğlenceli değil ve çok daha fazla sınıf düzenlemek zorunda kalıyorsunuz, bu da yeni hatalar alma riskinizi artırıyor ... şeyleri ilk kez "doğru" ayarlamak için çok daha iyi, dezavantajları var gibi görünse bile. Benim için, Eğer yolda karar verirseniz gereken yeniden çalışma, bir şeyin birden fazla kopyasına ihtiyaç duyduğunuzda, statiki mümkün olduğunca seyrek kullanmak için en zorlayıcı nedenlerden biridir. Ve böylece, statiklerin bağımlılıkları azalttığı ifadesine de katılmıyorum, bence "nasıl yapılacağını bilen bir nesne yerine doğrudan erişilebilen çok sayıda statik varsa daha fazla kodla sonuçlanacaksınız. bir şey "kendi üzerine.


11
Cevabınızı beğendim, sanırım eşzamanlılık ve kapsam gibi bazı kırmızı ringa balığı yerine statiki düşünmek için doğru deneklere odaklanıyor. Ve singleton için +1, daha iyi bir soru gerçekten tek değişkenler vs statik değişkenler / yöntemler kullanmak olabilir ...
studgeek

2
Singletonun kendisi iş parçacığı açısından güvenli olsa da (örneğin synchronizedyöntemleri kullanarak ), arama kodunun singleton durumuna göre yarış koşullarından arınmış olduğu anlamına gelmez.
André Caron

8
Ayrıca, statikler OOP paradigmasına karşı değildir. Birçok OOP fanatiği, sınıfın bir nesne olduğunu ve statik yöntemin, sınıf nesnesinin örnekleri yerine bir yöntemi olduğunu söyleyecektir. Bu fenomen Java'da daha az bulunur. Python gibi diğer diller, sınıfları değişken olarak kullanmanıza izin verir ve statik yöntemlere o nesnenin yöntemleri olarak erişebilirsiniz.
André Caron

4
Üçüncü paragrafın son satırı, yanılmıyorsam tüm statik olmayan değişkenlerinizi okumalıdır .
Steve

1
Object Lifetime, @jessica'nın bahsettiği çok önemli bir noktadır.
Abhidemon

93

Kötülük öznel bir terimdir.

Statiği yaratılış ve yıkım açısından kontrol etmezsiniz. Yükleme ve boşaltma programlarının en iyisinde yaşıyorlar.

Statik bir alanda yaşadığından, bunları kullanmak isteyen tüm iş parçacıkları yönetmeniz gereken erişim denetiminden geçmelidir. Bu, programların daha fazla bağlı olduğu ve bu değişikliğin öngörülmesi ve yönetilmesinin daha zor olduğu anlamına gelir (J Skeet'in dediği gibi). Bu, değişiklik etkisini izole etme sorunlarına yol açar ve böylece testin nasıl yönetildiğini etkiler.

Bunlar onlarla ilgili iki ana konu.


59

Hayır. Küresel devletler kendi başına kötü değildir. Ancak kodunuzu doğru kullanıp kullanmadığınızı görmek için kodunuzu görmeliyiz. Bir acemi küresel devletleri kötüye kullanmak oldukça mümkündür; her dil özelliğini kötüye kullanacağı gibi.

Küresel devletler mutlak bir zorunluluktur. Küresel devletlerden kaçınamayız. Küresel devletler hakkında akıl yürütmeden kaçınamayız. - Uygulama semantiğimizi anlamaya özen gösterirsek.

Bunun için küresel devletlerden kurtulmaya çalışan insanlar, kaçınılmaz olarak çok daha karmaşık bir sistemle sonuçlanır - ve küresel devletler hala, birçok dolaylı katman altında zekice / aptalca gizlenmiş; ve tüm indirimleri açtıktan sonra hala küresel devletler hakkında akıl yürütmeliyiz.

Küresel devletleri xml olarak cömertçe ilan eden ve bir şekilde üstün olduğunu düşünen Bahar insanları gibi.

@Jon Skeet if I create a new instance of an objectartık aklınızda iki şey var - nesnenin içindeki durum ve nesneyi barındıran ortamın durumu.


10
"Aklıma gelen iki şey var". Testimi yalnızca nesne durumuna bağlı yaparsam değil. Hangi daha kolay, daha az küresel devlet var.
DJClayworth

2
Bağımlılık enjeksiyonunun küresel durum veya küresel görünürlükle bir ilgisi yoktur - kabın kendisi bile küresel değildir. "Normal" kodla karşılaştırıldığında, kapsayıcı tarafından yönetilen bir nesnenin görebileceği tek ekstra şey, kabın kendisidir. Aslında DI, Singleton Paterninden kaçınmak için çok yaygın olarak kullanılır.
Floegipoky

31

Statik değişkenlerle ilgili 2 ana sorun vardır:

  • İş Parçacığı Güvenliği - statik kaynaklar tanım gereği iş parçacığı için güvenli değildir
  • Kod Etkisizliği - Statik değişkenlerin ne zaman başlatıldığını ve başka bir statik değişkenten önce başlatılıp başlatılmayacağını bilmiyorsunuz

Sanırım Jon Skeet, yayınladığınız aynı yorumdan bahsediyordu.
RG-3

13
İş Parçacığı Güvenlik noktası alamadım, ben bunu sürece sürece hiçbir şey iş parçacığı güvenli olduğunu düşünüyorum. Bu hiç statik şeylerle ilgili görünmüyor, bir şey eksikse lütfen beni düzeltin.
Zmaster

1
@Zmaster - İş parçacığı güvenliğinin statik değişkenlere özel bir sorun olmadığı doğru olsa da, tanımları gereği farklı bağlamlardan çağrıldıkları için onlar için daha fazla
budandırlar

2
@sternr Ne demek istediğini anlıyorum, eğer "farklı bağlamlar" mutlaka "farklı başlıklar" a eşit değilse olay. Ancak, iplik güvenliğinin genellikle statik kaynaklarla dikkate alınması gerektiği doğrudur. Cümleyi açıklığa kavuşturmalısınız.
Zmaster

Örneğin, statik kaynakların geçerli iş parçacığı güvenli kullanımları vardır. özel statik son Logger LOG = Logger.getLogger (Foo.class); özel statik son AtomicInteger x = yeni AtomicInteger (0); Anladığım kadarıyla, bunun gibi kaynakların statik atamaları sınıf yükleyicisi tarafından iş parçacığı için güvence altındadır. Logger örneği, işaretçiyi ona atadığınız yerden bağımsız olarak iş parçacığı için güvenli değildir veya değildir. Statiği devlette tutmak muhtemelen iyi bir fikir değildir, ancak iş parçacığının güvenli olmaması için hiçbir neden yoktur.
teknopaul

29

'Statik' anahtar kelimeyi 'final' anahtar kelimesi olmadan kullanıyorsanız, bu tasarımınızı dikkatlice değerlendirmek için bir işaret olmalıdır. Değişken bir statik nihai nesne de aynı derecede tehlikeli olabileceğinden, bir 'final' varlığı bile serbest geçiş değildir.

Bir 'final' olmadan 'statik' gördüğüm zamanın yaklaşık% 85'ini tahmin ediyorum, YANLIŞ. Genellikle, bu sorunları maskelemek veya gizlemek için garip çözümler bulurum.

Lütfen statik değişkenler oluşturmayın. Özellikle Koleksiyonlar. Genel olarak Koleksiyonlar, içerdikleri nesne başlatıldığında başlatılmalı ve içerdikleri nesne unutulduğunda sıfırlanacak veya unutulacak şekilde tasarlanmalıdır.

Statik kullanmak, mühendislerin günlerce acı çekmesine neden olacak çok ince hatalar oluşturabilir. Biliyorum, çünkü bu böcekleri hem yarattım hem de avladım.

Daha fazla ayrıntı istiyorsanız, lütfen okumaya devam edin…

Neden Statik Kullanılmıyor?

Statik, test yazma ve yürütme ve hemen belli olmayan ince hatalar dahil olmak üzere birçok sorun var.

Statik nesnelere dayanan kod kolayca birim testinden geçirilemez ve statikler kolayca alay edilemez (genellikle).

Statik kullanırsanız, daha yüksek seviyedeki bileşenleri test etmek için sınıfın uygulanmasını değiştirmek mümkün değildir. Örneğin, veritabanından yüklediği Müşteri nesnelerini döndüren statik bir CustomerDAO düşünün. Şimdi, bazı Customer nesnelerine erişmesi gereken bir sınıf CustomerFilter var. CustomerDAO statik ise, önce veritabanımı başlatmadan ve faydalı bilgileri doldurmadan CustomerFilter için bir test yazamıyorum.

Ve veritabanı nüfusu ve başlatma uzun zaman alıyor. Deneyimlerime göre, DB başlatma çerçeveniz zamanla değişecek, yani veriler değişecek ve testler bozulabilir. IE, Müşteri 1'in bir VIP olduğunu hayal edin, ancak DB başlatma çerçevesi değişti ve şimdi Müşteri 1 artık VIP değil, ancak testiniz Müşteri 1'i yüklemek için kodlanmıştı…

Daha iyi bir yaklaşım, bir CustomerDAO'yu başlatmak ve inşa edildiğinde MüşteriFiltresine aktarmaktır. (Daha da iyi bir yaklaşım, Spring veya başka bir Inversion of Control çerçevesini kullanmak olacaktır.

Bunu yaptıktan sonra, CustomerFilterTest'inizdeki alternatif bir DAO'yu hızlı bir şekilde alay edebilir veya saplayabilirsiniz, böylece test üzerinde daha fazla kontrole sahip olursunuz.

Statik DAO olmadan, test daha hızlı (db başlatma yok) ve daha güvenilir olacaktır (çünkü db başlatma kodu değiştiğinde başarısız olmaz). Örneğin, bu durumda, test söz konusu olduğunda, Müşteri 1'in VIP olmasını ve daima VIP olmasını sağlamak.

Testleri Yürütme

Statikler, birim test paketlerini birlikte çalıştırırken gerçek bir soruna neden olur (örneğin, Sürekli Entegrasyon sunucunuzla). Bir testten diğerine açık kalan ağ soketi nesnelerinin statik bir haritasını düşünün. İlk test 8080 numaralı bağlantı noktasında bir Soket açabilir, ancak test yırtıldığında Haritayı temizlemeyi unuttunuz. Şimdi ikinci bir test başlatıldığında, bağlantı noktası hala meşgul olduğundan 8080 bağlantı noktası için yeni bir Soket oluşturmaya çalıştığında çökmesi muhtemeldir. Ayrıca statik Koleksiyonunuzdaki Soket referanslarının kaldırılmadığını ve (WeakHashMap hariç) hiçbir zaman çöp toplanmaya uygun olmadığını ve bellek sızıntısına neden olmadığını hayal edin.

Bu aşırı genelleştirilmiş bir örnektir, ancak büyük sistemlerde bu sorun TÜM ZAMANINDA ortaya çıkar. İnsanlar, aynı JVM'de yazılımlarını tekrar tekrar başlatan ve durduran birim testlerini düşünmezler, ancak yazılım tasarımınızın iyi bir testidir ve yüksek kullanılabilirliğe yönelik istekleriniz varsa, bilmeniz gereken bir şeydir.

Bu sorunlar genellikle, örneğin DB erişiminiz, önbelleğe alma, mesajlaşma ve günlük katmanlarınız gibi çerçeve nesneleriyle ortaya çıkar. Java EE veya en iyi cins çerçeveler kullanıyorsanız, muhtemelen sizin için bunların çoğunu yönetirler, ancak benim gibi eski bir sistemle uğraşıyorsanız, bu katmanlara erişmek için birçok özel çerçeveniz olabilir.

Bu çerçeve bileşenlerine uygulanan sistem yapılandırması birim sınamaları arasında değişirse ve birim sınama çerçevesi bileşenleri yırtıp yeniden oluşturmazsa, bu değişiklikler etkili olmaz ve bir sınama bu değişikliklere dayandığında başarısız olur .

Çerçeve dışı bileşenler bile bu soruna tabidir. OpenOrders adlı statik bir harita düşünün. Birkaç açık sipariş oluşturan bir test yazıyorsunuz ve hepsinin doğru durumda olup olmadığını kontrol ediyorsunuz, sonra test sona eriyor. Başka bir geliştirici, ihtiyaç duyduğu siparişleri OpenOrders haritasına yerleştiren ikinci bir test yazıyor, ardından sipariş sayısının doğru olduğunu iddia ediyor. Tek tek çalışın, bu testlerin her ikisi de geçer, ancak bir pakette birlikte çalıştırıldığında başarısız olurlar.

Daha da kötüsü, başarısızlık testlerin yapıldığı sıraya bağlı olabilir.

Bu durumda, statikten kaçınarak daha iyi test güvenilirliği sağlamak için test örnekleri arasında veriyi sürdürme riskinden kaçınırsınız.

Hafif Böcekler

Yüksek kullanılabilirlikli bir ortamda çalışıyorsanız veya iş parçacıklarının başlatılabileceği ve durdurulabileceği herhangi bir yerde çalışıyorsanız, yukarıda kod test paketlerinde belirtilen endişe kodunuz üretim sırasında da geçerli olabilir.

Verileri saklamak için statik bir nesne kullanmak yerine, iş parçacıklarıyla uğraşırken, iş parçacığının başlangıç ​​aşamasında başlatılan bir nesneyi kullanmak daha iyidir. Bu şekilde, iş parçacığı her başlatıldığında, nesnenin yeni bir örneği (potansiyel olarak yeni bir yapılandırmayla) oluşturulur ve iş parçacığının bir örneğinden sonraki örneğe kadar olan verilerden kaçınırsınız.

Bir iş parçacığı öldüğünde, statik bir nesne sıfırlanmaz veya çöp toplanmaz. “EmailCustomers” adında bir iş parçacığına sahip olduğunuzu ve başladığında statik bir String koleksiyonunu bir e-posta adresleri listesiyle doldurduğunu, ardından her bir adresi e-postayla göndermeye başladığını düşünün. İş parçacığının bir şekilde kesildiğini veya iptal edildiğini varsayalım, bu nedenle yüksek kullanılabilirlik çerçeveniz iş parçacığını yeniden başlatır. Sonra iş parçacığı başladığında, müşteri listesini yeniden yükler. Ancak koleksiyon statik olduğundan, önceki koleksiyondaki e-posta adresleri listesini tutabilir. Artık bazı müşteriler yinelenen e-postalar alabilir.

Bir Kenara: Statik Final

Teknik uygulama farklılıkları olmasına rağmen, “statik final” kullanımı etkili bir şekilde C # tanımının Java eşdeğeridir. AC / C ++ #define, derlemeden önce ön işlemci tarafından koddan çıkarılır. Bir Java "statik finali" yığının üzerinde bulunan bellekle sonuçlanır. Bu şekilde, C ++ 'daki bir "statik const" değişkenine bir #define kıyasla daha benzerdir.

özet

Umarım bu, statikin sorunlu olmasının birkaç temel nedenini açıklamaya yardımcı olur. Java EE veya Spring gibi modern bir Java çerçevesi kullanıyorsanız, bu durumların çoğuyla karşılaşmayabilirsiniz, ancak büyük bir eski kod gövdesiyle çalışıyorsanız, bunlar daha sık olabilir.


15

Kimse * bundan bahsetmediği için eşzamanlılık. Statik değişkene okuma ve yazma için birden fazla iş parçacığınız varsa statik değişkenler sizi şaşırtabilir. Bu, web uygulamalarında (ör. ASP.NET) yaygındır ve bazı oldukça sinir bozucu hatalara neden olabilir. Örneğin, bir sayfa tarafından güncellenen statik bir değişkeniniz varsa ve sayfa "neredeyse aynı anda" iki kişi tarafından istenirse, bir kullanıcı diğer kullanıcı tarafından beklenen sonucu elde edebilir veya daha da kötüsü olabilir.

statik, kodun diğer kısımlarındaki bağımlılıkları azaltır. Mükemmel devlet sahipleri olarak hareket edebilirler

Umarım kilit kullanmaya ve çekişme ile uğraşmaya hazırsınızdır.

* Aslında, Preet Sangha bundan bahsetti.


5
Örnek değişkenlerin statik değerlere göre iş parçacığı güvenliği avantajları yoktur, hepsi korunmasız değişkenlerdir. Bunun yerine, bu değişkenlere erişen kodu nasıl koruduğunuza inersiniz.
studgeek

2
Bu iddiayı tam olarak iddia etmedim, ama tartışma uğruna: ayrılık bir koruma şeklidir. İş parçacığı durumları ayrılır; küresel devlet değildir . Bir örnek değişkeni, iş parçacıkları arasında açıkça paylaşılmadığı sürece korumaya gerek duymaz ; statik bir değişken her zaman işlemdeki tüm evreler tarafından paylaşılır.
Justin M. Keyes

Ben iplik statik değişkenler birinci sınıf bir kavram daha isterdim, çünkü bu bilgiler her sarma katmanından geçmek zorunda kalmadan güvenli bir şekilde sarılmış bir altyordam çağrı için kullanılabilir hale getirmek için çok yararlı olabilir. Örneğin, bir nesnenin iş parçacığının geçerli grafik bağlamına dönüştürmek için yöntemleri varsa ve geçerli grafik bağlamını kaydetmek / geri yüklemek için yöntemler varsa, bunları kullanmak, grafik bağlamını her yöntem çağrısından geçirmek zorunda kalmadan genellikle daha temiz olabilir.
supercat

15

Java'da Statik yöntemleri kullanmanın birkaç temel Avantaj ve Dezavantajını özetleme:

Avantajları:

  1. Global olarak erişilebilir, yani herhangi bir nesne örneğine bağlı değildir.
  2. JVM başına bir örnek.
  3. Sınıf adı kullanılarak erişilebilir (Nesne gerektirmez).
  4. Tüm örneklere uygulanabilen tek bir değer içerir.
  5. JVM başlangıcında yükleyin ve JVM kapatıldığında ölür.
  6. Nesnenin durumunu değiştirmezler.

Dezavantajları:

  1. Statik üyeler kullanımda olsun ya da olmasın her zaman hafızanın bir parçasıdır.
  2. Statik değişken oluşturmayı ve yok etmeyi kontrol edemezsiniz. Yararlı olarak program yüklenirken yaratılmış ve program kaldırıldığında (veya JVM kapatıldığında) yok edilmiştir.
  3. Senkronizasyonu kullanarak statik iş parçacığını güvenli hale getirebilirsiniz, ancak bazı ekstra çabalara ihtiyacınız vardır.
  4. Bir iş parçacığı, diğer iş parçacıklarının işlevselliğini bozabilecek statik bir değişkenin değerini değiştirirse.
  5. Kullanmadan önce “statik” bilmeniz gerekir.
  6. Statik yöntemleri geçersiz kılamazsınız.
  7. Serileştirme onlarla iyi çalışmıyor.
  8. Çalışma zamanı polimorfizmine katılmazlar.
  9. Çok sayıda statik değişken / yöntem kullanılıyorsa, bir bellek sorunu vardır (bir dereceye kadar sanırım çok fazla değil). Çünkü program bitene kadar Çöp Toplanmayacaklar.
  10. Statik yöntemlerin de test edilmesi zordur.

6, 7, 8 ve 10 dezavantajları kullanılan dillerin / çerçevelerin dezavantajlarıdır, genel olarak statik değişkenlerin dezavantajları değildir. Dezavantajlar 1, 4 ve 5, bazı çerçeveler tarafından sağlanan bazı tekli modeller gibi diğer çözümler için de mevcuttur. (
Cevaba

13

bir sınıf içindeki bir işleve 10.000 çağrı yapmak zorunda kalsaydım, yöntemi statik yapmaktan ve sınıfın 10.000 örneğiyle belleği karıştırmak yerine doğrudan bir class.methodCall () kullanmaktan memnuniyet duyarım, değil mi?

Verileri bir durumdaki bir nesneye kapsülleme ihtiyacını, bazı verilerdeki bir fonksiyonun sonucunu basitçe hesaplama ihtiyacını dengelemek zorundasınız.

Dahası statik, kodun diğer kısımlarındaki bağımlılıkları azaltır.

Kapsülleme de öyle. Büyük uygulamalarda, statikler spagetti kodu üretme eğilimindedir ve yeniden düzenleme veya teste kolayca izin vermez.

Diğer cevaplar da aşırı statik kullanımına karşı iyi nedenler sağlar.


13

Statik değişkenler genel olarak kötü kabul edilir çünkü küresel durumu temsil ederler ve bu nedenle akıl yürütmeleri çok daha zordur. Özellikle, nesne yönelimli programlama varsayımlarını kırıyorlar. Nesne yönelimli programlamada, her nesnenin örnek (statik olmayan) değişkenlerle temsil edilen kendi durumu vardır. Statik değişkenler, birim testi için çok daha zor olabilen durumlar arasındaki durumu temsil eder. Bunun nedeni, statik değişkenlerdeki değişiklikleri tek bir testle izole etmenin daha zor olmasıdır.

Bununla birlikte, düzenli statik değişkenler (genellikle kötü olarak kabul edilir) ve nihai statik değişkenler (AKA sabitleri; çok kötü değil) arasında bir ayrım yapmak önemlidir.


4
"Statik değişkenler sınıflar arasındaki durumu temsil eder" ... Sanırım "statik değişkenler örnekler arasındaki durumu temsil ediyor" mu? +1 "son statik AKA sabitleri, o kadar da kötü değil". Değer değiştirilemediğinden, bir anda ona bağlı olan herhangi bir şey davranışını daha sonra dolaylı olarak değiştiremez - değer aynıdır.
Jared Updike

"Statik değişkenler, durumlar arasındaki durumu temsil eder", bunu belirtmenin çok daha iyi bir yoludur. Cevabımı düzenledim.
Jack Edmonds

9

Bence performansla ilgili neredeyse hiç değil, tasarımla ilgili. Statik değişkenlerin kullanımından dolayı statik yöntemlerin yanlış kullanıldığını düşünmüyorum (ama aslında yöntem çağrıları hakkında konuşuyorsunuz).

Basitçe mantığın nasıl izole edileceği ve ona iyi bir yer verileceği ile ilgilidir. Bazen bu java.lang.Mathiyi bir örnek olan statik yöntemleri kullanarak haklı çıkar . Sınıflarınızın çoğunu adlandırdığınızda XxxUtilveya Xxxhelpertasarımınızı yeniden düşünmeniz gerektiğini düşünüyorum .


3
Saf yan etkisi olmayan statik yöntemler mükemmel derecede IMO'dur. Fakat küresel değişebilir devlet nadiren öyle ve OP'yi küresel devlet hakkında konuşmak olarak yorumluyorum.
CodesInChaos

1
@CodeInChaos tamamen katılıyorum. Ben OP statik yöntemler ve vars arasındaki fark tamamen açık değil buluyorum.
M Platvoet

8

Yanıtlarda verilen bazı noktaları özetledim. Yanlış bir şey bulursanız, lütfen düzeltmekten çekinmeyin.

Ölçeklendirme: JVM başına tam olarak bir statik değişken örneğimiz vardır. Bir kütüphane yönetim sistemi geliştirdiğimizi ve kitabın başına yalnızca bir tane olduğu için kitabın adını statik bir değişken koymaya karar verdiğimizi varsayalım. Ancak sistem büyürse ve birden fazla JVM kullanıyorsanız, hangi kitabı ele aldığımızı anlamanın bir yolu yok mu?

İş Parçacığı Güvenliği: Çok iş parçacıklı bir ortamda kullanıldığında hem örnek değişkeninin hem de statik değişkenin kontrol edilmesi gerekir. Ancak, bir örnek değişkeni olması durumunda, iş parçacıkları arasında açıkça paylaşılmadığı sürece korumaya ihtiyaç duymaz, ancak statik bir değişken olması durumunda, işlemdeki tüm iş parçacıkları tarafından her zaman paylaşılır.

Test: Test edilebilir tasarım iyi tasarıma eşit olmasa da, test edilemeyen iyi bir tasarımı nadiren gözlemleyeceğiz. Statik değişkenler küresel durumu temsil ettiğinden ve bunları test etmek çok zorlaşır.

Durum hakkında akıl yürütme: Bir sınıfın yeni bir örneğini oluşturursam, bu örneğin durumu hakkında akıl yürütebiliriz, ancak statik değişkenleri varsa, herhangi bir durumda olabilir. Neden? Statik değişken, örnekler arasında paylaşıldıkça statik değişkenin farklı bir örnek tarafından değiştirilmiş olması mümkündür.

Serileştirme: Serileştirme de onlarla iyi çalışmaz.

Yaratılış ve imha: Statik değişkenlerin yaratılması ve imhası kontrol edilemez. Genellikle program yükleme ve boşaltma zamanında oluşturulur ve imha edilirler. Bu, bellek yönetimi için kötü oldukları ve başlangıçta başlatma süresini topladıkları anlamına gelir.

Ama ya gerçekten onlara ihtiyacımız olursa?

Ancak bazen onlara gerçek bir ihtiyaç duyabiliriz. Uygulamada paylaşılan birçok statik değişkene gerçekten ihtiyaç duyarsak, bir seçenek, tüm bu değişkenlere sahip olan Singleton Tasarım desenini kullanmaktır. Veya bu statik değişkene sahip olan ve etrafından geçirilebilen bir nesne oluşturabiliriz.

Ayrıca statik değişken son olarak işaretlenirse, bir sabit olur ve bir kez atanan değer değiştirilemez. Bu, değişebilirliği nedeniyle karşılaştığımız tüm sorunlardan bizi kurtaracağı anlamına geliyor.


7

Bana statik değişkenler hakkında soru sorduğunuz anlaşılıyor, ancak örneklerinizdeki statik yöntemleri de işaret ediyorsunuz.

Statik değişkenler kötü değildir - çoğu durumda nihai değiştirici ile birlikte sabitler gibi küresel değişkenler olarak benimsenirler, ancak söylediği gibi onları aşırı kullanmayın.

Statik yöntemler, diğer yöntem. Bunları kullanmak genellikle kötü bir uygulama değildir, ancak büyük endişe, testi engelleyebilmeleridir .

Bir çok statik kullanan ve doğru şekilde yapan harika java projesine örnek olarak lütfen Play'e bakın! çerçeve . SO hakkında da tartışma var.

Statik değişkenlerle birleştirilen statik değişkenler / yöntemler, java gibi bildirici programlamayı kolaylaştıran kitaplıklarda da yaygın olarak kullanılmaktadır: bunu kolaylaştırır veya Hamcrest . Çok fazla statik değişken ve yöntem olmadan mümkün olmazdı.

Statik değişkenler (ve yöntemler) iyidir, ancak bunları akıllıca kullanın!


6

Statik değişkenler en önemlisi veri güvenliği ile ilgili sorun yaratır (herhangi bir zamanda değişebilir, herkes değişebilir, nesne olmadan doğrudan erişim, vb.)

Daha fazla bilgi almak için okumaya bu teşekkür ederiz.


6

Statik değişken kullandığınız çoğu durumda, gerçekten tekli kalıbı kullanmak isteyebilirsiniz .

Küresel devletlerle ilgili sorun, bazen daha basit bir bağlamda küresel olarak mantıklı olan şeyin, pratik bir bağlamda biraz daha esnek olması gerektiğidir ve bu da singleton modelinin faydalı hale geldiği yerdir.


5

Yine başka bir neden: kırılganlık.

Bir sınıfınız varsa, çoğu kişi onu oluşturabilir ve istediği gibi kullanabilir.

Durum böyle olmadığını belgeleyebilir veya buna karşı koruyabilirsiniz (singleton / fabrika deseni) - ancak bu ekstra bir iştir ve bu nedenle ek bir maliyettir. O zaman bile, büyük bir şirkette, birisi bir noktada tüm güzel yorumlara veya fabrikaya tamamen dikkat etmeden sınıfınızı kullanmaya çalışacaktır.

Statik değişkenleri çok kullanıyorsanız, bu bozulur. Hatalar pahalıdır.

% .0001 performans artışı ve potansiyel olarak clueless geliştiriciler tarafından değişime karşı sağlamlık arasında, çoğu durumda sağlamlık iyi bir seçimdir.


4

Statik değişkenlerin kullanımını daha uygun buluyorum. Ve onların da verimli olduklarını varsayıyorum (eğer yanılıyorsam lütfen beni düzeltin) çünkü bir sınıf içindeki bir işleve 10.000 çağrı yapmak zorunda kalsaydım, yöntemi statik yapmaktan ve basit bir class.methodCall () kullanmaktan memnuniyet duyarım. hafızayı sınıfın 10.000 örneğiyle karıştırmak yerine, değil mi?

Ne düşündüğünüzü görüyorum, ancak basit bir Singleton modeli, 10.000 nesneyi somutlaştırmak zorunda kalmadan aynı şeyi yapacaktır.

statik yöntemler kullanılabilir, ancak yalnızca nesne etki alanıyla ilgili olan ve nesnenin dahili özelliklerine ihtiyaç duymayan veya bunları kullanmayan işlevler için kullanılabilir.

örn:

public class WaterContainer {
    private int size;
    private int brand;
    ...etc

    public static int convertToGallon(int liters)...

    public static int convertToLiters(int gallon)...

}

Klasik bir singleton (yani erişilen Class.Instance), statik bir değişkenden zar zor daha iyidir. Biraz daha test edilebilir, ancak kodunuzu sadece bir tane varsayı üzerine inşa etmek yerine sadece tek bir örnek oluşturduğunuz tasarımlardan çok daha kötü.
CodesInChaos

Yorumunuzu anladığımdan emin değilim! OP'ye 10.000 nesnenin örneklenmesi hakkında italik olarak söyledikleri hakkında yanıt veriyordum. Neden tek ve statik değişkenleri karşılaştırdığınızı anlamıyorum? Yazdıklarından anladığım şey Singleton'un kötü tasarım olduğu ...! Bahar Çerçeve varsayılan olarak tüm fasulye Singleton ;-)
Cygnusx1

Class.InstanceDeğişken bir durum taşıyan klasik bir singleton ( kötü) IMO kötü tasarım. Bu durumda, bunları kullanacak sınıfa parametre olarak geçirilen tektonları aldığım bir tasarımı şiddetle tercih ederim (genellikle DI'nin yardımıyla). Mantıksal olarak değişmez klasik singletonlar iyi IMO'dur.
CodesInChaos

@ Cygnusx1 Bir Class singletonunun (sınıfın tek bir kopya olmasını sağlayan singleton) neden kolayca test edilemediği net değilse, sınıf varlığını programın yaşam döngüsüne sıkıca bağlar. Test etmek için, genellikle sınıfın test edilmesinde önemsiz yan etkileri olan programın başlatılmasına ve kapatılmasına uymalısınız. Etkin olarak tekil olarak (programda bir kopya, ancak aksi halde zorlama değilse), program olmadan test zamanında birden fazla kopya oluşturabilir ve sınıftaki davranışın her test senaryosu için olması gerektiği gibi olduğunu doğrulayabilirsiniz.
Edwin Buck

4

'Statik şeytan olmak' konusu küresel devletle ilgili bir konudur. Bir değişkenin statik olması için uygun zaman, birden fazla durumunun olmamasıdır; Tüm çerçeve tarafından erişilebilir olması ve aynı yöntem çağrıları için her zaman aynı sonuçları döndürmesi gereken IE araçları statik olarak asla 'kötü' değildir. Yorumunuza gelince:

Statik değişkenlerin kullanımını daha uygun buluyorum. Ve onların da verimli olduklarını düşünüyorum

Statik, hiç değişmeyen değişkenler / sınıflar için ideal ve verimli seçimdir .

Küresel devletle ilgili sorun, yaratabileceği doğal tutarsızlıktır. Birim testleri hakkındaki belgeler genellikle bu sorunu ele alır, çünkü birden fazla ilişkisiz nesne tarafından erişilebilen bir genel durum olduğunda, birim testleriniz eksik olur ve 'birim' taneli değil. Bu makalede küresel durum ve tektonlarla ilgili olarak belirtildiği gibi , A ve B nesnesi ilgisizse (birinde açıkça diğerine referans verilmiyorsa), A, B'nin durumunu etkileyemez.

Küresel yasağın iyi kodda saati gibi bazı istisnaları vardır. Zaman küreseldir ve - bir anlamda - kodlanmış bir ilişkiye sahip olmadan nesnelerin durumunu değiştirir.


"Zaman küreseldir" - bilgisayar sistemlerinde zamanı modellemenin kendi başına değişen bazı örtük, küresel bir şey olmaktan başka yolları da vardır. bakınız Bu anket: "Bilgi İşlemde Modelleme Zamanı: Bir Sınıflandırma ve Karşılaştırmalı Bir Araştırma" @ arxiv.org/abs/0807.4132
Jared Updike

4

Benim $ .02, bu istatistiklerin birçoğunun "statik kötü" demek yerine konuyu karıştırmasıdır. Kapsam belirleme ve örnekler hakkında konuşmak daha iyidir.

Ne söyleyebilirim bir statik bir "sınıf" değişkenler - o sınıfın tüm örnekleri arasında paylaşılan bir değeri temsil eder. Tipik olarak da bu şekilde kapsamlandırılmalıdır (sınıfa ve örneklerine karşı korumalı veya özel).

Sınıf düzeyinde davranışı etrafına koymayı ve başka bir koda göstermeyi planlıyorsanız, tek birton gelecekteki değişiklikleri desteklemek için daha iyi bir çözüm olabilir (@Jessica'nın önerdiği gibi). Bunun nedeni, arabirimleri sınıf / tekton düzeyinde, sınıf düzeyinde kullanamayacağınız yollarla (özellikle miras) kullanabilmenizdir.

Diğer cevaplardaki bazı yönlerin neden sorunun temelini oluşturmadığına dair bazı düşünceler ...

Statik "küresel" değildir. Java'da kapsam belirleme statik / örnekten ayrı olarak kontrol edilir.

Eşzamanlılık, statik için örnek yöntemlerden daha az tehlikeli değildir. Hala korunması gereken bir durum. Her biri bir örnek değişkeni ve yalnızca bir statik değişkeni olan 1000 örneğiniz olabileceğinden emin olabilirsiniz, ancak her ikisine erişen kod da iş parçacığı açısından güvenli bir şekilde yazılmamışsa, bunu gerçekleştirmeniz biraz daha uzun sürebilir .

Yaşam döngüsünü yönetmek ilginç bir argüman, ama bence bu daha az önemli. Neden init () / clear () gibi bir çift sınıf yöntemini yönetmek tek bir örneği oluşturmak ve yok etmek daha zor görmüyorum. Aslında, bazıları GC nedeniyle bir singletonun biraz daha karmaşık olduğunu söyleyebilir.

PS, Smalltalk açısından, lehçelerinin çoğunun sınıf değişkenleri vardır, ancak Smalltalk sınıflarında aslında Metaclass örnekleridir, bu yüzden gerçekten Metaclass örneğinde değişkenlerdir. Yine de aynı kuralý uygulardým. Örnekler arasında paylaşılan durum için kullanılıyorlarsa, tamam. Kamusal işlevselliği destekliyorlarsa, bir Singleton'a bakmalısınız. Ah, elbette Smalltalk'u özledim ....


4

Yayınınızda iki ana soru var.

İlk olarak, statik değişkenler hakkında. Statik değişkenler gereksizdir ve kullanımı kolayca önlenebilir. Genel olarak OOP dillerinde ve özellikle Java'da işlev parametreleri başvuru ile yapıştırılır, yani bir nesneyi bir işleve geçirirseniz, nesneye bir işaretçi geçirirsiniz, bu nedenle statik değişkenleri tanımlamanız gerekmez. nesneye bu bilgiye ihtiyaç duyan herhangi bir kapsama bir işaretçi iletebilirsiniz. Bu, belleğinizi işaretçilerle dolduracağı anlamına gelse bile, bu gerçek bir performans göstermeyecektir, çünkü gerçek bellek çağrı sistemleri bununla başa çıkmak için optimize edilmiştir ve yeniye geçtiğiniz işaretçiler tarafından referans verilen sayfaları bellekte tutacaktır. dürbün; statik değişkenlerin kullanılması, sistemin erişilmesi gerektiğinde bellek sayfasını depolandıkları yere yüklemesine neden olabilir (bu, sayfaya uzun süre erişilmezse gerçekleşir). Tüm bu statik stufu bazı küçük "yapılandırma sınıflarında" bir araya getirmek iyi bir uygulamadır, bu sistemin hepsini aynı bellek sayfasına koymasını sağlayacaktır.

İkincisi, statik yöntemler hakkında. Statik yöntemler o kadar da kötü değildir, ancak performansı hızla düşürebilirler. Örneğin, bir sınıfın iki nesnesini karşılaştıran ve nesnelerden hangisinin daha büyük olduğunu gösteren bir değer döndüren bir yöntemi düşünün (tipik karşılaştırma yöntemi) bu yöntem statik olabilir veya olmayabilir, ancak çağrıldığında statik olmayan form daha etkili olacaktır çünkü aynı yöntemin statik sürümünü çözmek zorunda kalacak üç referansla (her nesne için bir tane) yalnızca iki referansı çözmesi gerekecektir (biri sınıf artı iki, her nesne için bir tane). Ama dediğim gibi, bu o kadar da kötü değil, eğer Math sınıfına bakarsak, statik yöntemler olarak tanımlanan birçok matematik işlevi bulabiliriz. Bu, tüm bu yöntemleri sayıları tanımlayan sınıfa koymaktan çok daha etkilidir,

Sonuç: Statik değişkenlerin kullanımından kaçının ve statik veya statik olmayan yöntemlerle uğraşırken doğru performans dengesini bulun.

PS: İngilizcem için özür dilerim.


4

Statik değişkenlerle ilgili yanlış bir şey yoktur. Kırılan sadece Java sözdizimi. Her Java sınıfı aslında iki yapı tanımlar - statik değişkenleri kapsayan tek bir nesne ve bir örnek. Her ikisini de aynı kaynak bloğunda tanımlamak saf kötülüktür ve okunması zor bir kodla sonuçlanır. Scala bunu doğru yaptı.


3

a) Programların nedeni.

Statik değişken Global.foo'nun erişildiği küçük - orta büyüklükte bir programınız varsa, buna normalde çağrı hiçbir yerden gelmez - değişken yoktur. kullanıldı. Şimdi kimin gerçek değerine ayarladığını nasıl bilebilirim? Şu anda değiştirirsem ne olur, nasıl olur? Tüm kaynak üzerinde grep var, tüm erişimleri toplamak, neler olduğunu bilmek.

Kodu nasıl kullandığınızı biliyorsanız, sadece kodu yazdığınız için sorun görünmezdir, ancak yabancı kodu anlamaya çalışırsanız, anlayacaksınız.

b) Gerçekten sadece birine ihtiyacınız var mı?

Statik değişkenler genellikle aynı JVM'de farklı değerlerle aynı türden birden fazla programın çalışmasını önler. Programınızın birden fazla örneğinin yararlı olduğu kullanımları genellikle öngörmezsiniz, ancak gelişirse veya başkaları için faydalıysa, programınızın birden fazla örneğini başlatmak istedikleri durumlar yaşayabilirler. .

Birçok kişi tarafından uzun süre yoğun bir şekilde kullanılmayacak olan az çok işe yaramaz kod statik değişkenlerle iyi sonuç verebilir.


3

her şeyi (olabilir :) amacı var, eğer paylaşmanız / önbelleğe almanız gereken çok sayıda iş parçacığına ve ayrıca tüm erişilebilir belleğe sahipseniz (böylece bir JVM içinde bağlamlara bölünmezseniz) statik en iyi seçimdir

-> elbette zorlayabilirsiniz sadece bir örnek, ama neden?
statik değil, bu iş parçacığı bazı yorumlar bulmak;)


3

Statik değişkenler iyi veya kötü değildir. Belirli bir örneği değil, tüm sınıfı tanımlayan nitelikleri temsil ederler. Belirli bir sınıfın tüm örnekleri için bir sayacınız olması gerekiyorsa, statik bir değişken değeri tutmak için doğru yer olacaktır.

Örnekle ilgili değerleri tutmak için statik değişkenler kullanmaya çalıştığınızda sorunlar ortaya çıkıyor.


2

Yukarıdaki tüm cevaplar, statikin neden kötü olduğunu göstermektedir. Kötülüğün nedeni , aslında olmadığınızda, nesne yönelimli kod yazdığınıza dair yanlış izlenim vermesidir. Bu sadece açık bir kötülük.


1
Ancak, kodunuzu bazı keyfi standart paradigmaları izlemek için katı bir şekilde düşünmek aslında kodu daha iyi hale getiriyor mu, yoksa sadece çalışan kod yazmaktan kaçınıyor muyuz?
Zoey

Evet, bunu daha iyi hale getiriyor, çünkü gelecekte daha yönetilebilir, anlaşılması daha kolay ve daha açık hale getiriyor.
ahmak

1
OO kodu yazmamak neden kötüdür? ve neden Bjarne Stroustrup sizinle aynı fikirde değil? sadece bir isim ...
Lorne Marquis

2
OO kodunu yazmak için kötü olduğunu söylemedim. OO kodunu yazdığınızı düşünmenin kötü olduğunu söyledim, tüm olduğunuz küreselleri statik yöntemlerin ve özelliklerin arkasına gizlerken. Lütfen yazdıklarımı tekrar okuyun.
ahmak

2

Burada birçok iyi cevap var, buna ek olarak,

Bellek: Statik değişkenler, sınıf yükleyicisi [genel olarak VM ölene kadar] yaşadığı sürece canlıdır, ancak bu yalnızca statik olarak depolanan toplu nesneler / referanslar durumundadır.

Modülerleştirme: IOC, bağımlılık Enjeksiyon, proxy vb. Gibi kavramları göz önünde bulundurun. Hepsi tamamen sıkı bağlantı / statik uygulamalara karşıdır.

Diğer Con'lar: İplik Güvenliği, Test Edilebilirlik


0

Birçok kullanıcılı bir uygulamanız varsa ve statik bir form tanımladıysanız, her kullanıcının diğer kullanıcıların diğer tüm formlarını da değiştireceğini düşünün.


0

Statik anahtar kelime ile küresel değişkenlerin aşırı kullanımının, aynı zamanda, uygulamada bir noktada bellek sızıntısına yol açacağını düşünüyorum


0

Benim açımdan staticdeğişken sadece okunabilir veri veya kural tarafından oluşturulan değişkenler olmalıdır .

Örneğin, bir projenin kullanıcı arayüzüne sahibiz ve ülkeler, diller, kullanıcı rolleri, vb. Bir listemiz var. Ve bu verileri düzenlemek için sınıfımız var. uygulamanın bu listeler olmadan çalışmayacağından kesinlikle eminiz. uygulama init'te yaptığımız ilk şey bu listeyi güncellemeler için kontrol etmek ve bu listeyi api'den almak (gerekirse). Bu nedenle, bu verilerin uygulamada "her zaman" bulunduğunu kabul ediyoruz. Pratik olarak sadece verileri okur, bu yüzden durumuyla ilgilenmemiz gerekmez - bu durumu düşünerek bu verilerin çok fazla örneğini gerçekten istemiyoruz - bu vaka statik olmak için mükemmel bir aday gibi görünüyor .


0

Statikle çok oynadım ve size biraz farklı bir cevap verebilir miyim - ya da belki ona bakmak için biraz farklı bir yol?

Bir sınıfta statik kullandığımda (Üyeler ve yöntemler her ikisi de) sonunda sınıfımın aslında sorumluluk paylaşan iki sınıf olduğunu fark etmeye başladım - bir singleton gibi davranan "Statik" kısım var ve - statik kısım (normal sınıf). Bildiğim kadarıyla, bir sınıf için tüm statik ve diğeri için statik olmayanları seçerek bu iki sınıfı her zaman tamamen ayırabilirsiniz.

Bu, sınıfın örneklerini tutan bir sınıfın içinde statik bir koleksiyon ve koleksiyonu yönetmek için bazı statik yöntemler olduğunda çok olur. Bir kez düşündüğünüzde, sınıfınızın "Tek bir şey" yapmadığı açıktır, bu bir koleksiyon ve tamamen farklı bir şey yapmaktır.

Şimdi, sorunu biraz yeniden ele alalım: Sınıfınızı her şeyin statik olduğu bir sınıfa ayırırsanız, sadece "Normal Sınıf" olan ve "Normal Sınıf" ı unutursanız, sorunuz tamamen Statik sınıf mı SingleT'e burada (ve muhtemelen bir düzine başka soru) uzun süredir ele alınmıştı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.