CLR Obyek Biasa vs Obyek Transfer Data

405

POCO = Obyek Old CLR (atau lebih baik: Class)

DTO = Objek Transfer Data

Dalam posting ini ada perbedaan, tetapi terus terang sebagian besar blog yang saya baca menggambarkan POCO dalam cara DTO didefinisikan: DTO adalah wadah data sederhana yang digunakan untuk memindahkan data antara lapisan aplikasi.

Apakah POCO dan DTO adalah hal yang sama?

Patrick Peters
sumber
5
"POCO = Obyek CLR Biasa (atau lebih baik: Kelas)". Dengan demikian, objek seperti ini di VB.NET akan menjadi POCO juga, bukan POVO.
J. Polfer

Jawaban:

568

POCO mengikuti aturan OOP. Seharusnya (tetapi tidak harus) memiliki keadaan dan perilaku. POCO berasal dari POJO, diciptakan oleh Martin Fowler [ anekdot di sini ]. Dia menggunakan istilah POJO sebagai cara untuk membuatnya lebih seksi untuk menolak kerangka implementasi EJB yang berat. POCO harus digunakan dalam konteks yang sama di .Net. Jangan biarkan kerangka kerja mendikte desain objek Anda.

Satu-satunya tujuan DTO adalah untuk mentransfer status, dan seharusnya tidak memiliki perilaku. Lihat penjelasan Martin Fowler tentang DTO untuk contoh penggunaan pola ini.

Inilah perbedaannya: POCO menjelaskan pendekatan pemrograman ( pemrograman berorientasi objek kuno yang baik), di mana DTO adalah pola yang digunakan untuk "mentransfer data" menggunakan objek.

Meskipun Anda dapat memperlakukan POCO seperti DTO, Anda berisiko membuat model domain anemia jika Anda melakukannya. Selain itu, ada ketidakcocokan dalam struktur, karena DTO harus dirancang untuk mentransfer data, bukan untuk mewakili struktur sebenarnya dari domain bisnis. Hasil dari ini adalah bahwa DTO cenderung lebih datar daripada domain Anda yang sebenarnya.

Dalam domain dengan kompleksitas yang masuk akal, Anda hampir selalu lebih baik membuat POCO domain terpisah dan menerjemahkannya ke DTO. DDD (desain berbasis domain) mendefinisikan lapisan anti-korupsi (tautan lain di sini , tetapi hal terbaik yang harus dilakukan adalah membeli buku ), yang merupakan struktur yang baik yang membuat pemisahan jelas.

Michael Meadows
sumber
Saya tahu saya banyak merujuk Martin Fowler di sini, tetapi dia menciptakan istilah POJO, dan menulis buku PoEAA yang merupakan referensi pasti untuk DTO.
Michael Meadows
Saya tidak yakin apakah DTO seharusnya tidak memiliki perilaku. Menghakimi oleh diagram Martin Fowler, DTO dapat memiliki perilaku.
Beatles1692
39
@ Beatles1692, metode yang digambarkan adalah kode serialisasi. Mungkin terlalu luas pernyataan untuk mengatakan "tidak ada perilaku." Bagaimana dengan "tidak ada logika bisnis." Kode serialisasi, dan hal-hal objek tingkat rendah seperti kode hash, kesetaraan, dan tostring harus dapat diterima.
Michael Meadows
1
@PositiveGuy Model melayani tujuan yang berbeda dari DTO. DTO seharusnya untuk mentransfer data dari satu domain ke domain lain (terlepas dari apakah mereka dalam runtime yang sama tidak relevan). Model "mewakili" aspek domain, seperti layar, layanan, atau sumber data. Model termasuk keadaan dan perilaku, yang mewakili apa yang mereka modelkan.
Michael Meadows
2
Harap perhatikan bahwa model domain anemia tidak selalu buruk, terutama jika aplikasi Anda kebanyakan CRUD. Mendukung kesederhanaan daripada Martin Fowler.
Mariusz Jamro
50

Itu mungkin berlebihan bagi saya untuk berkontribusi karena saya sudah menyatakan posisi saya di artikel blog saya, tetapi paragraf terakhir dari artikel itu meringkaskan:

