Statik Sınıflar ve Üyeler Üzerine Düşünceler ve En İyi Uygulamalar [kapalı]


11

Statik üyeler veya tüm statik sınıflarla ilgili düşünceleri ve sektördeki en iyi uygulamaları merak ediyorum. Bunun bir dezavantajı var mı, yoksa herhangi bir anti-paterne katılıyor mu?

Bu varlıkları, işlevselliği sağlamak için sınıfın somutlaştırılmasını gerektirmedikleri veya talep etmedikleri için "faydalı sınıflar / üyeler" olarak görüyorum.

Bununla ilgili genel düşünceler ve sektördeki en iyi uygulamalar nelerdir?

Nelerden bahsettiğimi göstermek için aşağıdaki örnek sınıflara ve üyelere bakın.

// non-static class with static members
//
public class Class1
{
    // ... other non-static members ...

    public static string GetSomeString()
    {
        // do something
    }
}

// static class
//
public static class Class2
{
    // ... other static members ...

    public static string GetSomeString()
    {
        // do something
    }
}

Şimdiden teşekkür ederim!


1
Statik Sınıflar ve Statik Yöntemler MSDN makale oldukça iyi bir tedavi sağlamaktadır.
Robert Harvey

1
@Robert Harvey: Referans ettiğiniz makale faydalı olsa da, en iyi uygulamalar ve statik sınıfları kullanırken bazı tuzakların ne olduğu konusunda pek bir şey sunmuyor.
Bernard

Yanıtlar:


18

Genel olarak, statikten kaçının - özellikle her türlü statik durum.

Neden?

  1. Statik, eşzamanlılık konusunda sorun yaratır. Tek bir örnek olduğundan, eşzamanlı yürütme arasında doğal olarak paylaşılır. Bu paylaşılan kaynaklar, eşzamanlı programlama sorunudur ve çoğu zaman paylaşılmasına gerek yoktur .

  2. Statik, birim testlerinde sorun yaratır. Tuz değerine sahip herhangi bir birim test çerçevesi aynı anda testleri çalıştırır. Sonra # 1 ile karşılaşıyorsunuz. Daha da kötüsü, testlerinizi tüm kurulum / sökme işlemleriyle ve kurulum kodunu "paylaşmak" için kullanacağınız bilgisayar korsanlığıyla karmaşık hale getirirsiniz.

Çok küçük şeyler de var. Statik esnek değildir. Onları arayüzleyemezsiniz, onları geçersiz kılamazsınız, yapılarının zamanlamasını kontrol edemezsiniz, jeneriklerde iyi kullanamazsınız. Onları gerçekten versiyonlayamazsınız.

Kesinlikle statik kullanımı vardır: sabit değerler harika çalışır. Tek bir sınıfa uymayan saf yöntemler burada harika çalışabilir.

Ama genel olarak, onlardan kaçının.


Demek istediğin eşzamanlılık için ne kadar yetersiz olduğunu merak ediyorum. Bunu genişletebilir misin? Eğer üyelere ayrışma olmadan erişilebileceğini kastediyorsanız, bu çok mantıklıdır. Statik için kullanım durumlarınız, genellikle sabit değerler ve saf / yardımcı yöntemler için kullandığım şeylerdir. Statik için en iyi ve% 99 kullanım durumu ise, bu bana bir rahatlık seviyesi verir. Ayrıca, cevabınız için +1. Harika bilgi.
Thomas Stringer

@ThomasStringer - iş parçacıkları / görevler arasında daha fazla temas noktası olması, eşzamanlılık sorunları için daha fazla fırsat ve / veya senkronizasyon yaparken daha fazla performans kaybı anlamına gelir.
Telastyn

Bir iş parçacığı şu anda statik bir üyeye erişiyorsa, diğer iş parçacığı sahibi iş parçacığı kaynağı serbest bırakana kadar beklemek gerekir?
Thomas Stringer

@ThomasStringer - belki, belki değil. Statik (hemen hemen birçok dilde) bu bağlamda paylaşılan diğer kaynaklardan farklı değildir.
Telastyn

@ThomasStringer: Üyeyi işaretlemediğiniz sürece maalesef bundan daha kötü volatile. Uçucu veriler olmadan bellek modelinden hiçbir güvence almazsınız, bu nedenle bir iş parçacığında bir değişkeni değiştirmek hemen veya hiç yansıtmayabilir.
Phoshi

17

Eğer fonksiyon "saf" ise hiçbir problem görmüyorum. Saf bir işlev yalnızca giriş parametrelerinde çalışır ve buna dayalı bir sonuç sağlar. Herhangi bir küresel duruma veya dış bağlama bağlı değildir.

Kendi kod örneğinize bakarsam:

public class Class1
{
    public static string GetSomeString()
    {
        // do something
    }
}

Bu işlev herhangi bir parametre almaz. Bu nedenle, muhtemelen saf değildir (bu işlevin tek saf uygulaması sabit döndürmek olacaktır). Bu örneğin gerçek probleminizi temsil etmediğini varsayıyorum, sadece bunun muhtemelen saf bir işlev olmadığını belirtiyorum.

Farklı bir örnek verelim:

public static bool IsOdd(int number) { return (number % 2) == 1; }

Bu fonksiyonun statik olmasıyla ilgili yanlış bir şey yoktur. Bunu bir uzantı fonksiyonuna dönüştürerek istemci kodunun daha da okunabilir olmasını sağlayabiliriz. Uzatma fonksiyonları vardır temelde statik işlevleri sadece özel bir tür.

Telastin, statik üyelerde potansiyel bir sorun olarak eşzamanlılıktan doğru bir şekilde bahseder. Ancak, bu işlev paylaşılan durumu kullanmadığından, burada eşzamanlılık sorunu yoktur. Bin iş parçacığı eşzamanlılık sorunu olmadan aynı anda bu işlevi çağırabilir.

.NET çerçevesinde, uzantı yöntemleri oldukça uzun bir süredir varlığını sürdürmektedir. LINQ çok sayıda uzantı işlevi içerir (örneğin Enumerable.Where () , Enumerable.First () , Enumerable.Single () , vb.). Bunları kötü görmüyoruz, değil mi?

Birim testi genellikle kod değiştirilebilir soyutlamalar kullandığında yarar sağlayabilir ve birim testinin sistem kodunu bir test çiftiyle değiştirmesine izin verir. Statik işlevler bu esnekliği yasaklar, ancak bu çoğunlukla gerçek veri erişim katmanını sahte veri erişim katmanıyla değiştirmek istediğimiz mimari katman sınırlarında önemlidir .

Bununla birlikte, farklı davranan bir nesne için bir test yazarken, bir sayının tek veya çift olmasına bağlı olarak, IsOdd()işlevi gerçekten alternatif bir uygulama ile değiştirmemiz gerekmez . Benzer şekilde, Enumerable.Where()test amacıyla ne zaman farklı bir uygulama sağlamamız gerektiğini görmüyorum .

Şimdi bu işlev için istemci kodunun okunabilirliğini inceleyelim:

Seçenek a (işlev bir uzantı yöntemi olarak bildirilmiş olarak):

public void Execute(int number) {
    if (number.IsOdd())
        // Do something
}

Seçenek b:

public void Execute(int number) {
    var helper = new NumberHelper();
    if (helper.IsOdd(number))
        // Do something
}

Statik (uzatma) işlevi, ilk kod parçasını daha okunaklı hale getirir ve okunabilirlik çok önemlidir, bu nedenle uygun olduğunda statik işlevleri kullanın.

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.