Vatansızlık hakkında semantik bir ipucu olarak “statik”?


11

Geçenlerde Java'da geri dönüp birim testleri eklemek için orta ölçekli bir projenin yeniden düzenlenmesi işlemini yaptım. Singletonlar ve statiklerle alay etmenin ne kadar acı olduğunu fark ettiğimde, nihayet onlar hakkında okuduğum şeyi bu kez "aldım". (Deneyimden öğrenmesi gereken insanlardan biriyim. Oh iyi.)

Şimdi, nesneleri oluşturmak ve onları birbirine bağlamak için Spring'i kullandığımdan, staticsol ve sağ anahtar kelimelerden kurtuluyorum . (Potansiyel olarak bunu taklit istiyor olsaydı, doğru, Math.abs () olduğunu aynı anlamda gerçekten statik değil mi?) Şeydir, ben kullanma alışkanlığı içine kazanılmış staticbir yöntem itimat etmediğini belirtmek için herhangi bir nesne durumunda. Örneğin:

//Before
import com.thirdparty.ThirdPartyLibrary.Thingy;
public class ThirdPartyLibraryWrapper {
    public static Thingy newThingy(InputType input) {
         new Thingy.Builder().withInput(input).alwaysFrobnicate().build();
    }
}

//called as...
ThirdPartyLibraryWrapper.newThingy(input);
//After
public class ThirdPartyFactory {
    public Thingy newThingy(InputType input) {
         new Thingy.Builder().withInput(input).alwaysFrobnicate().build();
    }
}

//called as...
thirdPartyFactoryInstance.newThingy(input);

İşte burada dokunaklı bir şekilde hissediliyor. Eski yolu sevdim çünkü büyük harf bana Math.sin (x) gibi ThirdPartyLibraryWrapper.newThingy (x) 'in her seferinde aynı şeyi yaptığını söyledi. Nesnenin yapmasını istediğim şeyi nasıl yapacağını değiştirecek nesne durumu yok. İşte düşündüğüm bazı olası cevaplar.

  • Kimse bu şekilde hissetmiyor, bu yüzden benimle ilgili bir sorun var. Belki de OO'nun bir şeyler yapma şeklini gerçekten içselleştirmedim! Belki Java ile yazıyorum ama FORTRAN ya da daha çok düşünüyorum. (FORTRAN'ı hiç yazmadım çünkü bu etkileyici olurdu.)
  • Belki statiklik kod hakkında muhakeme amacıyla değişmezlik için bir tür proxy olarak kullanıyorum. Olduğu söyleniyor, neyin durumunun ne olduğunu ve neyin olmadığını bilmek için kodumda hangi ipuçlarının olması gerekir ?
  • Belki de iyi nesne metaforları seçersem bu bedavaya gelmelidir? örneğin thingyWrapper, Thingykendisinin değişebilen sarılı durumdan bağımsız bir duruma sahip gibi görünmüyor . Benzer şekilde, bunun thingyFactorygibi bir ses değişmez olmalı, ancak yaratılışta seçilen farklı stratejilere sahip olabilir.

Yanıtlar:


12

Eski yolu sevdim çünkü büyük harf bana Math.sin (x) gibi ThirdPartyLibraryWrapper.newThingy (x) 'in her seferinde aynı şeyi yaptığını söyledi. Nesnenin yapmasını istediğim şeyi nasıl yapacağını değiştirecek nesne durumu yok.

Bunu yapmanın doğru yolu bu, evet. Bununla birlikte static, değişmezlik veya devletin sürekliliği konusunda hiçbir garanti vermez. Bu tür garantiler için bir öneri olarak kullanmanız mantıklıdır, ancak hiçbir şekilde garanti edilmez.

Aşağıdakileri göz önünde bulundur:

public static class Logger
{
    public static int LogLevel { get; set; }

    public static void Log(string message, int logLevel)
    {
        if (logLevel >= LogLevel)
        {
            // logs the message, but only if it is important enough.
        }
    }
}

Bu sınıf yalnızca durumu değil, aynı zamanda Logger.Log()bu durum değiştirildiğinde yöntemin davranışı da değişir. staticSınıf düzeninin mükemmel bir şekilde meşru bir uygulamasıdır , ancak önerdiğiniz anlambilimsel garantilerin hiçbirine sahip değildir.


