Apakah objek yang tidak berubah dan DDD berjalan bersama?

18

Pertimbangkan sistem yang menggunakan DDD (juga: sistem apa pun yang menggunakan ORM). Inti dari sistem apa pun secara realistis, dalam hampir setiap kasus penggunaan, adalah memanipulasi objek domain tersebut. Kalau tidak, tidak ada efek atau tujuan nyata.

Memodifikasi objek yang tidak dapat diubah akan menyebabkannya untuk menghasilkan catatan baru setelah objek bertahan yang membuat gembung besar dalam sumber data (kecuali Anda menghapus catatan sebelumnya setelah modifikasi).

Saya dapat melihat manfaat dari menggunakan objek yang tidak dapat diubah, tetapi dalam hal ini, saya tidak pernah bisa melihat kasus yang berguna untuk menggunakan objek yang tidak dapat diubah. Apakah ini salah?

Steven Evers
sumber

Jawaban:

16

Komputasi dengan menggunakan objek yang tidak dapat diubah (seperti dalam pemrograman fungsional) tidak selalu berarti setiap objek yang dihasilkan tetap ada!

Steven A. Lowe
sumber
Saya tidak melihat contoh di mana skenario itu menggunakan benda-benda abadi - jadi mereka akan ada di sana tanpa tujuan tertentu. Apakah aku salah?
Steven Evers
1
Saya berpikir bahwa objek yang tidak dapat diubah akan berguna untuk perhitungan menengah (dalam utas paralel)
Steven A. Lowe
11

Apakah tidak berubah dalam domain berarti harus tidak berubah dalam database? Sebagai contoh pertimbangkan hal berikut dengan asumsi pelanggan selalu memiliki satu alamat:

customer.address = new Address('My Castle', 'Kings street');
customer_repo.save(customer);

sekarang sql berikut dijalankan mengingat id pelanggan adalah 1:

INSERT INTO addresses (customer_id, name, street)
VALUES (1, 'My Castle', 'Kings street');

sekarang perubahan berikut dibuat ke alamat:

customer.address = new Address('Pauper palace', 'Outlands');
customer_repo.save(customer);

dan lapisan kegigihan, menjadi sangat pintar menjalankan sql berikut:

UPDATE addresses SET name='Pauper palance', street='Outlands'
WHERE customer_id = 1;

Dengan cara ini Anda menghindari overhead pernyataan DELETE AND INSERT yang terpisah. Juga saya pikir beberapa RDBMS memiliki INSERT REPLACE atau sesuatu. MySql memiliki REPLACE .

andho
sumber
+1 Saya setuju dengan Anda pada prinsip umum: Saya tidak melihat mengapa objek domain yang tidak dapat berubah harus berarti baris DB yang tidak dapat diubah.
Andres F.
Dalam kasus di atas jika kita perlu mengubah atribut kota dari kelas alamat untuk pelanggan tertentu bagaimana kita menanganinya?, Lebih jauh menganggap pelanggan dapat memiliki beberapa alamat sehingga itu adalah hubungan satu ke banyak hubungan antara pelanggan dan alamat
Sudarshan
1
@ Sudarshan ini hanya cara untuk membuat 'objek nilai tidak berubah', tidak benar-benar tidak berubah dalam database. Untuk alasan kinerja. Setiap situasi perlu ditangani secara khusus tentu saja. Saya lebih suka Sumber Acara untuk Domain saya sekarang, tetapi saya agak kecanduan.
andho
@Sudarshan untuk menjawab pertanyaan Anda secara khusus, Anda hanya menjalankan kueri pembaruan yang memperbarui baris ke nilai baru. Jika itu satu-ke-banyak, maka alamat akan memiliki semacam pengidentifikasi dalam Root Agregat Pelanggan yang akan digunakan untuk mengidentifikasi secara unik dalam DB. Kemudian pengidentifikasi dan customer_id ini akan digunakan untuk memperbarui baris itu di tabel 'alamat'.
andho
@ andho "ini hanya cara untuk membuat 'objek nilai yang tidak berubah', tidak benar-benar tidak berubah dalam database." ini benar-benar membuat hari saya berterima kasih
Sudarshan
6

Dalam DDD, objek yang tidak dapat diubah cukup menyamakan dengan objek bernilai. Objek-objek ini bukan entitas, mereka tidak memiliki identitas. Oleh karena itu saya selalu mempertahankan nilai objek sebagai kolom dari entitas tempat mereka berada (dengan N / Hibernate Anda dapat menggunakan Komponen untuk itu). Mereka tidak punya meja sendiri.

guillaume31
sumber
4

Itu tergantung pada bagaimana objek yang tidak dapat diubah dipetakan dalam database. Jika itu hanya komponen seperti DateTime (dari perpustakaan Joda Time) maka mengubah nilai akan menghasilkan pembaruan daripada menyisipkan. Namun, jika immutable lebih kompleks membutuhkan baris dalam sebuah tabel maka Anda punya masalah mengasapi.

Saya kira, meskipun ini argumen yang lemah, Anda bisa menerapkan jejak audit dengan cara ini. Setiap perubahan pada immmutable dapat dilacak melalui sisipan. Ada banyak cara yang lebih baik untuk melakukan ini.

Semua dalam semua memiliki objek domain abadi (bukan hanya komponen mereka) tampaknya sedikit ketidakcocokan dengan kegigihan.

