Tek Sorumluluk İlkesini kullanırken, “sorumluluk nedir?”


198

"Tek Sorumluluk İlkesi" nin "sadece bir şey yaptığı" anlamına gelmediği çok açık görünüyor. Bunun için yöntemler var.

public Interface CustomerCRUD
{
    public void Create(Customer customer);
    public Customer Read(int CustomerID);
    public void Update(Customer customer);
    public void Delete(int CustomerID);
}

Bob Martin, “sınıfların değişmesi için tek bir neden olması gerektiğini” söylüyor. Ancak, SOLID için yeni bir programcıysanız aklınızı sarmak zor.

Sorumlulukların iş ünvanları gibi olduğunu önerdiğim başka bir soruya cevap yazdım ve konuyu açıklamak için bir restoran metaforu kullanarak bu konuda dans ettim. Fakat bu yine de birisinin sınıflarının sorumluluklarını tanımlamak için kullanabileceği bir dizi ilkeyi ifade etmiyor.

Peki nasıl yapıyorsun? Her sınıfın hangi sorumluluklara sahip olduğunu nasıl belirlersiniz ve SRP bağlamında bir sorumluluğu nasıl tanımlarsınız?


28
Kod İncelemeye gönderin ve paramparça olun :-D
Jörg W Mittag

8
@ JörgWMittag Hey, şimdi insanları korkutma :)
Flambino

118
Tecrübeli üyelerden gelen bu gibi sorular, tutmaya çalıştığımız kural ve ilkelerin hiçbir şekilde doğrudan veya basit olmadığını göstermektedir . Onlar iyi bir kurallar dizisinin olması gerektiği gibi, kendileriyle çelişkili ve mistik . Ve böyle soruların akıllıca alçakgönüllülüğüne inanmak ve umutsuzca aptallık duyanlara umut vermek istiyorum. Sağol Robert!
svidgen

41
Acaba bu soru reddedilir mi, + eğer bir noob tarafından gönderilmiş olsaydı hemen tekrarlandı mı diye işaretlendi mi :)
Andrejs

9
@ rmunn: ya da başka bir deyişle - büyük rep daha fazla temsilci çeker, çünkü kimse stackexchange'deki temel önyargıyı iptal etmedi
Andrejs

Yanıtlar:


117

Başınızı bunun etrafına sarmanın bir yolu, gelecekteki projelerdeki potansiyel ihtiyaç değişikliklerini hayal etmek ve bunları gerçekleştirmek için ne yapmanız gerektiğini kendinize sormaktır.

Örneğin:

Yeni iş gereksinimi: Kaliforniya'da bulunan kullanıcılar özel bir indirim kazanıyor.

"İyi" değişim örneği: İndirimleri hesaplayan bir sınıftaki kodu değiştirmem gerekiyor.

Kötü değişikliklere örnek: Kullanıcı sınıfındaki kodu değiştirmem gerekiyor ve bu değişikliğin, İndirim, numaralandırma ve yönetim gibi indirimlerle hiçbir ilgisi olmayan sınıflar da dahil olmak üzere, Kullanıcı sınıfını kullanan diğer sınıflar üzerinde basamaklı bir etkisi olacak.

Veya:

Yeni işlevsel olmayan gereksinim: SQL Server yerine Oracle kullanmaya başlayacağız

İyi değişikliklere örnek: Yalnızca, verilerin DTO'larda nasıl sürdürüleceğini belirleyen veri erişim katmanındaki tek bir sınıfı değiştirmeniz yeterlidir.

Kötü değişiklik: Tüm iş katmanı sınıflarımı değiştirmem gerekiyor, çünkü bunlar SQL Server'a özgü bir mantık içeriyor.

Buradaki düşünce gelecekteki potansiyel değişikliklerin ayak izini en aza indirerek, kod değişikliklerini değişim alanı başına bir kod alanıyla sınırlandırmaktır.

En azından, sınıflarınız mantıksal kaygıları fiziksel kaygılardan ayırmalıdır. Örneklerin büyük bir kümesi bulunabilir System.IOad: orada biz fiziksel akışların (örneğin bir çeşitli bulabilirsiniz FileStream, MemoryStreamya da NetworkStream) ve çeşitli okuyucu ve yazar ( BinaryWriter, TextWritermantıksal düzeyde) bu işe. Onları bu şekilde ayırarak, biz combinatoric patlama kaçının: yerine ihtiyaç duyan FileStreamTextWriter, FileStreamBinaryWriter, NetworkStreamTextWriter, NetworkStreamBinaryWriter, MemoryStreamTextWriter, ve MemoryStreamBinaryWriter, sadece yazar ve akış kanca ve istediğini olabilir. Daha sonra, XmlWriterhafıza, dosya ve ağ için ayrı ayrı uygulamaya gerek kalmadan bir ek ekleyebiliriz .


34
İleriyi düşünmekle aynı fikirdeyim, YAGNI gibi prensipler var ve TDD gibi metodolojiler bunun aksini gösteriyor.
Robert Harvey,

87
YAGNI bize bugün ihtiyaç duymadığımız şeyleri yapmamamızı söylüyor. Bir şeyi genişletilebilir şekilde inşa etmemeyi söylemez. Ayrıca “yazılım varlıklarının (sınıflar, modüller, fonksiyonlar vb.) Uzatma için açık, ancak değişiklik için kapalı olması gerektiğini” açık / kapalı ilkesine bakın .
John Wu

18
@JohnW: Yalnızca YAGNI yorumunuz için +1. Ben YAGNI olduğunu insanlara anlatmak için ne kadar inanamıyorum değil neyi SRP ve Kapalı müdürler için hedefliyoruz Açık / ironik çok tersi - değiştirmek tepki olamaz sert, esnek olmayan bir sistem inşa etmek bir bahane.
Greg Burghardt

36
@JohnWu: Ben katılmıyorum, YAGNI bize bugün tam olarak ihtiyaç duymadığımız şeyleri yapmamamızı söylüyor. Örneğin, okunabilirlik ve testler bir programın her zaman "bugün" ihtiyaç duyduğu bir şeydir, bu nedenle YAGNI hiçbir zaman yapı ve enjeksiyon noktaları eklememek için bir bahane değildir. Bununla birlikte, "genişletilebilirlik", faydaların "bugün" açık olmadığı için önemli bir maliyet eklediği anda, YAGNI, bu tür genişletilebilirlikten kaçınmak anlamına gelir;
Doktor Brown

9
@JohnWu SQL 2008'den 2012'ye geçtik. Değiştirilmesi gereken toplam iki sorgu vardı. Ve SQL Auth'ten güvenilir? Neden bu bir kod değişikliği bile olsa; config dosyasındaki connectionString'in değiştirilmesi yeterli. Yine, YAGNI. YAGNI ve SRP bazen endişe vericidir ve hangisinin daha iyi maliyet / faydaya sahip olduğuna karar vermeniz gerekir.
Andy,

