Apa manfaatnya memiliki model POCO murni?

15

Apa manfaat utama dari memiliki model POCO murni? Saya mendapatkan bahwa Model harus bersih dan sederhana, tetapi saya cenderung suka menjaga pemeliharaan objek anak di dalam kelas model. Sebagai contoh jika saya memiliki ClassAdan ClassBmendefinisikan sebagai berikut:

public class ClassA
{
    public string MyProp { get; set; }
    public IEnumerable<ClassB> Children { get; }

    public void AddChild(ClassB newChild) { /*... */ }
    public void RemoveChild(ClassB child) { /* ... */ }
}

public class ClassB
{
    public string SomeProp { get; set; }
} 

Apakah ada sesuatu yang salah dengan memiliki metode add and remove? Haruskah saya hanya membuka daftar dan memperbolehkan kode klien untuk menambahkan apa pun yang melewati tanggung jawab validasi data sederhana seperti tidak nol, dan tidak menduplikasi ke kelas lain?

Setiap bantuan sangat dihargai. Terima kasih.

Jesse
sumber
Saya akan menghapus metode Tambah / Hapus kecuali jika mereka menambahkan beberapa nilai, seperti menerjemahkan argumen ClassB nol ke versi pola NullObject objek:AddChild(ClassB newChild) => Children.Add(newChild ?? new NullClassB())
Graham
Jika Anda pernah berurusan dengan sakit kepala kelas ActiveRecord dengan ratusan metode yang mungkin atau mungkin tidak seperti yang Anda inginkan pada waktu tertentu, saya pikir akan lebih mudah untuk memahami banding.
Casey
Alasan utama untuk menghindari desain khusus ini adalah karena bertentangan dengan pedoman desain .net. Ini sepenuhnya sewenang-wenang, tetapi orang-orang berharap koleksi memiliki metode mutasi di dalamnya.
Frank Hileman
@Casey Saya tidak menggunakan pola Rekaman Aktif, metode add hanya melakukan beberapa validasi data kecil. Metode penghapusan ada di sana karena koleksi tidak terbuka, mereka hanya menambah dan menghapus dari daftar internal. Saya telah mengubahnya meskipun untuk menggunakan jenis koleksi yang berbeda yang memungkinkan saya untuk melakukan validasi sementara masih menggunakan metode Tambahkan / Hapus bawaan.
Jesse

Jawaban:

42

Dua pertanyaan Anda tidak berhubungan.

Apa manfaatnya memiliki model POCO murni?

POCO murni tidak tergantung pada beberapa kerangka kerja, konvensi, [] thingy, atau terkait erat dengan beberapa objek yang sama-sama bergantung. Dengan kata lain, dunia dapat benar-benar berubah di sekitar POCO dan terus melakukan apa yang dilakukannya tanpa peduli. Anda tidak dapat merusaknya dengan memperbarui kerangka kerja, dengan memindahkannya ke sistem baru, atau melihatnya lucu. Itu terus bekerja. Satu-satunya dependensi adalah hal-hal yang diminta secara eksplisit.

POCO tidak lebih dari ide POJO. J diubah menjadi C karena orang-orang melihat Anda lucu ketika Anda menjelaskan konsep yang memiliki Java dalam namanya jika orang-orang tersebut menggunakan C #. Idenya tidak tergantung pada bahasa. Mereka bisa saja menyebutnya Benda Tua Biasa. Tetapi siapa yang ingin membual tentang penggunaan POO?

Saya akan membiarkan Fowler menjelaskan asal-usulnya:

Istilah ini diciptakan ketika Rebecca Parsons, Josh MacKenzie, dan saya sedang mempersiapkan sebuah ceramah di sebuah konferensi pada bulan September 2000. Dalam ceramah tersebut kami menunjukkan banyak manfaat dari pengodean logika bisnis ke objek java biasa daripada menggunakan Entity Beans. Kami bertanya-tanya mengapa orang begitu menentang menggunakan objek biasa dalam sistem mereka dan menyimpulkan bahwa itu karena objek sederhana tidak memiliki nama mewah. Jadi kami memberi mereka satu, dan itu ditangkap dengan sangat baik.

martinfowler.com: POJO

Adapun pertanyaan Anda yang lain:

Apakah ada sesuatu yang salah dengan memiliki metode add and remove?

Saya tidak suka Alangsung tahu tentang B. Tapi itu hal DIP bukan hal POJO .

