Mengambil contoh PDF Anda sebagai titik awal, mari kita lihat ini.
http://en.wikipedia.org/wiki/Single_responsibility_principle
Prinsip Tanggung Jawab Tunggal menyarankan bahwa suatu objek harus memiliki satu dan hanya satu tujuan. Ingatlah ini.
http://en.wikipedia.org/wiki/Separation_of_concerns
Prinsip Separation of Concerns memberi tahu kita bahwa kelas tidak boleh memiliki fungsi yang tumpang tindih.
Ketika Anda melihat dua ini, mereka menyarankan bahwa logika harus masuk kelas hanya jika masuk akal, hanya jika kelas yang bertanggung jawab untuk melakukan itu.
Sekarang, dalam contoh PDF Anda, pertanyaannya adalah, siapa yang bertanggung jawab untuk mencetak? Apa yang masuk akal?
Cuplikan kode pertama:
Pdf pdf = new Pdf();
pdf.Print();
Ini tidak bagus. Dokumen PDF tidak mencetak dirinya sendiri. Itu akan dicetak oleh ... ta da! .. sebuah printer. Jadi Anda potongan kode kedua jauh lebih baik:
Pdf pdf = new Pdf();
PdfPrinter printer = new PdfPrinter();
printer.Print(pdf);
Ini masuk akal. Printer Pdf mencetak dokumen pdf. Lebih baik lagi, printer tidak boleh menjadi printer PDF, atau printer foto. Seharusnya hanya printer yang mampu mencetak barang-barang yang dikirim kepadanya dengan kemampuan terbaiknya.
Pdf pdf = new Pdf();
Printer printer = new Printer();
printer.Print(pdf);
Jadi itu sederhana. Letakkan metode di mana mereka masuk akal. Jelas, tidak selalu sesederhana itu. Ambil statistik negara Anda misalnya:
Country m = new Country("Mexico");
double ratio = m.GetDebtToGDPRatio();
Kekhawatiran Anda adalah bahwa mungkin ada n jumlah statistik, dan bahwa mereka tidak harus berada dalam kelas Country. Itu benar. Namun, jika model Anda hanya membutuhkan statistik tertentu, contoh pemodelan ini mungkin sebenarnya baik-baik saja.
Dalam hal ini, Anda dapat mengatakan dengan cukup logis bahwa suatu negara harus dapat menghitung statistiknya sendiri, khusus untuk model Anda dan persyaratan yang ada.
Dan di situlah letak masalahnya: apa kebutuhan Anda? Persyaratan Anda akan mendorong cara Anda memodelkan dunia, konteks, di mana persyaratan ini harus dipenuhi.
Jika Anda memang memiliki banyak statistik, maka contoh kedua Anda lebih masuk akal:
Country m = new Country("Mexico");
DebtStatistics ds = new DebtStatistics();
double usRatio = ds.GetDebtToGDPRatio(m);
Lebih baik lagi, memiliki superclass abstrak atau antarmuka yang disebut Statistik yang mengambil negara sebagai parameter:
interface StatisticsCalculator // or a pure abstract class if doing C++
{
double getStatistics(Country country); // or a pure virtual function if in C++
}
class DebtToGDPRatioStatisticsCalculator mengimplementasikan StatisticsCalculator ....
kelas BayiMortalityStatisticsCalculator mengimplementasikan StatisticsCalculator ...
Dan seterusnya dan seterusnya. Yang mengarah pada hal berikut: generalisasi, delegasi, abstraksi. Pengumpulan statistik akan didelegasikan ke contoh spesifik yang menggeneralisasi abstraksi tertentu (API pengumpulan statistik).
Saya tidak tahu apakah ini menjawab pertanyaan Anda 100%. Lagipula, kita tidak memiliki model yang sempurna yang didasarkan pada hukum yang tidak dapat diganggu gugat (seperti yang dilakukan orang-orang EE.) Yang dapat Anda lakukan hanyalah memasukkan hal-hal yang masuk akal. Dan itu keputusan teknis yang harus Anda ambil. Hal terbaik untuk dilakukan adalah benar-benar mengenal prinsip-prinsip OO (dan prinsip-prinsip pemodelan perangkat lunak yang baik pada umumnya.)