76

Pratik olarak konuşursak, değişmesi muhtemel olan şeyler sorumlulukları sınırlar . Dolayısıyla, ne yazık ki, sorumluluk teşkil eden bir şeye ulaşmanın bilimsel ya da formüllü bir yolu yoktur. Bu bir yargılama çağrısı.

Bu , deneyiminizde neyin değişebileceği ile ilgili.

Prensip dilini hiperbolik, edebi, gayretli bir öfke içinde uygulama eğilimindeyiz. Biz onlar çünkü sınıfları bölmek eğiliminde olabilir değiştirebilir veya basitçe bize sorunları yıkmak yardımcı çizgisinde. (İkinci sebep doğası gereği kötü değil .) Ancak, SRP kendi iyiliği için mevcut değil; sürdürülebilir bir yazılım oluşturmak için hizmette .

Dolayısıyla, eğer bölümler muhtemel değişikliklerden etkilenmiyorsa, YAGNI daha uygunsa , SRP 1'e gerçekten hizmet etmiyorlar . Her ikisi de aynı nihai amaca hizmet eder. Ve her ikisi de yargılama meselesidir - umarım mevsimsel yargılama.

Bob Amca bunu yazdığında, "değişikliği isteyen" anlamında "sorumluluk" düşünmemizi önerir. Başka bir deyişle, A Partisinin işlerini kaybetmesini istemiyoruz, çünkü B Partisi bir değişiklik istedi.

Bir yazılım modülü yazdığınızda, değişiklik talep edildiğinde, bu değişikliklerin yalnızca tek bir kişiden veya daha da dar bir şekilde tanımlanmış tek bir iş işlevini temsil eden sıkıca birleştirilmiş bir grup insandan kaynaklanabileceğinden emin olmak istersiniz. Modüllerinizi bir bütün olarak organizasyonun karmaşıklıklarından izole etmek ve sistemlerinizi her bir modülün sadece bir iş fonksiyonunun gereksinimlerinden sorumlu (cevap verecek) şekilde tasarlayacaksınız. ( Bob Amca - Tek Sorumluluk İlkesi )

İyi ve deneyimli geliştiriciler, değişikliklerin muhtemel olduğu anlayışına sahip olacaktır. Ve bu zihinsel liste endüstri ve organizasyona göre bir miktar değişecektir.

Özel başvurunuzda, özel organizasyonunuzda sorumluluk oluşturan, nihayetinde tecrübeli bir yargılama meselesidir . Değişmesi muhtemel olanla ilgili. Ve bir anlamda, modülün dahili mantığına sahip olan hakkında .


1. Açık olmak, bu onların kötü bölümler olduğu anlamına gelmez . Kod okunabilirliğini önemli ölçüde artıran büyük bölümler olabilirler . Bu sadece onların SRP tarafından yönlendirilmediği anlamına gelir.


11
En iyi cevap, ve aslında Bob Amca'nın düşüncelerini aktarıyor. Neyin değişmesi muhtemel ise, herkes G / Ç üzerinde büyük bir şey yapar, "veritabanını değiştirirsek ne olur?" ya da "XML'den JSON'a geçersek ne olur?" Bence bu genellikle yanlış yönlendirilmiş. Asıl soru, "bu int değerini bir şamandıra olarak değiştirmemiz, bir alan ekleyip bu Dizgiyi bir Dizin Listesinde değiştirmemiz gerekirse?" Olmalı.
user949300,

2
Bu aldatmaktır. Tek başına sorumluluk tek başına "izolasyonun değiştirilmesi" için önerilen bir yoldur. Sorumluluğu "tek" tutmak için değişiklikleri izole etmeniz gerektiğini açıklamak, bunun nasıl yapılacağını önermez, sadece gereksinimin kökenini açıklar.
Basilevs

6
@Basilevs Bu cevabın içinde gördüğünüz eksiklikten bahsetmeye çalışıyorum - Bob Amca'nın cevabından bahsetmiyorum! Ancak, belki de SRP'nin “bir değişimin” sadece 1 sınıfı etkilemesini sağlamakla ilgili olmadığını açıklığa kavuşturmalıyım . Bu, her sınıfın sadece "tek bir değişikliğe" cevap vermesini sağlamakla ilgilidir. ... Her sınıftan tek bir ok sahibine oklarını çizmeye çalışmakla ilgili. Her sahibinden tek bir sınıfa değil.
svidgen

2
Pragmatik bir yanıt verdiğiniz için teşekkür ederiz! Bob Amca bile, Çevik Mimari'de SOLID ilkelerine çok sıkı bağlı kalmaya karşı uyardı . Ben kullanışlı alıntı yok ama temelde bölme sorumlulukları gereği kodunuzu ve tüm soyutlama bir maliyetle geliyor soyutlama düzeyini artırdığını söylüyor, bu yüzden emin olun fayda ağır basar SRP (ya da diğer ilkelerini) Aşağıdakilerden maliyeti daha fazla soyutlama ekleyerek. (sonraki yorum devam ediyor)
Michael L.

4
Biz Bu nedenle gerektiği gibi erken müşterinin önünde ürünü koyup sıklıkta makul olduğu gibi bu yüzden onlar bizim tasarım değişiklikleri zorlar ve biz alanlardır görebilirsiniz muhtemel bu üründe değiştirmek için. Ayrıca kendimizi her türlü değişiklikten koruyamayacağımız konusunda uyarıyor . Herhangi bir uygulama için, belirli değişikliklerin yapılması zor olacaktır. Bunların gerçekleşmesi en muhtemel değişiklikler olduğundan emin olmalıyız.
Michael L.

29

"Sınıfların değişmesi için tek bir sebep olmalı" izini sürüyorum.

Benim için bu, ürün sahibimin bulabileceği harebrained şemaları düşünmek anlamına gelir ("Cep telefonunu desteklemeliyiz!", "Buluta gitmeliyiz!", "Çinlileri desteklemeliyiz!"). İyi tasarımlar, bu planların etkisini daha küçük alanlara sınırlar ve bunların gerçekleştirilmesini nispeten kolay hale getirir. Kötü tasarımlar, çok fazla koda gitme ve bir sürü riskli değişiklik yapma anlamına gelir.

Tecrübe, bu çılgın planların gerçekleşme ihtimalini doğru bir şekilde değerlendirdiğim için bulduğum tek şey - çünkü birini kolaylaştırmak diğer ikisini zorlaştırabilir - ve bir tasarımın iyiliğini değerlendirir. Deneyimli programcılar, kodu değiştirmek için ne yapmaları gerektiğini, eşekleri onları ısırmak için etrafta yatanları ve hangi hilelerin işleri kolaylaştırdığını hayal edebilir. Tecrübeli programcılar, ürün sahibi çılgınca şeyler istediğinde ne kadar berbat olduklarını iyi hissettirir.