Size onay işaretini verdim çünkü sezgilerime dayanarak faydalı bir kontrpuan sunuyorsunuz, ancak yine de devlet eksikliği ve kodlama yoluyla yan etkilerin olmaması hakkındaki bu sözleşmeyi / beklentiyi nasıl temsil etmem gerektiğine dair düşüncelerinizi almak istiyorum. sözleşmeler.
leoger

1
Normalde bu tür beklentiler yöntemin belgelerine dahil edilir; Aynı şey iplik güvenliği için de geçerlidir.
Robert Harvey

5

Bence ne diyorsun - tüm statik fonksiyonlar nullipotent olmak için - çoğu durumda kod yazmanın iyi bir OO yoludur, ancak statik bir fonksiyona baktığınızda otomatik olarak yan etkilere sahip olmadığını varsaymanız gerektiğine inanmıyorum. . Durum daha karmaşık olabilir; örneğin Class.forName(String)vatansız gibi görünen ancak aslında belleğe bir sınıf yükler ve sonunda statik alanları başlatır / statik başlatıcı çalıştırır; bu idempotent fonksiyonun bir örneğidir (birincisinden sonra gelen aramalar hiçbir fark yaratmaz), ancak saf bir fonksiyon değildir (yan etkileri olmadığı söylenemez). Bu da iyi bir seçimdir, ancak aynı işleve üç farklı çağrının üç farklı sonuç verdiği durumlar olabilir; örneğin ararsanThread.currentThread() çok iş parçacıklı bir uygulamada her seferinde aynı ipliği alacağınızın garantisi yoktur.

Olduğu söyleniyor, neyin durumunun ne olduğunu ve neyin olmadığını bilmek için kodumda hangi ipuçlarının olması gerekir?

Uygun bir çözüm belgelendirmektir (örneğin Javadoc); ayrıca, fonksiyonun adından ve bazen yaptığı şeyden, statik fonksiyonun saf bir fonksiyon olduğu anlaşılabilir. Örneğin, birinin Assert.assertTrue(boolean)JUnit'ten bir yerlerde bir durumu değiştireceğine inanması için hiçbir neden yoktur . Öte yandan, böyle bir işlev System.clearProperty(String)çağrıldığında yan etkilerin olacağı oldukça açıktır.


"Nullipotent" ve "stateless" arasındaki fark nedir?
Pacerier

@Pacerier Fark olmamalı.
m3th0dman

4

Olduğu söyleniyor, neyin durumunun ne olduğunu ve neyin olmadığını bilmek için kodumda hangi ipuçlarının olması gerekir?

Onları statik hale getirebilirsiniz. C # dünyasında FxCop sizi referans üye değişkenleri olmayan statik şeyler yapmak için itecektir. Bu yapılacak doğru şeydir (genellikle).

Singletonlar ve statiklerle alay etmenin ne kadar acı olduğunu fark ettiğimde, nihayet onlar hakkında okuduğum şeyi bu kez "aldım".

Hepsini örneklere taşımak belki de doğru yaklaşım değildir. Bunun yerine, statik yöntemlere bağımlılıkları, bunları kullanan sınıflardan ayırın. Statik yöntemleri ayrı ayrı test edebilir ve daha sonra tüketicilerin test edilmesi gerektiğinde bağımlılığı değiştirebilirsiniz.


Bana "statik yöntemlere bağımlılıkları ayırmak" örneği verebilir misiniz? Neyi aktifleştirdiğiniz net değil. Statik bir yöntemde uygulama ayrıntılarını zaten gizledim. Günün sonunda, onu kullanan sınıfın bu işlevselliğe ulaşması gerekir . Tüm statik yöntemler için ince sarmalayıcıları olan bir örnek nesne oluşturmam gerektiğini mi söylüyorsunuz?
leoger

1
@leoger - o sınıfı test ediyorsanız, statik yöntemi kullanan sınıfın işlevselliğe ulaşması gerekmez, aksi takdirde statik yöntemi alay etmezsiniz.
Telastyn
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.