Jadi, sebagai kesimpulan, belajarlah untuk mencintai POCO, dan pastikan Anda tidak menyebarkan informasi yang salah tentang hal itu sama dengan DTO. DTO adalah wadah data sederhana yang digunakan untuk memindahkan data di antara lapisan aplikasi. POCO adalah objek bisnis penuh dengan satu persyaratan bahwa mereka Ketidaktahuan (tidak ada metode mendapatkan atau menyimpan). Terakhir, jika Anda belum membaca buku Jimmy Nilsson, ambil dari tumpukan universitas setempat. Ini memiliki contoh dalam C # dan itu adalah bacaan yang bagus.

BTW, Patrick Saya membaca POCO sebagai artikel Gaya Hidup, dan saya sepenuhnya setuju, itu adalah artikel yang fantastis. Ini sebenarnya bagian dari buku Jimmy Nilsson yang saya rekomendasikan. Saya tidak tahu itu tersedia online. Bukunya benar-benar adalah sumber informasi terbaik yang saya temukan di POCO / DTO / Repository / dan praktik pengembangan DDD lainnya.


sumber
4
Tautan ke artikel blog: rlacovara.blogspot.com/2009/03/...
Jamie Ide
28

POCO hanyalah sebuah objek yang tidak bergantung pada kerangka eksternal. Itu adalah polos.

Apakah POCO memiliki perilaku atau tidak, itu tidak penting.

DTO dapat berupa POCO sebagaimana objek domain (yang biasanya kaya akan perilaku).

Biasanya DTO lebih cenderung untuk mengambil dependensi pada kerangka kerja eksternal (misalnya atribut) untuk keperluan serialisasi karena biasanya mereka keluar pada batas sistem.

Dalam arsitektur gaya Onion yang khas (sering digunakan dalam pendekatan DDD luas) lapisan domain ditempatkan di tengah dan karenanya objek-objeknya tidak, pada titik ini, memiliki dependensi di luar lapisan itu.

Neil
sumber
15

Saya menulis artikel untuk topik itu: DTO vs Value Object vs POCO .

Pendeknya:

  • DTO! = Nilai Objek
  • DTO ⊂ POCO
  • Nilai Objek ⊂ POCO
Vladimir
sumber
6

Saya pikir DTO bisa menjadi POCO. DTO lebih tentang penggunaan objek sementara POCO lebih dari gaya objek (dipisahkan dari konsep arsitektur).

Salah satu contoh di mana POCO adalah sesuatu yang berbeda dari DTO adalah ketika Anda berbicara tentang POCO di dalam model domain / model logika bisnis Anda, yang merupakan representasi OO yang bagus dari domain masalah Anda. Anda dapat menggunakan POCO di seluruh aplikasi, tetapi ini bisa memiliki beberapa efek samping yang tidak diinginkan seperti kebocoran pengetahuan. DTO misalnya digunakan dari Lapisan Layanan yang berkomunikasi dengan UI, DTO adalah representasi data yang datar, dan hanya digunakan untuk menyediakan data kepada UI, dan mengkomunikasikan perubahan kembali ke lapisan layanan. Lapisan layanan bertugas memetakan kedua cara DTO ke objek domain POCO.

Pembaruan Martin Fowler mengatakan bahwa pendekatan ini merupakan jalan yang berat untuk diambil, dan seharusnya hanya diambil jika ada ketidakcocokan yang signifikan antara lapisan domain dan antarmuka pengguna.

Davy Landman
sumber
2
@ David Landman, tautan yang Anda sertakan adalah untuk pola DTO Lokal, yaitu saat DTO digunakan untuk status transfer dalam batas sistem Anda. Dalam kasus ini, Anda harus sangat berhati-hati, karena di dalam sistem Anda, Anda harus sudah memiliki domain yang terdefinisi dengan baik yang dapat dibagikan. Saat mentransfer status melintasi batas sistem, DTO sulit untuk dihindari dan cukup sesuai dalam semua kasus.
Michael Meadows
@Michal Meadows, ya, tautannya memang berbicara tentang subset masalah yang berbeda. Tapi saya pikir dalam kasus transfer negara melintasi batas sistem Anda harus menggunakan layanan terjemahan untuk memetakan POCO dari satu konteks ke POCO dari konteks lain. Atau apakah Anda berbicara tentang batasan pada tingkat sistem?
Davy Landman
1