Pratik olarak, birim testlerinin burada yardımcı olduğunu buldum. Eğer kodunuz esnek değilse, test edilmesi zor olacaktır. Alaycı veya diğer test verilerini enjekte edemiyorsanız, muhtemelen bu SupportChinesekodu enjekte edemezsiniz .

Bir diğer kaba ölçüm ise asansör perdesidir. Geleneksel asansör perdeleri "bir yatırımcı ile asansördeyseniz, onu bir fikirle satabilir misiniz?" Yeni başlayanların ne yaptıklarının basit ve kısa açıklamalarına sahip olmaları gerekir - odaklarının ne olduğu. Aynı şekilde, sınıfları (ve fonksiyonları) onlar ne basit bir açıklama olmalıdır yapmak . "Bu sınıf, bu özel senaryolarda kullanabileceğiniz şekilde bazı fubarlar uygular" değil. Başka bir geliştiriciye söyleyebileceğiniz bir şey: "Bu sınıf kullanıcılar oluşturur". Diğer geliştiriciler bu iletişim kuramaz ise, konum gidiş böcek alır.


Bazen dağınık bir değişiklik olacağını düşündüğünüz şeyi uygulamaya gidiyorsunuz ve basit çıkıyor ya da küçük bir refaktör basitleştiriyor ve aynı zamanda kullanışlı işlevler ekliyor. Ama evet, genellikle sorunların geldiğini görebilirsiniz.

16
"Asansör perdesi" fikrinin büyük bir savunucusuyum. Bir sınıfın cümle içinde ne yaptığını açıklamak zorsa, riskli bölgedesiniz.
Ivan

1
Önemli bir noktaya değiniyorsunuz: Bu çılgın planların olasılığı bir proje sahibinden diğerine büyük ölçüde değişiyor. Sadece genel deneyiminize değil, proje sahibini ne kadar iyi tanıdığınıza da güvenmelisiniz. Sprintlerimizi bir haftaya kadar kesmek isteyen insanlar için çalıştım ve hala sprint ortasında yön değiştirmekten kaçınamadım.
Kevin Krumwiede

1
Belirgin faydalara ek olarak, kodunuzu "asansör perdeleri" kullanarak belgelemek de, birden fazla sorumluluğu ortaya çıkarmak için yararlı bulduğum doğal dili kullanarak kodunuzun ne yaptığını düşünmenize yardımcı olur.
Alexander

1
@KevinKrumwiede "Kafası kesilmiş tavuk koşturuyor" ve "Yabani Kaz Chase" metodolojileri bunun için!

26

Kimse bilmiyor. Ya da en azından bir tanım üzerinde anlaşamıyoruz. SPR'yi (ve diğer SOLID ilkelerini) oldukça tartışmalı kılan şey budur.

Sorumluluğun ne olduğunu veya ne olmadığını anlayabileceğimi, yazılım geliştiricisinin kariyeri boyunca öğrenmesi gereken becerilerden biri olduğunu savunuyorum. Ne kadar çok kod yazar ve gözden geçirirseniz, bir şeyin tek mi, yoksa birden fazla sorumluluk mu olduğunu belirlemek için o kadar fazla deneyim edinmeniz gerekir. Ya da tek bir sorumluluk, kodun ayrı bölümleri arasında kırılırsa.

SRP'nin temel amacının zor kural olmadığını söylemek isterim. Koddaki uyuma dikkat etmemiz gerektiğini ve hangi kodun uyuşup uyuşmadığını belirlemek için her zaman bilinçli bir çaba göstermemizi hatırlatmaktır.


20
Yeni programcılar, SOLID'i, olmadığı gibi bir yasalarmış gibi ele alma eğilimindedir. İnsanların sınıf tasarımında daha iyi olmalarına yardımcı olmak için sadece iyi fikirlerin bir gruplanmasıdır. Ne yazık ki, insanlar bu ilkeleri çok fazla ciddiye alma eğilimindedir; Geçenlerde SOLID'i iş gereksinimlerinden biri olarak gösteren bir iş ilanı gördüm.
Robert Harvey,

9
Son paragraf için +42. @RobertHarvey'in dediği gibi, SPR, SOLID ve YAGNI gibi şeyler “ mutlak kurallar ” olarak değil, “iyi tavsiye” nin genel ilkeleri olarak alınmalıdır . Öneriler (ve diğerleri) arasında tavsiye bazen çelişkili olacaktır, ancak bu tavsiyenin dengelenmesi (katı kurallara uyulmasının aksine) (zamanla, deneyiminiz büyüdükçe) daha iyi yazılımlar üretmenizi sağlayacaktır. Yazılım geliştirmede yalnızca bir "mutlak kural" olmalıdır: " mutlak kurallar yoktur ".
TripeHound

Bu, SRP'nin bir yönüyle ilgili çok iyi bir açıklamadır. Ancak, SOLID ilkeleri zor kurallar olmasa bile, hiç kimse ne anlama geldiğini anlamıyorsa çok da değerli değildir - "hiç kimsenin bilmediği" iddiası gerçekten doğruysa! ... anlaşılmaları zorlaşır. Herhangi bir beceride olduğu gibi , iyiyi daha az iyiden ayıran bir şey var ! Ama ... "kimse bilmiyor", daha fazla tehlikeli bir ayin yapar. (Ve bunun
SOLID'in

3
"Kimse bilmiyor" derken, umarım @Euphoric , her kullanım durumu için işe yarayacak kesin bir tanım olmadığı anlamına gelir . Bir dereceye kadar yargı gerektiren bir şey. Sorumluluklarınızın nerede yatacağını belirlemenin en iyi yollarından birinin hızlı bir şekilde yinelenmek ve kod tabanınızın size bildirmesini sağlamak olduğunu düşünüyorum . Kodunuzun kolayca bakımı yapılamayacağını "kokuyor" arayın. Örneğin, tek bir iş kuralında yapılan değişiklik, görünüşte alakasız sınıfları etkileyerek basamaklandırmayı etkilemeye başladığında, muhtemelen bir SRP ihlali yaşarsınız.
Michael L.

1
Ben yürekten ikinci @TripeHound ve tüm bu "kuralların" gelişimin Tek Gerçek Dinini tanımlamak için varolamadıklarını, ancak sürdürülebilir bir yazılım geliştirme olasılığını arttırdıklarını belirten diğerleri var. Eğer sürdürülebilir yazılımı nasıl geliştirdiğini, kalitesini artırdığını ya da kalkınmanın verimliliğini arttırdığını açıklayamazsanız, "en iyi uygulamayı" takip etmekten çekinmeyin ..
Michael L.

5

"Sorumluluk" teriminin metafor olarak faydalı olduğunu düşünüyorum çünkü yazılımın ne kadar iyi organize edildiğini araştırmak için yazılımı kullanmamıza izin veriyor. Özellikle, iki prensibe odaklanacağım:

  • Sorumluluk otorite ile orantılıdır.
  • Aynı şeyden iki kuruluş sorumlu olmamalıdır.

