Saya sedang mendesain ulang aplikasi berskala besar, kami menggunakan arsitektur multi-layer berdasarkan DDD.
Kami memiliki MVC dengan lapisan data (implementasi repositori), lapisan domain (definisi model domain dan antarmuka - repositori, layanan, unit kerja), lapisan layanan (implementasi layanan). Sejauh ini, kami menggunakan model domain (sebagian besar entitas) di semua lapisan, dan kami menggunakan DTO hanya sebagai model tampilan (di controller, layanan mengembalikan model domain (s) dan controller membuat model tampilan, yang diteruskan ke tampilan).
Saya sudah membaca banyak artikel tentang menggunakan, tidak menggunakan, memetakan dan melewati DTO. Saya mengerti bahwa tidak ada jawaban pasti, tetapi saya tidak yakin apakah itu ok atau tidak mengembalikan model domain dari layanan ke pengontrol. Jika saya mengembalikan model domain, itu masih tidak pernah diteruskan ke tampilan, karena pengontrol selalu membuat model tampilan khusus tampilan - dalam hal ini, tampaknya sah. Di sisi lain, rasanya tidak benar ketika model domain meninggalkan lapisan bisnis (lapisan layanan). Terkadang layanan perlu mengembalikan objek data yang tidak didefinisikan dalam domain dan kemudian kami harus menambahkan objek baru ke domain yang tidak dipetakan, atau membuat objek POCO (ini jelek, karena beberapa layanan mengembalikan model domain, beberapa mengembalikan DTO secara efektif).
Pertanyaannya adalah - jika kita benar-benar menggunakan model tampilan, apakah boleh mengembalikan model domain sepenuhnya ke pengontrol, atau haruskah kita selalu menggunakan DTO untuk komunikasi dengan lapisan layanan? Jika demikian, apakah boleh menyesuaikan model domain berdasarkan kebutuhan layanan apa? (Sejujurnya saya tidak berpikir begitu, karena layanan harus menggunakan domain apa yang dimiliki.) Jika kita harus tetap berpegang teguh pada DTO, haruskah mereka didefinisikan di lapisan layanan? (Saya pikir begitu.) Kadang-kadang jelas bahwa kita harus menggunakan DTO (misalnya, ketika layanan melakukan banyak logika bisnis dan membuat objek baru), kadang-kadang jelas bahwa kita harus menggunakan model domain yang adil (misalnya, ketika layanan Keanggotaan mengembalikan Pengguna yang anemia ( s) - sepertinya tidak masuk akal untuk membuat DTO yang sama dengan model domain) - tapi saya lebih suka konsistensi dan praktik yang baik.
Domain Artikel vs DTO vs ViewModel - Bagaimana dan Kapan menggunakannya? (dan juga beberapa artikel lainnya) sangat mirip dengan masalah saya, tetapi tidak menjawab pertanyaan ini. Artikel Haruskah saya menerapkan DTO dalam pola repositori dengan EF? juga mirip, tetapi tidak berurusan dengan DDD.
Penafian: Saya tidak bermaksud menggunakan pola desain apa pun hanya karena ada dan mewah, di sisi lain, saya ingin menggunakan pola dan praktik desain yang baik juga karena membantu merancang aplikasi secara keseluruhan, membantu pemisahan masalah, bahkan untuk menggunakan pola tertentu tidak "diperlukan", setidaknya saat ini.
Seperti biasa, terima kasih.
sumber
Jawaban:
Membuat Anda merasa seperti menarik keluar nyali bukan? Menurut Martin Fowler: Lapisan Layanan menentukan batas aplikasi, itu merangkum domain. Dengan kata lain itu melindungi domain.
Bisakah Anda memberikan contoh objek data ini?
Ya, karena responsnya adalah bagian dari lapisan layanan Anda. Jika itu didefinisikan "di tempat lain" maka lapisan layanan perlu merujuk bahwa "di tempat lain", menambahkan lapisan baru ke lasagna Anda.
DTO adalah objek respons / permintaan, masuk akal jika Anda menggunakannya untuk komunikasi. Jika Anda menggunakan model domain di lapisan presentasi Anda (MVC-Controllers / View, WebForms, ConsoleApp), maka lapisan presentasi digabungkan erat ke domain Anda, setiap perubahan dalam domain mengharuskan Anda untuk mengubah pengontrol Anda.
Ini adalah salah satu kelemahan DTO di mata baru. Saat ini, Anda sedang berpikir duplikasi kode , tetapi ketika proyek Anda diperluas maka akan jauh lebih masuk akal, khususnya di lingkungan tim di mana tim yang berbeda ditugaskan ke lapisan yang berbeda.
DTO mungkin menambah kompleksitas tambahan untuk aplikasi Anda, tetapi begitu juga layer Anda. DTO adalah fitur mahal dari sistem Anda, mereka tidak datang gratis.
Mengapa menggunakan DTO
Artikel ini memberikan keuntungan dan kerugian menggunakan DTO, http://guntherpopp.blogspot.com/2010/09/to-dto-or-not-to-dto.html
Ringkasan sebagai berikut:
Kapan Harus Digunakan
Kapan tidak digunakan
Argumen Melawan DTO
Argumen dengan DTO
sumber
Tampaknya aplikasi Anda cukup besar dan kompleks karena Anda telah memutuskan untuk melakukan pendekatan DDD. Jangan kembalikan entitas poco Anda atau yang disebut entitas domain dan objek nilai di lapisan layanan Anda. Jika Anda ingin melakukan ini, hapus layer layanan Anda karena Anda tidak membutuhkannya lagi! Lihat Model atau objek transfer Data harus hidup di lapisan Layanan karena mereka harus memetakan ke anggota model domain dan sebaliknya. Jadi mengapa Anda perlu memiliki DTO? Dalam aplikasi yang kompleks dengan banyak skenario Anda harus memisahkan keprihatinan domain dan tampilan presentasi Anda, model domain dapat dibagi menjadi beberapa DTO dan juga beberapa model Domain dapat diciutkan menjadi DTO. Jadi lebih baik untuk membuat DTO Anda dalam arsitektur berlapis bahkan itu akan sama dengan model Anda.
Haruskah kita selalu menggunakan DTO untuk komunikasi dengan lapisan layanan? Ya, Anda harus mengembalikan DTO oleh lapisan layanan Anda karena Anda telah berbicara dengan repositori Anda di lapisan layanan dengan anggota model domain dan memetakannya ke DTO dan kembali ke pengontrol MVC dan sebaliknya.
Apakah boleh untuk menyesuaikan model domain berdasarkan kebutuhan layanan apa? Sebuah layanan hanya berbicara dengan repositori dan metode domain serta layanan domain, Anda harus menyelesaikan bisnis di domain Anda berdasarkan kebutuhan Anda dan itu bukan tugas layanan untuk memberi tahu domain apa yang dibutuhkan.
Jika kita harus berpegang teguh pada DTO, haruskah mereka didefinisikan di lapisan layanan? Ya, coba miliki DTO atau ViewModel hanya dalam layanan nanti karena mereka harus dipetakan ke anggota domain di lapisan layanan dan itu bukan ide yang baik untuk menempatkan DTO di pengontrol aplikasi Anda (coba gunakan pola Respons Permintaan di lapisan Layanan Anda), tepuk tangan !
sumber
Dalam pengalaman saya, Anda harus melakukan apa yang praktis. "Desain terbaik adalah desain paling sederhana yang berfungsi" - Einstein. Dengan itu adalah pikiran ...
Benar-benar tidak apa-apa! Jika Anda memiliki Entitas Domain, DTO, dan Lihat Model, kemudian sertakan tabel database Anda memiliki semua bidang dalam aplikasi diulang di 4 tempat. Saya telah bekerja pada proyek besar di mana Entitas Domain dan Model Tampilan bekerja dengan baik. Satu-satunya pengecualian untuk ini adalah jika aplikasi didistribusikan dan lapisan layanan berada di server lain dalam hal ini DTO diminta untuk mengirim melalui kawat untuk alasan serialisasi.
Secara umum saya setuju dan mengatakan tidak karena model Domain biasanya merupakan cerminan dari logika bisnis dan biasanya tidak dibentuk oleh konsumen logika itu.
Jika Anda memutuskan untuk menggunakannya, saya setuju dan mengatakan ya, lapisan Layanan adalah tempat yang sempurna karena mengembalikan DTO pada akhir hari.
Semoga berhasil!
sumber
Saya terlambat ke pesta ini, tetapi ini adalah pertanyaan yang umum, dan penting, sehingga saya merasa harus menanggapinya.
Yang dimaksud dengan "layanan", maksud Anda "Lapisan Aplikasi" yang dijelaskan oleh Evan dalam buku biru ? Saya akan menganggap Anda melakukannya, dalam hal ini jawabannya adalah bahwa mereka tidak boleh mengembalikan DTO. Saya sarankan membaca bab 4 dalam buku biru, berjudul "Isolating the Domain".
Dalam bab itu, Evans mengatakan hal berikut tentang lapisan:
Ada alasan bagus untuk ini. Jika Anda menggunakan konsep urutan parsial sebagai ukuran kompleksitas perangkat lunak maka memiliki lapisan yang bergantung pada lapisan di atasnya akan menambah kompleksitas, yang menurunkan kemampuan pemeliharaan.
Menerapkan ini untuk pertanyaan Anda, DTO benar-benar merupakan adaptor yang menjadi perhatian lapisan User Interface / Presentation. Ingatlah bahwa komunikasi jarak jauh / lintas-proses adalah persis tujuan DTO (perlu dicatat bahwa dalam pos itu Fowler juga berpendapat bahwa DTO menjadi bagian dari lapisan layanan, meskipun ia tidak harus berbicara bahasa DDD).
Jika lapisan aplikasi Anda bergantung pada DTO tersebut, itu tergantung pada lapisan di atasnya dan kompleksitas Anda meningkat. Saya dapat menjamin bahwa ini akan meningkatkan kesulitan memelihara perangkat lunak Anda.
Misalnya, bagaimana jika sistem Anda berinteraksi dengan beberapa sistem atau tipe klien lain, masing-masing membutuhkan DTO sendiri? Bagaimana Anda tahu metode DTO mana yang harus dikembalikan oleh layanan aplikasi Anda? Bagaimana Anda bahkan memecahkan masalah itu jika bahasa pilihan Anda tidak memungkinkan kelebihan metode (metode layanan, dalam hal ini) berdasarkan jenis pengembalian? Dan bahkan jika Anda mencari cara, mengapa melanggar Layer Aplikasi Anda untuk mendukung masalah lapisan Presentasi?
Secara praktis, ini adalah langkah menurun yang akan berakhir dengan arsitektur spageti. Saya telah melihat devolusi semacam ini dan hasilnya dalam pengalaman saya sendiri.
Di mana saya saat ini bekerja, layanan di Layer Aplikasi kami mengembalikan objek domain. Kami tidak menganggap ini masalah karena lapisan Antarmuka (yaitu UI / Presentasi) tergantung pada lapisan Domain, yang berada di bawahnya. Juga, ketergantungan ini diminimalkan ke jenis ketergantungan "hanya referensi" karena:
a) Lapisan Antarmuka hanya dapat mengakses objek-objek Domain ini sebagai nilai kembali hanya-baca yang diperoleh melalui panggilan ke lapisan Aplikasi
b) metode pada layanan dalam Lapisan Aplikasi menerima sebagai input hanya input "mentah" (nilai data) atau parameter objek (untuk mengurangi jumlah parameter bila perlu) didefinisikan dalam lapisan itu. Secara khusus, layanan aplikasi tidak pernah menerima objek Domain sebagai input.
Layer Interface menggunakan teknik pemetaan yang didefinisikan dalam Layer Interface itu sendiri untuk memetakan dari objek Domain ke DTO. Sekali lagi, ini membuat DTO fokus pada menjadi adaptor yang dikendalikan oleh Layer Interface.
sumber
Terlambat ke pesta, tapi saya menghadapi jenis arsitektur yang sama persis dan saya condong ke "hanya DTO dari layanan". Ini terutama karena saya telah memutuskan untuk hanya menggunakan objek / agregat domain untuk mempertahankan validitas dalam objek, sehingga hanya ketika memperbarui, membuat, atau menghapus. Saat kami meminta data, kami hanya menggunakan EF sebagai repositori dan memetakan hasilnya ke DTO. Ini membuat kami bebas untuk mengoptimalkan kueri baca dan tidak menyesuaikannya dengan objek bisnis, sering menggunakan fungsi basis data karena cepat.
Setiap metode layanan mendefinisikan kontraknya sendiri dan karenanya lebih mudah untuk mempertahankannya dari waktu ke waktu. Saya harap.
sumber
Karena Model Domain menyediakan terminologi ( Bahasa yang Tidak Dapat Ditebak ) untuk seluruh aplikasi Anda, lebih baik menggunakan Model Domain secara luas.
Satu-satunya alasan untuk menggunakan ViewModels / DTO adalah implementasi pola MVC dalam aplikasi Anda untuk memisahkan
View
(segala jenis lapisan presentasi) danModel
(Model Domain). Dalam hal ini, presentasi dan model domain Anda secara longgar digabungkan.Saya berasumsi bahwa Anda berbicara tentang layanan Logika Aplikasi / Bisnis / Domain.
Saya sarankan Anda mengembalikan entitas domain saat Anda bisa. Jika diperlukan untuk mengembalikan informasi tambahan, dapat diterima untuk mengembalikan DTO yang memiliki beberapa entitas domain.
Kadang-kadang, orang-orang yang menggunakan kerangka kerja bagian 3, yang menghasilkan proxy atas entitas domain, menghadapi kesulitan mengekspos entitas domain dari layanan mereka, tetapi itu hanya masalah penggunaan yang salah.
Saya akan mengatakan itu cukup untuk mengembalikan entitas domain dalam 99,9% kasus.
Untuk menyederhanakan pembuatan DTO dan memetakan entitas domain Anda ke dalamnya, Anda dapat menggunakan AutoMapper .
sumber
Jika Anda mengembalikan bagian dari model domain Anda, itu menjadi bagian dari kontrak. Kontrak sulit untuk diubah, karena hal-hal di luar konteks Anda bergantung padanya. Dengan demikian, Anda akan membuat bagian dari model domain Anda sulit diubah.
Aspek yang sangat penting dari model domain adalah mudah diubah. Ini membuat kami fleksibel terhadap persyaratan perubahan domain.
sumber
Saya sarankan menganalisis dua pertanyaan ini:
Apakah lapisan atas Anda (yaitu melihat & melihat model / pengontrol) mengonsumsi data dengan cara yang berbeda dari apa yang ditampilkan lapisan domain? Jika ada banyak pemetaan yang dilakukan atau bahkan logika yang terlibat saya akan menyarankan mengunjungi kembali desain Anda: mungkin harus lebih dekat dengan bagaimana data sebenarnya digunakan.
Seberapa besar kemungkinan Anda mengubah lapisan atas Anda? (mis. menukar ASP.NET untuk WPF). Jika ini sangat berbeda dan arsitektur Anda tidak terlalu kompleks, Anda mungkin lebih baik mengekspos entitas domain sebanyak yang Anda bisa.
Saya khawatir itu adalah topik yang cukup luas dan benar-benar turun ke seberapa rumit sistem Anda dan persyaratannya.
sumber
Dalam pengalaman saya, kecuali Anda menggunakan pola OO UI (seperti objek telanjang), mengekspos objek domain ke UI adalah ide yang buruk. Ini karena seiring pertumbuhan aplikasi, kebutuhan dari UI berubah dan memaksa objek Anda untuk mengakomodasi perubahan tersebut. Anda akhirnya melayani 2 master: UI dan DOMAIN yang merupakan pengalaman yang sangat menyakitkan. Percayalah, Anda tidak ingin berada di sana. Model UI memiliki fungsi berkomunikasi dengan pengguna, model DOMAIN untuk memegang aturan bisnis dan model ketekunan berkaitan dengan menyimpan data secara efektif. Mereka semua menangani berbagai kebutuhan aplikasi. Saya di tengah menulis posting blog tentang ini, akan menambahkannya ketika sudah selesai.
sumber