Kasus penggunaan utama untuk DTO adalah dalam mengembalikan data dari layanan web. Dalam hal ini, POCO dan DTO setara. Setiap perilaku dalam POCO akan dihapus ketika dikembalikan dari layanan web, jadi tidak masalah apakah itu memiliki perilaku atau tidak.

John Saunders
sumber
5
Saya pikir jawaban Anda salah menggambarkan apa yang terjadi sedikit. Dalam hal layanan web, proksi dihasilkan berdasarkan status objek yang terbuka. Ini berarti DTO dibuat terpisah dari POCO yang kebetulan memiliki negara publik yang sama dengan POCO. Ini mungkin terlihat halus, tetapi ini penting. Alasannya adalah bahwa bahkan jika proxy identik dengan yang asli, itu sebenarnya tidak dibangun dari kelas yang sama.
Michael Meadows
Eh, tidak. Seseorang menggunakan DTO untuk mengembalikan / menerima data antar tingkatan, dalam hal ini, layanan web. Seseorang memilih DTO karena hanya memiliki data, dan tidak memiliki perilaku. Memang benar bahwa kelas proxy kemungkinan juga akan menjadi DTO, dan jika Anda menggunakan kelas POCO sebagai gantinya, bahwa proxy akan dibuat. Tetapi dalam kasus ini, kelas POCO secara efektif adalah DTO, karena perilakunya tidak akan diterjemahkan. Saya masih mengatakan menggunakan DTO karena Anda tidak akan kehilangan perilaku yang tidak pernah ada.
John Saunders
5
** Semantik: Layanan web mengekspos tas negara objek menggunakan WSDL. Proxy dihasilkan dari ini. Ini tidak termasuk perilaku. Jika menggunakan layanan web, satu-satunya hubungan antara objek Anda dan objek domain terbuka adalah bahwa ia memiliki status publik yang sama yang dibuat berdasarkan inspeksi.
Michael Meadows
7
@ John, saya pikir Anda bereaksi berlebihan. Saya mengatakan Anda benar, tetapi kata-kata Anda menyesatkan. "Dalam hal ini, POCO dan DTO setara." Semantik, itu tidak benar. POCO dapat digunakan sebagai DTO dan sebaliknya, tetapi itu tidak berarti mereka setara ... tidak lebih dari mobil dan truk pickup yang setara, meskipun keduanya dapat digunakan untuk mengantar Anda ke toko bahan makanan. Mereka memiliki fungsi yang tumpang tindih, tetapi Anda akan kesulitan menemukan seseorang untuk memberi tahu Anda wawasan setara dengan F350, bahkan dalam konteks perjalanan bahan makanan.
Michael Meadows
3
Jawaban ini sangat salah, layanan web tidak cukup umum untuk satu. Yang terpenting adalah fakta bahwa DTO BUKAN POCO. DTO adalah sebuah wadah data, sementara POCO adalah objek sebagai properti dan tidak tahu apa-apa (tidak mendapatkan atau menyimpan metode).
Tom Stickel
1

di sini adalah aturan umum: DTO == jahat dan indikator perangkat lunak yang direkayasa berlebihan. POCO == bagus. Pola 'perusahaan' telah menghancurkan otak banyak orang di dunia Java EE. tolong jangan ulangi kesalahan di .NET land.

benmmurphy
sumber
7
Bisakah Anda menguraikannya? DTO diperlukan saat mengembalikan data dari layanan web, untuk menghindari implementasi dan platform spesifik dalam kontrak.
John Saunders
1
Ya, John DTO dirancang untuk apa yang Anda katakan dan bekerja dengan baik. Namun sayangnya mereka sering digunakan ketika tidak diperlukan dalam aplikasi web lapis tunggal dan memiliki nilai yang kecil.
Craig
9
Saya pikir, @drscroogemcduck, bahwa mungkin Anda tidak menyukai DTO karena mereka digunakan sebagai pilihan pertama dan bukan pilihan terakhir, tetapi mereka pada dasarnya tidak jahat ... tidak lebih dari singleton atau pola pabrik yang terkenal . Apa yang jahat adalah arsitek yang mendorong kerangka kerja ke bawah leher pengembang yang memaksa mereka untuk membuat DTO untuk semuanya. Untuk apa yang mereka lakukan, mentransfer data, DTO (jika dilakukan dengan hati-hati) sangat cocok.
Michael Meadows
0