Bu iki ilke, sorumluluğu anlamlı bir şekilde üstlenmemize izin verir çünkü birbirlerini mahvederler. Sizin için bir şeyler yapması için bir kod parçasını yetkilendiriyorsanız, yaptıklarından sorumlu olması gerekir. Bu, bir sınıfın büyümesi gerekliliğini doğurarak, daha geniş ve daha geniş kapsamlara “değişmenin bir nedeni” olarak genişler. Bununla birlikte, işleri genişlettikçe, doğal olarak aynı şeyden birden çok kişinin sorumlu olduğu durumlarla karşılaşmaya başlarsınız. Bu, gerçek hayattaki sorumluluk alanlarıyla doludur, bu yüzden kesinlikle kodlamada da bir sorun teşkil eder. Sonuç olarak, bu ilke, sorumluluğu çoğaltılmamış parsellere aktarırken kapsamın daralmasına neden olur.

Bu ikisine ek olarak, üçüncü bir prensip makul görünüyor:

  • Sorumluluk devredilebilir

Yeni çıkmış bir program düşünün ... boş bir sayfa. İlk başta, bir bütün olarak program olan tek bir varlığa sahipsiniz. Her şeyden ... sorumlu. Doğal olarak bir noktada fonksiyonlara veya sınıflara sorumluluk devretmeye başlayacaksınız. Bu noktada, ilk iki kural bu sorumluluğu dengelemeniz için sizi zorlar. Üst düzey program hala genel çıktıdan sorumlu, tıpkı bir yöneticinin kendi ekibinin üretkenliğinden sorumlu olduğu gibi, ancak her bir alt kuruluşun sorumluluğu ve bu sorumluluğu yerine getirme yetkisi verildi.

Ek bir avantaj olarak, bu SOLID'i, özellikle yapılması gereken herhangi bir kurumsal yazılım geliştirme ile uyumlu hale getirir. Gezegendeki her şirketin sorumluluğu devretme konusunda bir fikri vardır ve hepsi aynı fikirde değildir. Yazılımınızdaki sorumluluğu şirketinizin kendi delegasyonunu hatırlatan bir şekilde devrederseniz, gelecekteki geliştiricilerin bu şirkette işlerinizi nasıl yürüttüğünü hızlandırması çok daha kolay olacaktır.


Bunun tamamen açıkladığından% 100 emin değilim. Ancak, “otorite” ile ilgili “sorumluluk” u açıklamanın, onu ifade etmenin anlamlı bir yolu olduğunu düşünüyorum! (+1)
svidgen

Pirsig, “Sorunlarını makineye koymaya meyilli” dedi, bu beni duraklattı.

@nocomprende Ayrıca, güçlü yanlarınızı makineye dahil etme eğilimindesiniz. Güçlü ve güçsüzlüğün aynı şeyler olduğunda, o zaman ilginçleştiğini iddia ediyorum.
Cort Ammon

5

Gelen bu konferansta Yale, Bob amca bu verir komik örneği:

Resim tanımını buraya girin

EmployeeDeğişim için üç nedene, üç değişim gereksinim kaynağına sahip olduğunu ve bu mizahi ve yanak dilini , ancak yine de açıklayıcı bir açıklama yaptığını söylüyor :

  • Eğer CalcPay()yöntemi hata vardır ve ABD Doları şirkete milyonlarca maliyeti, CFO seni kovarım .

  • Eğer ReportHours()yöntemi hata vardır ve ABD Doları şirkete milyonlarca maliyeti, COO seni kovarım .

  • WriteEmmployee() Yönteminde çok fazla veri silinmesine neden olan bir hata varsa ve şirketin milyon ABD doları tutarında bir maliyeti varsa, CTO sizi kovacaktır .

Bu yüzden , üç farklı C seviyesine sahip olmak, sizi aynı sınıftaki masraflı hatalardan dolayı potansiyel olarak kovar , sınıfın çok fazla sorumluluğu olduğu anlamına gelir.

SRP'nin ihlalini çözen ancak henüz videoda gösterilmeyen DIP'in ihlalini çözmek zorunda olan bu çözümü veriyor.

Resim tanımını buraya girin


Bu örnek, yanlış sorumluluklara sahip bir sınıfa benziyor .
Robert Harvey,

4
@RobertHarvey Bir sınıfın çok fazla sorumluluğu varsa, bu ekstra sorumlulukların yanlış sorumluluk olduğu anlamına gelir .
Tulains Córdova

5
Ne dediğini duyuyorum ama çekici bulmuyorum. Çok fazla sorumluluğu olan bir sınıf ile hiç ilgisi olmayan bir şeyi yapan bir sınıf arasında bir fark vardır. Aynı gelebilir, ama değil; yer fıstığı saymak, ceviz demekle aynı şey değildir. Bob Amca'nın ilkesi ve Bob Amca'nın örneği, ancak yeterince açıklayıcı olsaydı, bu soruya hiç ihtiyacımız olmazdı.
Robert Harvey,

@RobertHarvey, fark nedir? Bu durumlar benim için izomer görünüyor.
Paul Draper

3

Bence "değişme nedenlerinden" daha iyi şeyleri bölmenin daha iyi bir yolu, iki (veya daha fazla) eylem gerçekleştirmesi gereken kodun ayrı bir nesne referansı tutması gerekmesinin gerekip gerekmediğini düşünerek başlamaktır. Her bir eylem için ve bir eylemi gerçekleştirebilecek, ancak diğerini gerçekleştiremeyen ortak bir nesneye sahip olmanın faydalı olup olmadığı.

Her iki soruya da cevaplar evet ise, bu eylemlerin ayrı sınıflar tarafından yapılması gerektiğini gösterir. Her iki soruya da verilen cevaplar hayır ise, bu, kamusal açıdan bir sınıf olması gerektiğini; Bunun için kodun hantal olması halinde, dahili olarak özel sınıflara bölünebilir. İlk sorunun cevabı hayır, ama ikinci evet ise, her eylem için ayrı bir sınıf olmalıdır artı başkalarının örneklerini başvurular içeren bir kompozit sınıfa.

Eğer bir yazar kasa tuş takımı için ayrı sınıflara sahipse, bip sesi, sayısal okuma, makbuz yazıcısı ve kasa çekmecesi varsa ve tam bir kasa için bileşik sınıf yoksa, bir işlemi işleme alması gereken kod yanlışlıkla işleme alınabilir bir makinenin tuş takımından girdi alan, ikinci bir makinenin bip sesinden gürültü üreten, üçüncü bir makinenin ekranındaki sayıları gösteren, dördüncü bir makinenin yazıcısına bir makbuz basar ve beşinci bir makinenin nakit çekmecesini açar. Bu alt işlevlerin her biri, ayrı bir sınıf tarafından faydalı bir şekilde ele alınabilir, ancak bunlara katılan bir bileşik sınıf da olmalıdır. Bileşik sınıf, kurucu sınıflara mümkün olduğu kadar mantık vermeli,

