Objek DDD dan Nilai. Apakah Object Nilai yang bisa berubah menjadi kandidat yang bagus untuk Non Aggr. Entitas root?

9

Ini sedikit masalah

Memiliki entitas, dengan objek nilai. Bukan masalah. Saya mengganti objek nilai untuk yang baru, lalu nhibernate menyisipkan nilai baru dan yatim piatu yang lama, lalu menghapusnya. Ok, itu masalah.

Tertanggung adalah entitas saya di domain saya. Dia memiliki koleksi Alamat (objek nilai). Salah satu alamat adalah Alamat Mailing. Ketika kita ingin memperbarui alamat surat, misalkan kode pos salah, mengikuti doktrin Tn. Evans, kita harus mengganti objek lama dengan yang baru karena tidak dapat diubah (objek nilai kan?).

Tapi kami tidak ingin menghapus baris Anda, karena PK alamat itu adalah FK di tabel MailingHistory. Jadi, mengikuti doktrin Tn. Evans, kita benar-benar kacau disini. Kecuali saya membuat Entitas addressses saya, jadi saya tidak perlu "menggantinya", dan cukup perbarui anggota kode posnya, seperti masa lalu yang baik.

Apa yang akan Anda sarankan untuk saya dalam kasus ini? Cara saya melihatnya, ValueObjects hanya berguna ketika Anda ingin merangkum sekelompok kolom tabel database (komponen dalam nhibernate). Segala sesuatu yang memiliki id kegigihan dalam database, lebih baik membuatnya menjadi Entity (tidak harus merupakan agregat root) sehingga Anda dapat memperbarui anggotanya tanpa membuat ulang seluruh objek grafik, terutama jika itu objek bersarang.

Apakah Anda setuju? Apakah diizinkan oleh Tn. Evans untuk memiliki objek nilai yang dapat berubah? Atau objek nilai yang bisa berubah kandidat untuk Entitas?

Terima kasih

Pepito Fernandez
sumber
2
Apakah ada yang namanya "objek nilai yang bisa berubah"? Saya selalu memiliki nilai objek kesan yang tidak berubah.
herby
@ Kalau saya kira Anda bisa memiliki objek yang bisa berubah yang mewakili objek nilai DDD dalam kode, tetapi Anda harus mempertimbangkan bahwa setelah Anda memutasikan objek, itu tidak mereferensikan objek nilai DDD logis yang sama lagi tetapi yang baru. Ini mungkin diinginkan tetapi itu resep untuk kebingungan imo - membuat nilai objek tidak berubah dalam kode adalah konvensi yang cerdas.
MattDavey

Jawaban:

8

Segala sesuatu yang memiliki identitas harus menjadi Entitas, dan segala sesuatu yang tidak memiliki identitas adalah nilai sederhana, karenanya merupakan objek nilai.

Mengutip Martin Fowler (yang pada gilirannya Qoutes Eric Evans)

  • Entity: Objek yang memiliki identitas berbeda yang berjalan melalui waktu dan representasi yang berbeda. Anda juga mendengar ini disebut "objek referensi".
  • Nilai Objek: Objek yang penting hanya memiliki kombinasi atribut mereka.

Alasan menjadikan alamat Anda sebagai Objek Nilai:

Jika alamat Anda bisa berubah, Anda mungkin akan mengacaukan riwayat pengiriman surat Anda pada akhirnya. Misalnya, jika Anda mengirim barang ke pelanggan, Anda tidak dapat memastikan ke alamat mana Anda benar-benar mengirim sesuatu di masa lalu jika alamat yang dirujuk oleh tabel MailingHistory Anda telah diubah.

Entri MailingHistory Kami mengirim A764 ke alamat 657 bisa berarti Kami mengirim artikel A764 ke Boston kemarin dan Kami mengirim artikel A764 ke New York besok.

Jika alamat surat harus diubah, tidak perlu menghapus yang lama. Simpan, dan tandai sebagai tidak aktif , dan yang baru aktif .


Tentu saja Anda dapat memperlakukan alamat Anda sebagai Entitas, tetapi hanya saat memperbarui itu tidak akan mengubah tempat sebenarnya yang dirujuk oleh alamat, karenanya hanya mengizinkan koreksi kesalahan ketik.

Jika Anda yakin dapat memastikan hal itu, daripada menggunakan Entitas adalah mungkin.


Tetapi solusi terbaik IMHO adalah tidak mereferensikan Entitas alamat dalam riwayat pengiriman surat Anda, melainkan menyimpan alamat khusus secara langsung di tabel riwayat pengiriman surat Anda (pada dasarnya menyalin data alamat).

Dengan cara ini, Anda selalu tahu di mana Anda mengirim barang-barang Anda (atau apa pun yang Anda kirim), dan karena Anda akan menggunakan Entitas yang bisa berubah, tabel alamat Anda tidak akan berantakan.

