Tasarım: Object yöntemi vs Object'i parametre olarak alan ayrı sınıfın yöntemi?


14

Örneğin, yapmak daha iyidir:

Pdf pdf = new Pdf();
pdf.Print();

veya:

Pdf pdf = new Pdf();
PdfPrinter printer = new PdfPrinter();
printer.Print(pdf);

Başka bir örnek:

Country m = new Country("Mexico");
double ratio = m.GetDebtToGDPRatio();

veya:

Country m = new Country("Mexico");
Country us = new Country("US");
DebtStatistics ds = new DebtStatistics();
double usRatio = ds.GetDebtToGDPRatio(us);
double mRatio = ds.GetDebtToGDPRatio(m);    

Son örnekteki endişem, bir ülke hakkında bilmek isteyebileceğiniz potansiyel olarak sonsuz istatistikler (ancak diyelim ki sadece 10 tane) olması; hepsi ülke nesnesine mi ait?

Örneğin

Country m = new Country("Mexico");
double ratio = m.GetGDPToMedianIncomeRatio();

Bunlar basit oranlardır, ancak istatistiklerin bir yöntemi gerektirecek kadar karmaşık olduğunu varsayalım.

Bir nesneye özgü işlemler ile bir nesne üzerinde gerçekleştirilebilen ancak onun bir parçası olmayan işlemler arasındaki çizgi nerede?

Yanıtlar:


16

PDF örneklerinizi başlangıç ​​noktası olarak ele alalım, buna bakalım.

http://en.wikipedia.org/wiki/Single_responsibility_principle

Tek Sorumluluk İlkesi, bir nesnenin tek bir hedefi olması gerektiğini önermektedir. Bunu aklında tut.

http://en.wikipedia.org/wiki/Separation_of_concerns

Endişelerin Ayrılması ilkesi bize sınıfların örtüşen işlevlere sahip olmaması gerektiğini söyler.

Bu ikisine baktığınızda, mantığın sadece mantıklı bir sınıfta gitmesi gerektiğini, ancak o sınıfın bunu yapmaktan sorumlu olması gerektiğini önerirler.

Şimdi, PDF örneğinizde soru şu: Baskıdan kim sorumlu? Ne mantıklı?

İlk kod snippet'i:

Pdf pdf = new Pdf();
pdf.Print();

Bu iyi değil. Bir PDF belgesi kendi kendine yazdırmaz. Bir yazıcı tarafından ... ta da! .. yazdırılır. Yani ikinci kod pasajınız çok daha iyi:

Pdf pdf = new Pdf();
PdfPrinter printer = new PdfPrinter();
printer.Print(pdf);

Bu mantıklı. Pdf Yazıcı bir pdf belgesi yazdırır. Daha da iyisi, bir yazıcı PDF yazıcı veya fotoğraf yazıcısı olmamalıdır. Sadece kendisine gönderilenleri en iyi şekilde yazdırabilen bir yazıcı olmalıdır.

Pdf pdf = new Pdf();
Printer printer = new Printer();
printer.Print(pdf);

Yani bu basit. Yöntemleri mantıklı oldukları yere koyun. Açıkçası, her zaman bu kadar basit değildir. Ülkenizin istatistiklerini ele alalım örneğin:

Country m = new Country("Mexico");
double ratio = m.GetDebtToGDPRatio();

Endişeniz, n sayıda istatistik olabileceğidir ve bir Country sınıfında olmamalıdır. Bu doğru. Ancak, modeliniz yalnızca belirli istatistikleri çağırıyorsa, bu modelleme örneği gerçekten iyi olabilir.

Bu durumda, oldukça mantıklı bir şekilde, bir ülkenin modelinize ve gereksinimlerinize özgü kendi istatistiklerini hesaplayabilmesi gerektiğini söyleyebilirsiniz.

Ve bir şey var: Gereksinimleriniz neler? Gereksinimleriniz, dünyayı modelleme şeklinizi, bu gereksinimlerin karşılanacağı bağlamı yönlendirecektir.

Gerçekten çok sayıda / değişken sayıda istatistiğiniz varsa, ikinci örneğiniz daha anlamlı olur:

Country m = new Country("Mexico");
DebtStatistics ds = new DebtStatistics();
double usRatio = ds.GetDebtToGDPRatio(m);