Biri, her bir sınıfın "sorumluluğunun" ya bazı gerçek mantıkları dahil etmek olduğunu ya da bunu yapan diğer birçok sınıf için ortak bir bağlantı noktası sağlamak olduğunu söyleyebilir, ancak önemli olan öncelikle müşteri kodunun bir sınıfı nasıl görmesi gerektiğine odaklanmaktır. İstemci kodunun bir şeyi tek bir nesne olarak görmesi mantıklıysa, istemci kodu onu tek bir nesne olarak görmelidir.


Bu sağlam bir tavsiye. Sorumlulukları yalnızca SRP'den daha fazla kritere göre paylaştığınızı belirtmek faydalı olabilir.
Jørgen Fogh

1
Araba benzetmesi: Bir başkasının tankında ne kadar gaz olduğunu bilmem ya da bir başkasının sileceklerini açmak istememe gerek yok. (ama internetin tanımı budur) (Şşş! hikayeyi mahvedeceksin)

1
@nocomprende - "Başka birinin deposunda ne kadar gaz olduğunu bilmeme gerek yok" - ailenin hangi otomobilini bir sonraki seyahatiniz için "ödünç almaya" karar vermeye çalışan bir genç olmadığınız sürece ...;)
alephzero

3

SRP'nin doğru olması zor. Çoğunlukla kodunuza 'işler' vermek ve her bir parçanın açık sorumlulukları olduğundan emin olmaktan ibarettir. Gerçek hayatta olduğu gibi, bazı durumlarda işi insanlar arasında bölmek oldukça doğal olabilir, ancak diğer durumlarda, özellikle onları (ya da işi bilmiyorsanız) gerçekten zor olabilir.

Her zaman önce sadece basit kod yazmanızı öneriyorum , sonra biraz yeniden yönlendirin: Kodun bir süre sonra doğal olarak nasıl kümelendiğini görme eğiliminde olacaksınız. Kod (veya insanları) ve yapılacak işi bilmeden önce sorumlulukları zorlamanın bir hata olduğunu düşünüyorum.

Dikkat edeceğiniz şeylerden biri, modülün çok fazla yapmaya başladığı ve hata ayıklaması / bakımı zor olduğu durumdur. Bu, yeniden ateşleme zamanı; Ana iş ne olmalı ve başka bir modüle hangi görevler verilebilir? Örneğin, güvenlik kontrollerini ve diğer işleri idare etmeli mi, yoksa önce başka bir yerde güvenlik kontrolleri yapmalı mıydınız yoksa kod daha karmaşık mı olacak?

Çok fazla aktarma kullanın ve yine bir karışıklık olur ... diğer prensiplerde olduğu gibi, bu KISS, YAGNI, vb. Gibi başkalarıyla çatışacak. Her şey bir denge konusu.


SRP sadece Constantine'nin Uyum Yazısı büyük değil mi?
Nick Keighley

Yeterince uzun kod yazarsanız bu kalıpları doğal olarak bulacaksınız, ancak öğrenmeyi isimlendirerek hızlandırabilir ve iletişimde yardımcı olur ...
Christophe Roussy

@NickKeighley Bence uyum, çok büyük değil ama başka bir bakış açısıyla baktı.
sdenham

3

"Tek sorumluluk ilkesi" belki de kafa karıştırıcı bir isimdir. “Değişmenin tek bir nedeni” ilkenin daha iyi bir açıklamasıdır, ancak yanlış anlaşılması kolaydır. Nesnelerin çalışma zamanında durumunu değiştirmesine neden olan şeylerden bahsetmiyoruz. Gelecekte, geliştiricilerin kodu değiştirmek zorunda kalabileceklerini ele alıyoruz.

Bir hatayı düzeltmiyorsak, değişiklik yeni veya değiştirilmiş bir işletme gereksiniminden kaynaklanacaktır. Kodun dışında düşünmek zorunda kalacaksınız ve dış faktörlerin gereksinimlerin bağımsız olarak değişmesine neden olabileceğini hayal etmeniz gerekecek . Söyle:

  • Vergi oranları politik karar nedeniyle değişiyor.
  • Pazarlama tüm ürünlerin isimlerini değiştirmeye karar veriyor
  • UI erişilebilir olması için yeniden tasarlandı
  • Veri tabanı sıkışık olduğundan bazı optimizasyonlar yapmanız gerekir.
  • Bir mobil uygulamayı barındırmanız gerekir
  • ve bunun gibi...

İdeal olarak, farklı sınıfları etkilemek için bağımsız faktörlerin olmasını istersiniz. Örneğin vergi oranları ürün isimlerinden bağımsız olarak değiştiğinden, değişiklikler aynı sınıfları etkilememelidir. Aksi taktirde vergi değişikliği giriş riskini yaşarsınız, ürün adlandırmada bir hata var; bu modüler bir sistemde kaçınılması gereken sıkı bağlantı türüdür.

Dolayısıyla sadece neyin değişebileceğine odaklanmayın - gelecekte akla gelebilecek her şey değişebilir. Bağımsız olarak nelerin değişebileceğine odaklanın . Değişiklikler, farklı aktörler tarafından yaratıldıysa, genellikle bağımsızdır.

İş unvanlarına sahip olan örneğiniz doğru yolda, ancak daha gerçek anlamalısınız! Pazarlama, kodda değişikliklere neden olabilirse ve finansman başka değişikliklere neden olabilirse, bu değişiklikler aynı kodu etkilememelidir, çünkü bunlar kelimenin tam anlamıyla farklı iş ünvanlarıdır ve bu nedenle değişiklikler bağımsız olarak gerçekleşecektir.

Terimi icat eden Bob Amca'ya :

Bir yazılım modülü yazdığınızda, değişiklik talep edildiğinde, bu değişikliklerin yalnızca tek bir kişiden veya daha da dar bir şekilde tanımlanmış tek bir iş işlevini temsil eden sıkıca birleştirilmiş bir grup insandan kaynaklanabileceğinden emin olmak istersiniz. Modüllerinizi bir bütün olarak organizasyonun karmaşıklıklarından izole etmek ve sistemlerinizi her bir modülün sadece bir iş fonksiyonunun gereksinimlerinden sorumlu (cevap verecek) şekilde tasarlayacaksınız.

Özetle: Bir "sorumluluk", tek bir iş fonksiyonunu yerine getirmektedir. Birden fazla oyuncu bir sınıfı değiştirmeniz gerekmesine neden olabilirse, o zaman sınıf muhtemelen bu prensibi ihlal eder.