Kelas DTO digunakan untuk membuat serial / deserialisasi data dari berbagai sumber. Ketika Anda ingin melakukan deserialisasi objek dari sumber, tidak peduli apa sumber eksternal itu: layanan, file, database dll. Anda mungkin hanya ingin menggunakan beberapa bagian dari itu tetapi Anda ingin cara mudah deserialize data ke suatu obyek. setelah itu Anda menyalin data itu ke XModel yang ingin Anda gunakan. Serializer adalah teknologi indah untuk memuat objek DTO. Mengapa? Anda hanya perlu satu fungsi untuk memuat (deserialize) objek.

Herman Van Der Blom
sumber
0

TL; DR:

DTO menggambarkan pola transfer negara. POCO tidak menjelaskan apa pun. Ini cara lain untuk mengatakan "objek" di OOP. Itu berasal dari POJO (Jawa), diciptakan oleh Martin Fowler yang secara harfiah hanya menggambarkannya sebagai nama yang lebih menarik untuk 'objek' karena 'objek' tidak terlalu seksi.

DTO adalah pola objek yang digunakan untuk mentransfer keadaan di antara lapisan yang memprihatinkan. Mereka dapat memiliki perilaku (yaitu secara teknis bisa menjadi poco) selama perilaku itu tidak mengubah negara. Misalnya, mungkin ada metode yang membuat cerita bersambung.

POCO adalah objek polos, tetapi yang dimaksud dengan 'polos' adalah bahwa objek itu tidak istimewa. Ini hanya berarti itu adalah objek CLR tanpa pola tersirat padanya. Istilah umum. Itu tidak dibuat untuk bekerja dengan beberapa kerangka kerja lain. Jadi, jika POCO Anda memiliki [JsonProperty]atau dekorasi EF di seluruh propertinya, misalnya, maka saya berpendapat bahwa itu bukan POCO.

Berikut beberapa contoh berbagai jenis pola objek untuk dibandingkan:

  • Lihat Model : digunakan untuk memodelkan data untuk tampilan. Biasanya memiliki anotasi data untuk membantu pengikatan dan validasi. Dalam MVVM, itu juga bertindak sebagai pengontrol. Ini lebih dari sekadar DTO
  • Value Object : digunakan untuk merepresentasikan nilai
  • Agregat Root : digunakan untuk mengelola negara dan invarian
  • Penangan : digunakan untuk menanggapi suatu peristiwa / pesan
  • Atribut : digunakan sebagai dekorasi untuk menangani masalah lintas sektoral
  • Layanan : digunakan untuk melakukan tugas-tugas kompleks
  • Controller : digunakan untuk mengontrol aliran permintaan dan respons
  • Pabrik : digunakan untuk mengonfigurasi dan / atau merakit objek kompleks untuk digunakan ketika konstruktor tidak cukup baik. Juga digunakan untuk membuat keputusan tentang objek mana yang harus dibuat saat runtime.
  • Repositori / DAO : digunakan untuk mengakses data

Ini semua hanyalah objek, tetapi perhatikan bahwa sebagian besar dari mereka umumnya terikat pada suatu pola. Jadi Anda bisa menyebutnya "objek" atau Anda bisa lebih spesifik tentang maksudnya dan menyebutnya dengan apa adanya. Ini juga mengapa kami memiliki pola desain; untuk menggambarkan konsep kompleks dalam beberapa karya. DTO adalah sebuah pola. Root agregat adalah sebuah pola, View Model adalah sebuah pola (mis. MVC & MVVM). POCO bukan sebuah pola.

POCO tidak menjelaskan suatu pola. Ini hanya cara berbeda untuk merujuk ke kelas / objek di OOP. Anggap saja sebagai konsep abstrak; mereka bisa merujuk pada apa saja. IMO, ada hubungan satu arah meskipun karena begitu suatu objek mencapai titik di mana ia hanya dapat melayani satu tujuan dengan bersih, itu bukan lagi POCO. Misalnya, setelah Anda menandai kelas Anda dengan dekorasi untuk membuatnya bekerja dengan beberapa kerangka kerja, itu bukan lagi POCO. Karena itu:

  • DTO adalah POCO
  • POCO bukan DTO
  • Model Tampilan adalah POCO
  • POCO bukan Model Tampilan