Gary Rowe
sumber
Tidak semuanya. Komponen sangat berguna karena memungkinkan objek domain disusun berbeda dari data dasar yang sama. Masalahnya datang dengan menegakkan kekekalan. Secara pribadi, saya akan memperlakukan objek domain sebagai bisa berubah (dengan pengecualian bidang kunci utama) dan tetap sederhana.
Gary Rowe
"Semuanya memiliki objek domain yang tidak dapat diubah (alih-alih hanya komponen mereka) tampaknya sedikit tidak cocok dengan kegigihan." Menurut pendapat Anda, di mana kita perlu memiliki objek nilai yang tidak boleh dimodelkan sebagai komponen (terminologi Hibernate)? --- Maaf saya salah mengetik komentar terakhir saya dan karenanya menghapusnya.
Sudarshan
Hindari komponen ketika satu entitas sepenuhnya diwakili oleh satu baris dan tidak ada data yang dibagikan oleh objek domain lain.
Gary Rowe
4

Itu tergantung pada domain. DDD tidak menentukan bahwa paradigma pemrograman berorientasi objek. Namun paradigma berorientasi objek sangat cocok untuk aplikasi khas yang harus dipertahankan dalam database.

DDD hanya menyatakan bahwa Anda harus membangun perangkat lunak Anda di sekitar model domain yang mewakili masalah aktual yang coba dipecahkan oleh perangkat lunak. Jika masalah itu misalnya matematis pada dasarnya, maka mengimplementasikan lapisan domain menggunakan pemrograman fungsional dan struktur data yang tidak dapat diubah akan sangat masuk akal.

Jika di sisi lain, masalahnya adalah lebih dari aplikasi perusahaan biasa, dan Anda menggunakan struktur objek yang tidak dapat diubah untuk semua objek domain Anda, maka saya berpendapat bahwa Anda tidak mengikuti DDD. Saya dapat mengajukan setidaknya dua argumen:

  • Implementasi Anda tidak mewakili model domain dari domain masalah Anda. Domain masalah Anda dalam hal ini terdiri dari entitas yang memiliki status untuk diubah. Dan bukan itu cara Anda menerapkannya.

  • Anda tidak memiliki bahasa di mana-mana. Bahasa dan konsep dalam model domain tidak mengikuti apa yang digunakan pakar domain.

Catatan: DDD memang menggunakan objek yang tidak dapat diubah di mana sesuai, mereka hanya disebut objek nilai.

Jadi saya tidak mengatakan bahwa Anda tidak dapat membuat aplikasi database menggunakan struktur data yang berfungsi murni, dan saya tidak mengatakan bahwa Anda seharusnya tidak. Saya hanya tidak berpikir Anda bisa menyebutnya DDD, tergantung pada jenis aplikasi

Pete
sumber
Peter, jawaban yang bagus. Bisakah Anda melihat pertanyaan saya di sini stackoverflow.com/questions/13783666/… dan bantu saya mencari tahu masalah saya. Saya pikir objek nilai tidak berubah bagus untuk perangkat lunak yang tidak terkait perusahaan. Sebagian besar objek aplikasi perusahaan bisa berubah menurut pendapat saya. Bayangkan memiliki objek nilai deep-nested yang tidak dapat diubah ... ContactInfo-> PhysicalLocation-> Address dan Anda ingin memperbarui kode pos ... membuat bagan seluruh grafik objek bagi saya antikristus, bukan hanya antiputern. Bagaimana menurut anda?
Pepito Fernandez
3

Jika Anda menggunakan ORM seperti Hibernate / NHibernate Anda dapat mengatur opsi kaskade Anda untuk secara otomatis menghapus objek yatim. Jika seseorang memiliki alamat objek nilai, ketika Anda mengubah alamat, yang baru akan disimpan dan yang lama dihapus karena sekarang menjadi yatim piatu.

Mike Rowley
sumber
0

Nilai objek hampir selalu berubah dalam DDD dan pola kelas terbang dapat digunakan untuk menjaga duplikasi objek nilai itu dalam memori seperti halnya .NET lakukan dengan string. Tradeoff utama adalah memori satu sisi dan sisi lain adalah efisiensi penciptaan. Dengan pola kelas terbang, perbandingan berbasis nilai harus dilakukan untuk menentukan apakah objek nilai baru atau yang dilarutkan sudah ada dalam cache kelas terbang tetapi perbandingan lain setelah titik itu secara umum dapat dilakukan dengan aman dengan referensi karena satu contoh diterapkan. Either way apakah kelas terbang digunakan atau tidak, objek nilai masih dibuat abadi karena mereka hanya memiliki identitas intrinsik dan dengan demikian mengubah nilainya akan mengubah identitas mereka.

jpierson
sumber
-1

Ada cara lain untuk menggunakan objek yang tidak dapat diubah ...

Alih-alih menyimpan nilai 5.0, 6.0, 7.0, 8.0 dan menyalin seluruh catatan setiap kali, Anda dapat menyimpan sesuatu seperti ini: 5.0, +1.0, +1.0, +1.0, dan kemudian membangun dependensi dengan benar untuk merekonstruksi urutan 5.0 , 6.0, 7.0, 8.0. Dengan cara ini, modifikasi kecil hanya membutuhkan sedikit memori ...

tp1
sumber