"Clean Architecture" adlı kitabına göre bu kesinlikle doğru. İş kuralları tek bir kaynaktan ve yalnızca bir kaynaktan gelmelidir. Bu, İK, Operasyonlar ve BT'nin “Tek Sorumluluk” içerisinde formüle etme şartlarını yerine getirmesi gerektiği anlamına gelir. Ve bu ilkedir. +1
Benny Skogberg

2

SOLID programlama ilkelerini açıklayan ve bu ilkeleri izleyen ve izlemeyen kod örnekleri veren iyi bir makale https://scotch.io/bar-talk/solid-the-first-five-principles- of-object-orented- tasarım .

SRP ile ilgili örnekte birkaç şekil sınıfına (daire ve kare) bir örnek ve çoklu şekillerin toplam alanını hesaplamak için tasarlanmış bir sınıf verir.

İlk örneğinde, alan hesaplama sınıfını oluşturur ve çıktısını HTML olarak döndürür. Daha sonra bunun yerine JSON olarak göstermek istediğine karar verir ve alan hesaplama sınıfını değiştirmek zorunda kalır.

Bu örnekteki problem, alan hesaplama sınıfını şekil alanını hesaplamaktan ve bu alanı görüntülemekten sorumludur. Daha sonra, özellikle alanları görüntülemek için tasarlanmış başka bir sınıfı kullanarak bunu yapmak için daha iyi bir yol izler.

Bu basit bir örnektir (ve makaleyi kod snippet'lerine sahip olduğu için daha kolay anlaşılır) ancak SRP'nin ana fikrini göstermektedir.


0

Her şeyden önce, sahip olduğunuz aslında iki ayrı sorun: sınıflarınıza hangi yöntemleri koyacağınız ve arayüz kabartması sorunu.

Arayüzler

Bu arayüze sahipsiniz:

public Interface CustomerCRUD
{
  public void Create(Customer customer);
  public Customer Read(int CustomerID);
  public void Update(Customer customer);
  public void Delete(int CustomerID);
}

Varsayalım ki, CustomerCRUDarayüze uyan birden fazla sınıfınız var (aksi halde arayüz gereksizdir) ve do_crud(customer: CustomerCRUD)uyumlu bir obje içinde yer alan bazı fonksiyonlar . Fakat zaten SRP'yi kırdınız: bu dört farklı işlemi birbirine bağladınız.

Diyelim ki daha sonra veritabanı görünümlerinde çalışacaksınız. Bir veritabanı görünümünde yalnızca bunun Readiçin mevcut yöntem vardır. Ancak do_query_stuff(customer: ???), tam gelişmiş masalarda veya görünümlerde şeffaf olarak çalışan bir fonksiyon yazmak istiyorsunuz ; sonuçta sadece Readyöntemi kullanır .

Öyleyse bir arayüz oluştur

genel Arayüz CustomerReader {genel Müşteri Oku (customerID: int)}

ve CustomerCrudarayüzünüzü şu şekilde değerlendirin:

public interface CustomerCRUD extends CustomerReader
{
  public void Create(Customer customer);
  public void Update(Customer customer);
  public void Delete(int CustomerID);
}

Ama görünürde son yok. Yaratabileceğimiz ancak güncelleyemeyeceğimiz nesneler olabilir, vb. Bu tavşan deliği çok derin. Tek sorumluluk ilkesine bağlı kalmanın tek mantıklı yolu, tüm arayüzlerinizin tek bir yöntem içermesini sağlamaktır . Go aslında bu metodolojiyi gördüğümden, tek bir işlev içeren arayüzlerin büyük çoğunluğuyla izler; iki işlev içeren bir arabirim belirlemek istiyorsanız, ikisini birleştiren beceriksizce yeni bir arabirim oluşturmanız gerekir. Yakında arayüzlerin bir birleşimsel patlama olsun.

Bu karmaşadan kurtulmanın yolu, arayüzler yerine (nominal bir alt tipte olan) yapısal alt tip kullanmaktır (örn. OCaml'de uygulanır). Arayüzleri tanımlamıyoruz; bunun yerine, sadece bir fonksiyon yazabiliriz

let do_customer_stuff customer = customer.read ... customer.update ...

Bu bizim istediğimiz yöntemlerden herhangi biri. OCaml, bu yöntemleri uygulayan herhangi bir nesneye geçebileceğimizi belirlemek için tip çıkarımını kullanacaktır. Bu örnekte, customertipe sahip olduğu belirlenir <read: int -> unit, update: int -> unit, ...>.

Sınıflar

Bu arayüz karışıklığını çözer ; ama yine de çoklu yöntemler içeren sınıfları uygulamak zorundayız. Örneğin, iki farklı sınıflar oluşturmak, gerektiği CustomerReaderve CustomerWriter? Tabloların okunma şeklini değiştirmek istiyorsak (örneğin, verileri aldıktan sonra cevaplarımızı redis olarak önbelleğe alıyoruz), ama şimdi nasıl yazılır? Eğer izlerseniz bu mantıksal sonucuna muhakeme zinciri, sen fonksiyonel programlamaya ayrılmaz kurşun konum :)


4
"Anlamsız" biraz güçlü. "Mistik" veya "Zen" in arkasına geçebilirim. Ancak, anlamsız
svidgen

Yapısal alt tiplemenin neden bir çözüm olduğunu biraz daha açıklayabilir misiniz?
Robert Harvey,

@RobertHarvey Cevabımı önemli ölçüde yeniden yapılandırdım
gardenhead

4
Arabirimleri sadece uygulayan tek bir sınıfım olsa bile kullanırım. Neden? Birim testlerinde alay.
Eternal21

0

Aklımda, aklıma gelen bir SRP'ye en yakın şey kullanım akışıdır. Herhangi bir sınıf için net bir kullanım akışınız yoksa, muhtemelen sınıfınız bir tasarım kokusuna sahiptir.

Bir kullanım akışı, size beklenen (dolayısıyla test edilebilir) bir sonuç verecek olan belirli bir yöntem çağrısı sırasıdır. Temel olarak, IMHO aldığı kullanım durumlarıyla bir sınıf tanımlarsınız, bu nedenle tüm program metodolojisi uygulama üzerindeki arayüzlere odaklanır.


0

Birden fazla gereksinim değişikliğinin gerçekleştirilmesi, bileşeninizin değişmesini gerektirmez .

Fakat ilk bakışta, SOLID'i ilk duyduğunuzda bunu anlamada iyi şanslar.


Ben yorum çok söyleyerek bkz SRP ve YAGNI birbirinden itiraz edebilir, ama YAGN TDD yürütür ben (Goos, Londra Okulu) öğretti düşünmek ve müşterinin bakış açısından benim bileşenleri tasarlamak için. Arayüzlerimi, herhangi bir müşterinin yapmasını isteyeceği en az şeyin ne olduğu ile tasarlamaya başladım . Ve bu alıştırma TDD bilgisi olmadan yapılabilir.

Bob Amca tarafından tarif edilen tekniği seviyorum (ne yazık ki nereden hatırlayamıyorum).

Kendine sor, bu sınıf ne yapıyor?

Cevabınız birini ihtiva mı Ve ya Or

Eğer öyleyse, cevabın o kısmını çıkartın, kendi sorumluluğundadır.

Bu teknik mutlaktır ve @svidgen'in dediği gibi, SRP bir yargı çağrısıdır, ancak yeni bir şey öğrenirken, mutlaklar en iyisidir, sadece her zaman bir şeyler yapmak daha kolaydır . Ayrılmadığınız neden olduğundan emin olun; Eğitimli bir tahmin ve değil nasıl bilmiyorum çünkü. Bu sanat ve tecrübe alıyor.


Bence cevapların çoğu, SRP hakkında konuşurken ayrılmak için bir tartışma yaratıyor gibi görünüyor .

SRP olduğu değil bir değişiklik bağımlılık grafiği aşağı yaymak değil emin olmak için.

Teorik olarak, SRP olmasaydı, hiçbir bağımlılığınız olmazdı ...

Bir değişiklik başvuruda birçok yerde değişikliğe neden olmamalıdır, ancak bunun için başka prensiplerimiz var. Ancak SRP , Açık Kapalı Prensibi iyileştirmektedir . Bu ilke soyutlama hakkında daha fazladır, ancak daha küçük soyutlamaların yeniden yerleştirilmesi daha kolaydır .

Bir bütün olarak KATI öğretirken Yani, öğretmek için dikkatli olmak SRP yapmanıza olanak verir değiştirmek aslında, daha az yazmaya izin verdiğinde, gereksinimler değiştirmek daha az kod yeni kod.


3
When learning something new, absolutes are the best, it is easier to just always do something.- Tecrübelerime göre, yeni programcılar çok dogmatik. Mutlakçılık, düşüncesiz geliştiricilere ve kargo kült programlamasına yol açar. "Sadece bunu yap" demek güzeldir, konuştuğunuz kişinin daha sonra onlara ne öğrettiğinizi öğrenmesi gerekeceğini anladığınız sürece .
Robert Harvey,

@RobertHarvey, Tamamen doğru, dogmatik davranış yaratır ve deneyim kazandıkça öğrenmeniz / öğrenmeniz gerekir . Benim düşüncem bu. Eğer yeni bir programcı, kararlarını gerekçelendirmeksizin yargılama çağrıları yapmaya çalışırsa, sınırsız görünüyor, çünkü işe yaradığında neden işe yaradığını bilmiyorlar. İnsanları aşırıya kaçmasıyla , vasıfsız tahminler yapmak yerine istisnaları aramayı öğretir. Söylediğin her şey mutlakiyetçilikle ilgili doğru, bu yüzden sadece başlangıç ​​noktası olmalı.
Chris Wohlert

@RobertHarvey, Hızlı ve gerçek bir yaşam örneği: Çocuklarınıza her zaman dürüst olmayı öğretebilirsiniz , ancak yaşlandıkça, insanların en dürüst düşüncelerini duymak istemedikleri birkaç istisna gerçekleştireceklerdir. Dürüst olmakla ilgili 5 yaşındaki bir doğru karar vermesini beklemek en iyisidir. :)
Chris Wohlert