candied_orange
sumber
Saya memiliki ketergantungan langsung Buntuk kesederhanaan, Idealnya keduanya akan mengimplementasikan antarmuka. Tetapi Amasih memiliki daftar IInterfaceB. Apakah ada yang salah dengan AddChildmetode ini jika anak-anak longgar digabungkan melalui referensi antarmuka?
Jesse
6
Saya bisa melakukan banyak hal konyol demi kesederhanaan. Apa yang saya tidak suka adalah A mengetahui tentang B. A tidak menggunakan B sehingga tidak perlu mendefinisikan antarmuka yang dimiliki A yang tepat untuk berbicara dengan B melalui. Sejauh yang saya tahu A adalah koleksi. Jadi A harus berurusan dengan B melalui <T> sehingga tidak perlu tahu apa-apa tentang itu.
candied_orange
2
Saya juga telah melihat "PODO" untuk "objek data lama biasa" untuk menghindari segala jenis penspesifikasi bahasa dalam akronim. PODO terdengar agak konyol (agak mirip julukan yang akan Anda dengar di Tatooine, bagi saya), lebih dari POJO atau POCO saya kira, tetapi secara signifikan kurang konyol dibandingkan POO.
KRyan
2
Saya ingin tahu seberapa baik presentasi Fowler jika dia menyebut mereka POO?
Oliver
3

Dengan Tambah dan Hapus Anda menerapkan Collection<T>fitur. Tanyakan kepada diri sendiri mengapa Anda menggunakan IEnumerable<T>alih-alih List<T>atau kelas yang bisa berubah-ubah lainnya? Ternyata bukan karena koleksi Anda harus dibaca saja.

Satu-satunya alasan yang dapat saya pikirkan adalah Anda ingin mengontrol metode akses apa yang ingin Anda terbitkan. Dalam hal itu akan lebih baik untuk membuat kelas koleksi Anda sendiri, merangkum daftar, menerapkan metode pilih Anda Tambah dan Hapus dan terapkan IEnumerable<T>. Kemudian gunakan itu bukan IEnumerable<T>untuk jenis koleksi anak-anak Anda.

Tapi menurut saya List<ClassB>mungkin hanya akan melayani Anda dengan baik.

Martin Maat
sumber
0

Apa yang AddChildditambahkan, dan RemoveChilddihapus dari? Jika itu dari database (atau toko kegigihan dalam bentuk apa pun), Anda semacam mendapat Rekaman Aktif. Tidak selalu selalu merupakan hal yang buruk, tetapi pasti membuat Anda hampir harus khawatir tentang kerangka kerja, konvensi, dependensi, dll, seperti yang disebutkan @CandiedOrange.

Pada saat yang sama, apa gunanya menghindari ketergantungan dari ClassA ke ClassB (atau setidaknya InterfaceB) jika mereka semua ada dalam aplikasi yang sama? Dalam domain dunia nyata yang dimodelkan oleh aplikasi Anda, banyak hal bergantung satu sama lain. Objek dunia nyata memang memiliki koleksi benda lain yang "milik" mereka. Sepenuhnya tepat untuk mewakili hubungan-hubungan itu dalam kode Anda.

Satu-satunya alasan bahkan menjadi sedikit rumit adalah karena Anda memiliki kebutuhan untuk mengelola dengan tepat bagaimana ClassB menjadi terkait dengan dan terlepas dari ClassA. Jadi, Anda memiliki sedikit perilaku untuk diterapkan. Anda dapat mengimplementasikannya di dalam kelas (yang benar-benar "legal"; lihat /programming//a/725365/44586 ), atau Anda dapat memiliki semacam kelas terpisah yang berisi perilaku itu. Lakukan apa yang paling masuk akal untuk keadaan pribadi Anda.

Bagaimanapun, POJO / POCO benar-benar hanya OOP sebagaimana seharusnya, tanpa hiasan dan tidak terbebani. Ikuti prinsip OOP dan Anda akan aman.

John M Gant
sumber
Sungguh AddChild hanya memeriksa duplikasi, dan nol, dan tidak mengizinkan keduanya. RemoveChild ada di sana karena untuk mencegah backdoor menambahkan koleksi terkena sebagai IEnumerable. Itu hanya akan melakukan penghapusan standar dari koleksi sekalipun.
Jesse
1
Terima kasih telah menjelaskan. Ya, itu terdengar seperti tipe perilaku yang seharusnya ada dalam POCO, dan jelas lebih baik daripada hanya mengekspos IEnumerable Anda yang mendasarinya bagi penelepon untuk memodifikasi atau mengganti sesuka hati.
John M Gant
Saya pikir Rekaman Aktif hanyalah pola yang buruk.
Casey
1
@ Casey, Anda tidak akan mendapatkan argumen dari saya tentang hal itu. Tapi saya tidak akan berdebat jika seseorang ingin menggunakannya juga. Poin utama adalah jika Jesse berniat untuk menggunakan pola seperti Rekaman Aktif yang mengintegrasikan ketekunan dengan definisi model, ia akan memiliki semua masalah yang disoroti oleh CandiedOrange, dan tidak akan benar-benar memenuhi syarat sebagai POCO, untuk apa nilainya. Tapi toh itu bukan yang dia lakukan.
John M Gant