Tek Sorumluluk İlkesi işlevler için geçerli midir?


17

Robert C. Martin'e göre, SRP şunları söylüyor:

Bir sınıfın değişmesi için asla birden fazla sebep olmamalıdır .

Bununla birlikte, Temiz Kod , bölüm 3: İşlevler kitabında aşağıdaki kod bloğunu gösterir:

    public Money calculatePay(Employee e) throws InvalidEmployeeType {
        switch (e.type) {
            case COMMISSIONED:
                return calculateCommissionedPay(e);
            case HOURLY:
                return calculateHourlyPay(e);
            case SALARIED:
                return calculateSalariedPay(e);
            default:
                throw new InvalidEmployeeType(e.type);
        }
    }

Ve sonra şunu belirtiyor:

Bu işlevle ilgili birkaç sorun vardır. Birincisi, büyük ve yeni çalışan türleri eklendiğinde büyüyecek. İkincisi, açıkça birden fazla şey yapar. Üçüncüsü, Tek Sorumluluk İlkesini (SRP) ihlal ediyor çünkü değişmesi için birden fazla neden var . [benimkini vurgula]

İlk olarak, SRP'nin sınıflar için tanımlandığını düşündüm, ancak fonksiyonlar için de geçerli olduğu ortaya çıktı. İkincisi, bu fonksiyonun değişmek için birden fazla nedeni var mı? Değiştiğini sadece Çalışan değişikliği nedeniyle görebiliyorum.


5
Bu, polimorfizm için bir ders kitabı vakası gibi görünüyor.
wchargin

Bu çok ilginç bir konu. Bu soruna aşağıdaki çözümü ekleme şansınız var mı? Her çalışan sınıfı bir calculatePay fucntion koymak seggust ama şimdi kötü çünkü her çalışan sınıfı şu şekilde değiştirilebilir: 1. Ödeme hesaplamaları. 2. sınıfa daha fazla özellik ekleme vb.
Stav Alfi

Yanıtlar:


13

Tek Sorumluluk İlkesinin sıklıkla gözden kaçırılan bir ayrıntısı, "değişim nedenlerinin" kullanım senaryosu aktörleri tarafından gruplandırılmasıdır ( burada tam bir açıklama görebilirsiniz ).

Bu nedenle, örneğinizde, calculatePayher yeni çalışan türü gerektiğinde yöntemin değiştirilmesi gerekecektir. Bir tür çalışanın diğeriyle ilgisi bulunmayabileceğinden, bu değişiklikleri bir arada tutarsanız prensip ihlal edilebilir, çünkü değişiklik sistemdeki farklı kullanıcı gruplarını (veya kullanım örneği aktörlerini) etkileyecektir.

Şimdi, ilkenin işlevler için geçerli olup olmadığı hakkında: Tek bir yöntemde bir ihlali olsa bile, bir sınıfı birden fazla nedenden ötürü değiştiriyorsunuzdur, bu yüzden hala SRP ihlalidir.


1
Bağlantılı youtube videosunu izlemeye çalıştım, ancak 10 dakika sonra kullanım senaryosu aktörleri tarafından gruplandırmadan bahsetmeden vazgeçtim. İlk 6 dakika, görünürde bir sebep olmaksızın entropi ile dolup taşıyor. Videoda bunu tartışmaya başladığı bir yer verdiyseniz, yardımcı olacaktır.
Michael Shaw

@MichaelShaw 10:40 den izlemeyi deneyin. Bob Amca, kodun "farklı insanlar nedeniyle farklı nedenlerle değişeceğini" belirtiyor. Sanırım MichelHenrich'in bizi işaret etmeye çalıştığı şey bu olabilir.
Enrique

Çoğunluğu açıklığa kavuşturulması gereken şeyle ilgili olmayan 50 dakikalık tüm youtube videosunu izlemeyi bitirdi. Saat 16: 00'da o konudan çoktan geçtiğini fark ettim ve hiçbir zaman konuya geri dönmedi. "Açıklama" aslında buna dayanır: SRP'deki "sorumluluk", "değişik değişiklik nedenleri" anlamına gelmez, bu da gerçekten "farklı insanların isteği üzerine değişiklikler" anlamına gelir; msgstr "insanların oynadığı farklı roller isteği". "Açıklama" hiçbir şeyi netleştirmez, belirsiz bir kelimeyi diğeriyle değiştirir.
Michael Shaw