0

Buna net bir cevap yok. Her ne kadar soru dar olsa da, açıklamalar değil.

Benim için, eğer istersen, Occam Razor gibi bir şey. Şu anki kodumu karşı ölçmeye çalıştığım bir ideal. Sade ve basit kelimelerle çivilenmek zor. Başka bir metafor, “tek bir konu« gibi soyut, yani kavraması zor bir konu ”olacak. Üçüncü bir tanım, “bir soyutlama düzeyi ile uğraşmaktır”.

Bu pratikte ne anlama geliyor?

Son zamanlarda çoğunlukla iki fazdan oluşan bir kodlama tarzı kullanıyorum:

Aşama I en iyi yaratıcı kaos olarak tanımlanır. Bu aşamada düşünceleri akarken kod yazarım - ham ve çirkin.

Faz II tam tersidir. Bir kasırgadan sonra temizlik yapmak gibidir. Bu en çok çalışmayı ve disiplini alır. Ve sonra kodu tasarımcının bakış açısından inceliyorum.

Çoğunlukla Python'da çalışıyorum, bu daha sonra nesneleri ve sınıfları düşünmeme izin veriyor. Birinci Aşama I - Sadece fonksiyonlar yazarım ve farklı modüllerdeki rastgele rasgele yayınlarım. II . Aşama'da işleri hallettikten sonra, hangi modülün çözümün hangi kısmı ile ilgilendiğine daha yakından bakıyorum. Ve modüller arasında gezinirken, başıma çıkan konular var. Bazı fonksiyonlar tematik olarak ilişkilidir. Bunlar dersler için iyi adaylar . Ve fonksiyonları sınıflara dönüştürdükten sonra - neredeyse girinti ile yapıldı ve python'daki selfparametre listesine ekledi ;) - SRPDiğer modüllere ve sınıflara işlevselliği çıkarmak için Occam's Razor gibi kullanıyorum .

Mevcut bir örnek, geçen gün küçük ihracat işlevselliği yazıyor olabilir .

Bir zip içinde csv , excel ve birleştirilmiş excel sayfalarına ihtiyaç vardı .

Düz işlevsellik her biri üç görünümde yapıldı (= işlevler). Her işlev, filtreleri belirlemek için ortak bir yöntem ve verileri almak için ikinci bir yöntem kullandı. Daha sonra her bir fonksiyonda dışa aktarmanın hazırlığı yapıldı ve sunucudan bir Yanıt olarak teslim edildi.

Karışık birçok soyutlama seviyesi vardı:

I) gelen / giden istek / cevap ile ilgilenmek

II) filtrelerin belirlenmesi

III) veri almak

IV) verilerin dönüşümü

Kolay adım, exporterbirinci adımda II-IV katmanları ile başa çıkmak için bir soyutlama ( ) kullanmaktı .

Geriye kalan tek şey istek / cevaplarla ilgilenen konuydu . Aynı soyutlama seviyesinde , tamam olan istek parametreleri çıkarılıyor . Bu yüzden bu görüş için bir "sorumluluk" vardı.

İkincisi, ihracatçıyı bölmek zorunda kaldım, gördüğümüz gibi en az üç diğer soyutlama katmanından oluşuyordu.

Filtre kriterleri ve gerçek geri kazanımın belirlenmesi neredeyse aynı soyutlama seviyesindedir (verilerin doğru alt kümesini elde etmek için filtreler gerekir). Bu seviyeler veri erişim katmanı gibi bir şeye kondu .

Bir sonraki adımda, gerçek ihracat mekanizmalarını parçaladım: Geçici bir dosyaya yazmak gerektiğinde, bunu iki "sorumluluk" a böldüm: biri diske gerçek veri yazmak için, diğeri de asıl format ile ilgileniyordu.