Daha da iyisi, ülkeyi parametre olarak alan, İstatistik adı verilen soyut bir üst sınıf veya arayüze sahip olun:

interface StatisticsCalculator // or a pure abstract class if doing C++
{
   double getStatistics(Country country); // or a pure virtual function if in C++
}

class DebtToGDPRatioStatisticsCalculator uygular StatisticsCalculator ....

Sınıf InfantMortalityStatisticsCalculator uygular İstatistiklerCalculator ...

Ve benzeri vb. Bu aşağıdakilere yol açar: genelleme, delegasyon, soyutlama. İstatistiksel toplama, belirli bir soyutlamayı (bir istatistik toplama API'sı) genelleyen belirli örneklere devredilir .

Bunun sorunuzu% 100 yanıtlayıp yanıtlamadığını bilmiyorum. Sonuçta, dokunulmaz yasalara dayanan (EE milletlerinin yaptığı gibi) yanılmaz modellerimiz yok. Yapabileceğiniz tek şey, mantıklı oldukları şeyler koymaktır. Ve bu, vermeniz gereken bir mühendislik kararı. Yapılacak en iyi şey gerçekten OO ilkelerini (ve genel olarak iyi yazılım modelleme ilkelerini) tanımaktır.


1
StatisticsCalculator Arayüzü için +1 (ve daha sonra Strateji Kalıbı kullanımı). İyi düşünülmüş cevap
edwardsmatt

3
şu anda iyice yapıyı çözmek için yetersiz zaman, ancak Printer sınıfının zaman içinde her tür belge sınıfına sıkıca bağlı bir Tanrı sınıfı haline geleceğini belirtmek gerekir. Pdf.Print tercih edilir - ancak her şey 'tek sorumluluğu' nasıl tanımladığınıza bağlıdır ;-)
Steven A. Lowe

@Steve - önerdiğiniz şey korkunç bir fikirdir (Pdf'i print () uygulayarak). Baskının gerçek hayatta nasıl uygulandığını yansıtmaz. Fark ettiğim her işletim sistemi ve yazdırma API'sı için bir soyutlama sağlar Printer. XP / Vista makinenizdeki yazıcı listesine bakın (veya / n altında / * nix altında eşdeğeri veya eşdeğeri). Her uygulama bir belge nesnesini yazıcılarından birine serileştirir. Word yazıcı veya metin Yazıcı veya PDF yazıcı yok. Sadece yazıcılar vardır belirli baskı aygıtına ve belge türüne özgü değildir.
luis.espinal

2
+1 Seviyorum Söylediklerini düşünüyorum .. @Steve ve luis: Bence Tanrı nesneleri hakkındaki tartışmanın eksik parçası genel bir Printer nesnesi ASCII veya bitmap gibi birkaç standart formatı kabul etmeli (pdf muhtemelen makul olabilir) ve belirli bir belge türünü (ms word belgesi diyelim) bu standart biçimlerden birine dönüştürmek 3. sınıfın sorumluluğunda olmalıdır.
Kullanıcı

2
Bana öyle geliyor ki, belki bir PDF kendisini bir Canvas arabirimine ya da daha sonra bir Printer nesnesi tarafından işlenebilecek bir Image nesnesine dönüştürebilmelidir.
Winston Ewert

4

Bence ikisi de kesinlikle diğerinden daha iyi değil. Pdf.Print () kullanmak daha sıkıdır, ancak aşağıdaki durumlarda PdfPrinter sınıfına sahip olmak daha iyi olabilir:

  • Yazıcı örneklerini yönetmeniz gerekiyor
  • Pdf'yi patlatacak çok çeşitli seçenekler ve eylemler vardır.

Aksi takılmam.


iyi, pratik bir cevap; bunun nasıl gelişmesi gerektiğini zaman gösterecek
Steven A. Lowe

1
Kısa öneri hem bakmaktır mantık ve veri biz pişman olacak karar vermek amacıyla, SRP uygulanırken değil er ayrılmasıyla. Yazıcı başına ayarları Pdfsınıfta saklama sorunu, birlikte Pdfdepolanmamalarıdır - bir dosyada saklanır, ancak yazıcı başına ayarlar kullanıcı / makine profiliyle birlikte saklanmalıdır.
rwong
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.