2016-04-03 22 views
0

Görünüş:Açık/Kapalı İlkesi, sınıflarımızın arayüzlerini değiştiremediğimizi söylüyor mu? Lütfen sınıfta

public class SomeClass { 

public void method1(){ 
    // do something 
} 

public void method2(){ 
    // do something 
} 

} 

Sonraki 10 sınıfları bu sınıfı miras olduğunu düşünün. Yani, eğer methodr() 'e parametr eklersek, örneğin 10 sınıfı değiştirmeliyiz. Bu Açık/Kapalı ilkesine aykırıdır. Yani, Açık/Kapalı İlkesi sınıflarımızın genel arayüzünü değiştiremeyeceğimizi söylüyor mu?

+1

Birden fazla 10 değiştirmek zorunda bu parametrenin bir sağlayıcı enjekte sınıflar. Bu çağıran argümanlardan hiçbiri artık geçerli olmadığından * call1 'method1()' olacak her sınıfı değiştirmelisiniz. OCP konusunda basit geriye dönük uyumluluk konusunda çok endişelenmem. Tabii ki, tüm arama kodunu kontrol ederseniz, sorun yok. Gerçekten içeriğe bağlı. –

+1

http://programmers.stackexchange.com/questions/310603/is-it-appropriate-to-not-follow-the-oc-principle-if-you-have-unit-test-coverage –

+0

@JonSkeet, Genel arayüzünü değiştirebileceğim tüm çağrı kodlarını kontrol ediyorum. Kontrol etmezsem eski yöntem sürümünü kaydetmeli ve yeni bir versiyon eklemeliyim? Bundan sonra eski sürümü kullanımdan kaldırılabilir mi? –

cevap

0

Evet - nevi ... 8.> P

biraz sen public void method1() imzayı kaldırmak ne de tüm düzgün uygulayarak teslim edilecek (onun semantik değiştirmemelidir diyor "değişikliklere Closed" beton sınıfları.

"Uzantıya aç" bit, önceki arabirim öğelerinin olduğu gibi (yapısal ve semantik olarak) olduğu sürece arabirimi (dikkatli bir şekilde) değiştirmenize izin verir.

public class SomeClass { 

    @Deprecated 
    default public void method1(){ 
     method1(#SENTINAL#); 
    } 

    public void method1(#TYPE# arg){ 
     if (arg == #SENTINAL#) { 
      // do something old 
     } else { 
      // do something new 
     } 
    } 

    public void method2(){ 
     // do something 
    } 

} 

NOT: argüman yararlı bir # Sentinal # değeri yoktur, bu yaklaşım çalışmayabilir, örneğin Böyle bir şey deneyebilirsiniz Bu bir int ve tüm değerler geçerlidir.

public class SomeClass { 

    @Deprecated 
    default public void method1(){ 
     method1(true); 
    } 

    public void method1(#TYPE# arg){ 
     method1(false, arg) 
    } 

    private void method1(boolean isOldWay, #TYPE# arg) { 
     if(isOldWay) { 
      // snore - still old clients 
     } else { 
      // yea! new clients are much greener! 
     } 
    } 
} 

PS: Genellikle olsa da, bir şey vb böyle sentinal mevcut olduğunda, herhangi bir MİN veya MAX değeri, negatif boş veya null bir nesne gibi, sen gibi özel ortak yöntem, oluşturabilir, orada - Sınıf kullanıyorsanız bile "arayüz" diyorum. Sadece arayüzü, sınıfın uygulandığı aynı zamanda ilan edilen sınıfın genel öğeleri olarak düşünün. Genelde kod-arası arayüzleri tercih ederim, fakat bu OP'nin sorusu değil, ya da benim noktayı değiştirir (yalnızca kodunun değiştirilmesinin yapıldığı - Java 8 arayüz-varsayılan uygulamaları kullanılıyorsa).

+0

"Uzantıya aç" seçeneğinin, arabirimi değiştirmenize izin verdiğine katılmıyorum - bunu zaman zaman yapmanız gerekebilir, ancak bu, OCP'yi ihlal ediyor, daha sonra bunun bir parçası değil. OCP, yeniden düzenleme ve değişiklik yapmanız gerekiyorsa, gelecekteki uzantıya açık bir şekilde yaptığınızı söylüyor. Örneğin. Ziyaretçi/Strateji modeli gibi bir şey aracılığıyla. Ayrıca bakınız [Bob Amca] Bu makale (https://blog.8thlight.com/uncle-bob/2014/05/12/TheOpenClosedPrinciple.html) – anotherdave

+0

Eh, biraz saç kıvırıyor, ama sanırım müşteri kodları değiştirilmeye gerek olmadığı sürece, iyi (çoğu derlemede, fakat tek bir ayraç bile düzeltilemiyor) * gülümseme :: *). Doğru, "saf" bir OCP ihlali bir şey, ama ben ruhu, tamamen *** uyumlu değişiklikler arayüz tarafından korunur düşünmek için pragmatik değilim - varsayılan neden aslında bu yüzden diline yine de? (Çok kötü, biz onları 'varsayılan final' yapamayız ... * :: haha ​​:: *) – Stevel

+0

pragmatizm her zaman anahtardır (bu da bir "kural" yerine bir "prensip" olmasının nedeni budur) Bir kod onu ihlal etmek için kokuyor, ama bu asla yapılmaması gerektiği anlamına gelmez). – anotherdave

0

Bu bir OCP ihlalidir. Modifikasyon, sınıfa geçtikten ve test ettikten sonra artık değiştirmemeniz anlamına gelir. İş gereksinimlerinin aniden değiştiğini ve bunları ne kadar iyi tasarlamış olursanız olun sınıflarınızı değiştirmeniz gerektiğini tahmin edebileceğiniz durumlar vardır. Senin durumunda bunu yapmanın en temiz yolu uygulayan sınıfların yapıcısı bunu enjekte ederek bu yeni parametre eklemek için, ya da daha da iyisi,

public class SomeClass{  
    IProvider _provider; 

    public SomeClass(IProvider provider){ 
     _provider = provider 
    } 

    public void method1(){ 
     var someInput = _provider.Get(); 
     // do something 
    } 

    public void method2(){ 
     var someInput = _provider.Get(); 
     // do something 
    } 
}