2
@MichaelShaw kitaptaki alıntıda olduğu gibi, farklı çalışan türlerini tanıtmanız gerekiyorsa, Çalışan sınıfını değiştirmeniz gerekir. Farklı çalışan türlerinin ödenmesinden farklı roller sorumlu olabilir, bu nedenle bu durumda, Çalışan sınıfı birden fazla rol için değiştirilmelidir, bu nedenle SRP ihlali.
MichelHenrich

1
@MichaelShaw evet, haklısın - SRP kuruluşun nasıl organize edildiğine bağlı. Bu yüzden tüm yorumlarıma "may" veya "might" ekliyorum :). Bununla birlikte, bu durumlarda bile, kod SRP'yi ihlal etmese de, kesinlikle OCP'yi ihlal eder.
MichelHenrich

3

176. sayfada 12.Bölüm: Ortaya Çıkma, başlıklı bölümde Asgari Sınıflar ve Yöntemler , bir miktar düzeltme sağlayarak, şunları belirterek:

Sınıflarımızı ve yöntemlerimizi küçültmek için çok fazla küçük sınıf ve yöntem oluşturabiliriz. Bu kural, fonksiyonumuzu ve sınıf sayımlarımızı da düşük tuttuğumuzu gösteriyor

ve

Yüksek sınıf ve yöntem sayıları bazen anlamsız dogmatizmin sonucudur.

Açıkçası, SRP'yi takip etmek için calculatePay()yukarıdaki gibi mükemmel ince masum küçük yöntemleri parçalamak için dogmatizmden bahsediyor .


3

Bay Martin, SRP'yi bir işleve uyguladığında, SRP tanımını dolaylı olarak genişletmektedir. SRP genel bir prensibin OO'ya özgü bir ifadesi olduğundan ve işlevlere uygulandığında iyi bir fikir olduğu için, bununla ilgili bir sorun görmüyorum (ancak açıkça tanım).

Ben de değiştirmek için birden fazla neden görmüyorum ve SRP'yi "sorumluluklar" veya "değişim nedenleri" açısından düşünmenin faydalı olduğuna inanmıyorum. Esasen SRP'nin ele aldığı şey, yazılım varlıklarının (işlevler, sınıflar, vb.) Bir şey yapması ve iyi yapmasıdır.

Tanımıma bir göz atarsanız, SRP'nin normal ifadelerinden daha az belirsiz değildir. SRP'nin olağan tanımlarıyla ilgili sorun, çok belirsiz olmaları değil, aslında belirsiz olan bir şey hakkında çok spesifik olmalarıdır.

Ne yaptığına bakarsanız calculatePay, açıkça tek bir şey yapıyor: türe göre gönderme. Java, tür tabanlı dağıtım yapmanın yerleşik yollarına sahip olduğundan calculatePay, yetersiz ve deyimsiz olduğundan, yeniden yazılmalıdır, ancak belirtilen nedenlerle değil.


-2

Haklısın @Enrique. Sınıfın bir işlevi veya yöntemi ne olursa olsun, SRP bu kod bloğunda yalnızca bir şey yaptığınız anlamına gelir.

'Değiştirme nedeni' ifadesi bazen biraz yanıltıcı olabilir, ancak değiştirirseniz calculateSalariedPayveya calculateHourlyPaynumaralandırmanız Employee.typebu yöntemi değiştirmeniz gerekir.

Örneğinizde işlev:

  • çalışanın türünü kontrol eder
  • parayı türe göre hesaplayan başka bir işlevi çağırır

Bence bu doğrudan bir SRP ihlali değildir, çünkü Çalışan ve yöntemler zaten varsa, anahtar durumlar ve çağrılar daha kısa yazılamaz. Her neyse, açık bir kapalı-kapalı prensibi (OCP) ihlalidir, çünkü çalışan türlerini eklerseniz 'case' ifadelerini eklemeniz gerekir, bu yüzden kötü bir uygulamadır: refactor.

'Para'nın nasıl hesaplanması gerektiğini bilmiyoruz, ancak en kolay yol Employeearayüz ve bazı somut uygulamalara sahip olmaktır.getMoney yöntemlerle . Bu durumda, tüm fonksiyon gereksizdir.

Hesaplamak daha karmaşıksa,% 100 SRP olmayan ziyaretçi kalıbı da kullanılabilir, ancak bir anahtar durumundan daha fazla OCP.


2
İşlevin yaptığı 2 şeyi nasıl listeleyebileceğinizden emin değilim, ancak bunun bir SRP ihlali olmadığını söyleyin.
JeffO

@JeffO: Bu 2 şey değil, bu bir şeyin 2 bölümü: türe göre uygun işlevi çağırmak.
Michael Shaw
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.