Sınıfların ve modüllerin oluşumu boyunca, işler neye aitti, neye aitti. Ve her zaman gizli soru, sınıfın çok fazla yapıp yapmadığı .

Her sınıfın hangi sorumluluklara sahip olduğunu nasıl belirlersiniz ve SRP bağlamında bir sorumluluğu nasıl tanımlarsınız?

Takip edecek bir tarif vermek zor. Tabii ki şifreli »bir soyutlama seviyesini« tekrar edebilirim - eğer yardımcı olursa kural.

Çoğunlukla benim için mevcut tasarıma götüren bir tür "sanatsal sezgi" dir; Bir sanatçı gibi kod yapıyorum kil biçebilir veya resim yapabilir.

Beni Kodlayan Bob Ross ;) olarak hayal edin ;)


0

SRP'yi izleyen kod yazmak için ne yapmaya çalışıyorum:

  • Çözmeniz gereken belirli bir problem seçin;
  • Bunu çözen kodu yazın, her şeyi tek bir yöntemle yazın (örneğin: ana);
  • Kodu dikkatlice inceleyin ve işletmeye dayalı olarak, gerçekleştirilen tüm işlemlerde görünen sorumlulukları tanımlamaya çalışın (bu, işe / projeye / müşteriye de bağlı olan sübjektif kısımdır);
  • Lütfen, tüm işlevlerin zaten uygulandığını unutmayın; sıradaki sadece kodun organizasyonu (bu yaklaşımda bundan sonra ek bir özellik veya mekanizma uygulanmayacak);
  • Önceki adımlarda tanımladığınız sorumluluklara dayanarak (işe ve “değişmenin bir nedeni” fikrine dayanarak tanımlanmıştır), her biri için ayrı bir sınıf veya yöntem çıkarın;
  • Lütfen bu yaklaşımın sadece SPR ile ilgilendiğini unutmayın; İdeal olarak, burada diğer ilkelere de uymaya çalışılması gereken ilave adımlar bulunmalıdır.

Örnek:

Sorun: kullanıcıdan iki sayı al, toplamlarını hesapla ve sonucu kullanıcıya gönder:

//first step: solve the problem right away
static void Main(string[] args)
{
    Console.WriteLine("Number 1: ");
    int firstNumber = Convert.ToInt32(Console.ReadLine());

    Console.WriteLine("Number 2: ");
    int secondNumber = Convert.ToInt32(Console.ReadLine());

    int result = firstNumber + secondNumber;

    Console.WriteLine("Hi there! The result is: {0}", result);

    Console.ReadLine();
}

Ardından, yapılması gereken görevlere dayanarak sorumlulukları tanımlamaya çalışın. Bundan uygun sınıfları çıkarın:

//Responsible for getting two integers from the user
class Input {
    public int FirstNumber { get; set; }
    public int SecondNumber { get; set; }
    public void Read() {
        Console.WriteLine("Number 1: ");
        FirstNumber = Convert.ToInt32(Console.ReadLine());

        Console.WriteLine("Number 2: ");
        SecondNumber = Convert.ToInt32(Console.ReadLine());
    }
}

//Responsible for calculating the sum of two integers
class SumOperation {
    public int Result { get; set; }
    public void Calculate(int a, int b) {
        Result = a + b;
    }
}

//Responsible for the output of some value to the user
class Output {
    public void Write(int result) {
        Console.WriteLine("Hello! The result is: {0}", result);
    }
}

Ardından, yenilenen program şu şekilde olur:

//Program: responsible for main execution.
//Gets two numbers from user and output their sum.
static void Main(string[] args)
{
    var input = new Input();
    input.Read();

    var operation = new SumOperation();
    operation.Calculate(input.FirstNumber, input.SecondNumber);

    var output = new Output();
    output.Write(operation.Result);

    Console.ReadLine();
}

Not: Bu çok basit örnek sadece SRP prensibini dikkate almaktadır. Diğer ilkelerin kullanılması (örneğin: "L" - kodu, sözleşmelerden ziyade soyutlamalara dayanmalıdır), koda daha fazla fayda sağlayacak ve iş değişiklikleri için daha sürdürülebilir hale getirecektir.


1
Örneğiniz SRP'yi yeterince göstermek için çok basit. Kimse bunu gerçek hayatta yapmaz.
Robert Harvey,

Evet, gerçek projelerde, örneğimdeki gibi tam kodu yazmak yerine bazı sahte kodlar yazıyorum. Sözde koddan sonra, örnekteki gibi sorumlulukları bölmeye çalışıyorum. Neyse, aynen böyle yapıyorum.
Emerson Cardoso

0

Robert C. Martins kitabından Clean Architecture: 10 Eylül 2017 tarihinde yayınlanan bir Zanaatkarın Yazılım Yapısı ve Tasarımı Kılavuzu , Robert, sayfa 62'de yazıyor:

Tarihsel olarak, SRP şu şekilde tanımlanmıştır:

Bir modülün değişmesi için tek bir neden olmalı

Yazılım sistemleri kullanıcıları ve paydaşları memnun edecek şekilde değiştirilir; bu kullanıcılar ve paydaşlar olan "değiştirmek için bir neden". bu ilke hakkında konuşuyor. Gerçekten, bunu söyleme ilkesini tekrar ifade edebiliriz:

Bir modül bir kullanıcı, yalnızca bir kullanıcı veya paydaştan sorumlu olmalıdır.

Ne yazık ki, "kullanıcı" ve "paydaş" kelimesi burada kullanılacak doğru kelime değil. Sistemin aklı başında bir şekilde değişmesini isteyen birden fazla kullanıcı veya paydaş olması muhtemeldir. Bunun yerine gerçekten bir gruba atıfta bulunuyoruz - bu değişikliği gerektiren bir veya daha fazla kişi. Bu gruba bir oyuncu olarak değineceğiz .

Dolayısıyla, SRP'nin son versiyonu şöyledir:

Bir modül, bir ve yalnızca bir oyuncuya karşı sorumlu olmalıdır.

Yani bu kod ile ilgili değil. SRP, sadece tek bir kaynaktan gelebilecek gereksinimlerin ve iş ihtiyaçlarının akışını kontrol etmekle ilgilidir.


Neden “kod hakkında değil” ayrımını yaptığını bilmiyorum. Elbette kodla ilgili; bu yazılım geliştirmedir.
Robert Harvey,

@RobertHarvey Amacım, gereksinimlerin akışının bir kaynaktan, aktörden geldiğidir. Kullanıcılar ve Menfaat Sahipleri kodda değil, şart olarak bize gelen iş kurallarındadır. Dolayısıyla, SRP bu gereksinimleri kontrol etmek için bir işlemdir, ki bu benim için kod değil. Yazılım Geliştirme (!), Ancak kod değil.
Benny Skogberg
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.