Poin dalam membuat perbedaan antara keduanya adalah tentang menjaga pola yang jelas dan konsisten dalam upaya untuk tidak melintasi masalah dan mengarah pada penggabungan yang ketat. Sebagai contoh jika Anda memiliki objek bisnis yang memiliki metode untuk bermutasi, tetapi juga dihiasi dengan dekorasi EF untuk disimpan ke SQL Server DAN JsonProperty sehingga dapat dikirim kembali melalui titik akhir API. Objek itu akan tidak toleran untuk berubah, dan kemungkinan akan dikotori dengan varian properti (misalnya UserId, UserPk, UserKey, UserGuid, di mana beberapa dari mereka ditandai untuk tidak disimpan ke DB dan yang lain ditandai untuk tidak diserialisasi ke JSON di titik akhir API).

Jadi, jika Anda memberi tahu saya bahwa ada sesuatu yang merupakan DTO, maka saya mungkin akan memastikan bahwa itu tidak pernah digunakan untuk hal lain selain mengubah keadaan. Jika Anda memberi tahu saya bahwa ada sesuatu yang merupakan model tampilan, maka saya mungkin akan memastikan itu tidak disimpan ke basis data. Jika Anda memberi tahu saya bahwa ada sesuatu yang merupakan Model Domain, maka saya mungkin akan memastikan tidak ada ketergantungan pada apa pun di luar domain. Tetapi jika Anda mengatakan kepada saya bahwa ada sesuatu yang disebut POCO, Anda tidak akan benar-benar memberi tahu saya sama sekali.

Sinaesthetic
sumber
-13

Jangan panggil mereka DTO. Mereka disebut Model .... Periode. Model tidak pernah memiliki perilaku. Saya tidak tahu siapa yang datang dengan DTO istilah bodoh ini, tetapi itu harus menjadi .NET yang bisa saya pikirkan. Pikirkan model tampilan di MVC, bendungan yang sama ** hal, model digunakan untuk mentransfer keadaan antara sisi server lapisan atau selama periode kawat, mereka semua model. Properti dengan data. Ini adalah model yang Anda lewati. Model, Model Model. Itu dia.

Saya berharap istilah bodoh DTO akan pergi dari kosakata kami.

PositiveGuy
sumber
1
saya tidak tahu dari mana Anda mendapat ide bahwa model tidak pernah memiliki perilaku. Bagaimana Anda membuat model selain CRUD tanpa perilaku pemodelan? Bahkan ViewModels memiliki perilaku dalam banyak kasus, terutama di aplikasi MVVM. DTO adalah istilah yang berguna karena secara akurat menggambarkan tujuan; untuk mentransfer data.
Gerald
9
downvoted karena secara faktual salah, dan untuk sikap pontificating.
joedotnot
Omong kosong. Model harus wadah bodoh. Tidak ada DTO, ini adalah istilah MS. Anda mentransfer model antara domain, layanan, dan aplikasi. Titik. DTO adalah pemborosan istilah yang tidak diperlukan dan hanya membingungkan banyak hal. Model, Model, dan banyak lagi Model itu saja. Model mungkin memiliki perilaku atau tidak. Lihat Model seharusnya tidak. Perilaku itu harus dalam BL, bukan di kelas Model.
PositiveGuy
Saya setuju bahwa DTO adalah Model fungsional. ViewModels memiliki perilaku dan apa yang Anda ikat di MVVM. NAMUN, saya menulis sebuah aplikasi di mana Model saya lebih cerdas (pada dasarnya VM tetapi saya tidak ingin memanggil mereka daripada) dan mereka "menerima" objek DTO. Ini memungkinkan saya untuk memiliki lebih banyak opsi dengan kerangka kerja. Jadi dari CRUD (atau bahkan EF), saya akan mengirimkan objek melalui layanan WCF dan menerima objek DTO dan merangkumnya (menambahkan OnProp Change, dll). ViewModels saya melakukan enkapsulasi lebih lanjut dan mungkin telah menerima dua (atau daftar) "Model". Definisi yang kaku adalah VM.
SQLMason
"Anda mentransfer model antara domain, layanan, dan aplikasi" Mengapa menurut Anda istilah model lebih tepat dan pas daripada istilah DTO untuk perilaku yang Anda uraikan ini?
caa