Saya telah bekerja dengan / pada beberapa sistem ERP, dan hampir semuanya menggunakan pendekatan ini.

Anda akan memiliki beberapa redundansi di database Anda, tetapi ini adalah cara IMHO yang paling pragmatis.

kemalasan
sumber
Ini mungkin solusi yang paling bebas sakit kepala. Hanya jika Anda berharap bahwa saluran komunikasi di masa depan akan membutuhkan kolom tambahan, dan database Anda terlalu besar untuk ALTER, menggunakan entitas dalam tabel terpisah mungkin menjadi perlu. Itu, pada gilirannya, panggilan untuk strategi seperti "selalu bergabung dengan terbaru alamat / telepon / e-mail" dalam SELECTpertanyaan, yang menantang untuk menjaga dipertahankan dan efisien. Sederhanakan, jika memungkinkan.
Timo
@Timo "selalu bergabung dengan alamat / telepon / email terbaru" tidak sulit jika Anda mendenormalkan data Anda sedikit dengan hanya menambahkan active-flag. Tentu saja Anda harus memastikan untuk selalu menggunakan and active = truedalam Bergabung Anda, menjaga bendera tetap up-to-date dan menambahkan contraint ke meja Anda sehingga mis. Hanya satu email untuk setiap pelanggan dapat memiliki bendera ini disetel ke true.
sloth
Ini memperkenalkan masalah menonaktifkan yang sebelumnya. Jika Anda telah mengganti objek alamat "saat ini" Anda dalam kode, dan Anda pergi ke kode akses data Anda, maka itu tidak akan tahu (1) apakah ada yang baru, atau (2) apa yang berpotensi lama satu adalah. Jadi setiap operasi penyimpanan harus melakukan sesuatu yang berbelit-belit seperti "pertama pergi dan menonaktifkan semua alamat terkait dalam database", dan kemudian menyimpan yang sekarang dengan active=true. Ini bukan apa yang saya sebut sederhana, itulah sebabnya saya suka solusi Anda.
Timo
2

Saya melihat 2 hal:

  1. Apakah boleh mengubah kode pos untuk memengaruhi catatan riwayat? Saya pikir akan logis jika catatan sejarah menunjuk ke alamat lama yang tidak diubah, sehingga Anda tahu Anda mengirimnya ke alamat yang salah.

  2. Saat MailingHistory memiliki FK pada alamat, alamat berhenti menjadi objek nilai dan menjadi entitas. Objek nilai tidak memiliki identitas, yang memungkinkan entitas lain mereferensikan identitas ini. Anda dapat memiliki alamat dalam satu tabel dengan tabel lain menunjuk ke sana, tetapi hanya efeknya yang menghemat ruang. Dari sudut pandang domain, jika dua entitas memiliki referensi yang sama jenis objek nilai, maka mereka tidak berbagi informasi apa pun.

Euforia
sumber
2

IMO objek alamat adalah entitas di domain Anda. Ini dibagikan oleh banyak entitas, memiliki identitas sendiri dan unik di seluruh sistem.

Evans mengatakan:

Objek yang didefinisikan terutama oleh identitasnya disebut entitas.

margabit
sumber
Identitas domain, menurut pemahaman saya, tidak ada hubungannya dengan identitas kegigihan. Menurut buku Pak Evan.
Pepito Fernandez
Kamu benar. Saya mengedit jawaban saya. Maksud saya adalah bahwa objek alamat itu penting di domain spesifik ini, itu unik. IMO the Foreign Key dan Primary Key adalah tanda bahwa itu sebenarnya objek unik di seluruh domain, sehingga memiliki identitas.
margabit
1
"objek alamat ... memiliki identitasnya sendiri" - atribut alamat mana yang secara unik mengidentifikasinya? Tidak ada atribut tunggal dari alamat yang unik, tetapi kombinasi atribut berfungsi sebagai identitas. Ini adalah definisi utama dari objek nilai
MattDavey
@MattDavey: ini kesimpulan yang bagus, tapi saya bingung ketika Tony mengatakan "kami tidak ingin menghapus baris, karena alamat PK itu adalah FK di tabel MailingHistory". Ini berarti bagi saya bahwa objek Alamat juga memiliki makna di luar Agregat 'Tertanggung'. Yang menunjukkan kepada saya bahwa objek 'Alamat' tidak boleh menjadi ValueObject. Bagaimana menurut anda?
margabit
Bisakah kita mengatakan bahwa Value Objects akan selalu menjadi komposisi sepenuhnya dimiliki (UML) oleh induknya? Selain itu, Obyek Nilai tidak akan masuk akal tanpa Induknya dan tidak dapat dibagikan di antara Induk?
Sudarshan