Tanggung jawab tunggal (alasan untuk berubah) dari suatu entitas harus secara unik mengidentifikasi dirinya sendiri, dengan kata lain, tanggung jawabnya harus dapat ditemukan.
Buku DDD Eric Evan, hal. 93:
tanggung jawab paling mendasar dari Entitas adalah untuk membangun kesinambungan sehingga perilaku dapat menjadi jelas dan dapat diprediksi. Mereka melakukan yang terbaik jika disimpan. Daripada berfokus pada atribut atau bahkan perilaku, lepaskan definisi objek Entitas ke karakteristik yang paling intrinsik, terutama yang mengidentifikasi atau biasa digunakan untuk menemukan atau mencocokkannya. Tambahkan hanya perilaku yang penting untuk konsep dan atribut yang diperlukan oleh perilaku itu.
Di luar itu, terlihat untuk menghapus perilaku dan atribut ke objek lain yang terkait dengan Entitas inti. Selain masalah identitas, Entitas cenderung memenuhi tanggung jawab mereka dengan mengoordinasikan operasi objek yang mereka miliki.
1.
... lepaskan definisi objek ENTITY ke karakteristik paling intrinsik, terutama yang mengidentifikasinya atau yang biasa digunakan untuk menemukan atau mencocokkannya. Tambahkan hanya perilaku yang penting untuk konsep ...
Setelah suatu entitas diberi ID unik , identitasnya dibuat dan jadi saya akan berasumsi entitas seperti itu tidak memerlukan perilaku untuk mempertahankan identitasnya atau membantunya mengidentifikasi dirinya . Jadi, saya tidak mengerti perilaku seperti apa yang penulis maksudkan (selain find
dan match
operasi ) dengan " perilaku yang penting untuk konsep "?
2.
... lepaskan definisi objek ENTITY ke karakteristik paling intrinsik, terutama yang mengidentifikasinya atau yang biasa digunakan untuk menemukan atau mencocokkannya. ... Selain itu, lihat untuk menghapus perilaku dan atribut ke objek lain yang terkait dengan ENTITY inti.
Jadi setiap perilaku yang tidak membantu mengidentifikasi entitas, tetapi kami masih akan mencirikan perilaku itu sebagai karakteristik intrinsik dari entitas itu (yaitu menggonggong adalah intrinsik untuk anjing, terbang adalah intrinsik untuk pesawat terbang, bertelur adalah intrinsik untuk burung .. .), harus dimasukkan ke objek lain yang terkait dengan entitas itu (contoh: kita harus memasukkan perilaku menggonggong ke objek yang terkait dengan entitas anjing)?
3.
Di luar itu, lihat untuk menghapus perilaku dan atribut ke objek lain yang terkait dengan ENTITY inti.
a) MyEntity
mendelegasikan tanggung jawab A_resp
dan B_resp
ke objek a
dan b
, masing-masing.
Meskipun sebagian besar A_resp
dan B_resp
pekerjaan dilakukan oleh a
dan b
contoh, klien masih dilayani A_resp
dan B_resp
melalui MyEntity
, yang berarti bahwa dari perspektif klien, dua tanggung jawab menjadi tanggung jawabnya MyEntity
. Jadi, bukankah itu berarti MyEntity
juga memiliki A_resp
dan B_resp
tanggung jawab dan dengan demikian melanggar SRP ?
b) Bahkan jika kita menganggap itu A_resp
dan B_resp
bukan milik MyEntity
, MyEntity
masih memiliki tanggung jawab AB_resp
untuk mengoordinasi operasi objek a
dan b
. Jadi tidak MyEntity
melanggar SRP karena setidaknya ia memiliki dua tanggung jawab - untuk mengidentifikasi dirinya secara unik dan juga AB_resp
?
class MyEntity
{
private A a = ...
private B b = ...
public A GetA()
{ ... }
public B GetB()
{ ... }
/* coordinates operations of objects a and b */
public int AworkB()
{ ... }
}
/* A encapsulates a single responsibility resp_A*/
/* A is value object */
class A
{ ... }
/* B encapsulates a single responsibility resp_B*/
/* B is value object */
class B
{ ... }
MEMPERBARUI:
1.
Perilaku dalam konteks ini mengacu pada perilaku semantik. Misalnya, properti di kelas (yaitu atribut pada objek domain) yang digunakan untuk mengidentifikasi secara unik itu memiliki perilaku. Meskipun ini tidak direpresentasikan dalam kode secara langsung. Perilaku yang diharapkan adalah bahwa tidak akan ada nilai duplikat untuk properti itu.
Jadi dalam kode kita hampir tidak perlu benar-benar menerapkan perilaku (yaitu operasi) yang entah bagaimana akan mempertahankan identitas entitas, karena ketika Anda menjelaskan perilaku seperti itu hanya ada sebagai konsep dalam model domain (dalam bentuk atribut ID dari sebuah entitas), tetapi ketika kita menerjemahkan atribut ID ini ke dalam kode, bagian dari semantiknya hilang (yaitu bagian yang secara implisit memastikan nilai ID unik hilang)?
2.
Lebih jauh lagi, properti seperti Zaman tidak memiliki konteks di luar Entitas Orang, dan dengan demikian, tidak masuk akal untuk pindah ke objek yang berbeda ... Namun informasi tersebut dapat dengan mudah disimpan di lokasi terpisah yang merupakan pengidentifikasi unik, oleh karena itu referensi yang membingungkan untuk perilaku. Usia bisa menjadi nilai yang dimuat malas.
a) Jika Age
properti malas dimuat, maka kita dapat menyebutnya perilaku, meskipun secara semantik Age
hanya atribut?
3.
Anda dapat dengan mudah memiliki operasi khusus untuk Alamat seperti verifikasi bahwa itu adalah alamat yang valid. Anda mungkin tidak tahu itu pada waktu desain, tetapi seluruh konsep ini adalah untuk memecah benda menjadi bagian terkecil mereka
Sementara saya setuju bahwa kita akan kehilangan konteks dengan pindah Age
ke objek yang berbeda, konteksnya tidak akan hilang jika kita memindahkan DateOfBirth
properti ke objek yang berbeda, tetapi kita biasanya tidak memindahkannya.
Apa alasan utama kami pindah Address
ke objek lain, tetapi tidak DateOfBirth
? Karena DateOfBirth
lebih intrinsik ke Person
entitas atau karena ada sedikit peluang di suatu tempat di masa depan kita mungkin perlu mendefinisikan operasi khusus untuk DateOfBirth
?
4. Saya harus mengatakan saya masih tidak tahu apakah MyEntity
juga memiliki A_resp
dan B_resp
tanggung jawab dan mengapa MyEntity
juga AB_resp
tidak dianggap sebagai pelanggaran SRP
EULERFX
1)
Perilaku yang penulis maksudkan adalah perilaku yang terkait dengan entitas. Ini adalah perilaku yang mengubah keadaan entitas
a) Jika saya memahami Anda dengan benar, Anda mengatakan bahwa entitas seharusnya hanya berisi perilaku yang mengubah atributnya (yaitu keadaannya )?
b) Dan bagaimana dengan perilaku yang tidak perlu mengubah keadaan entitas , tetapi masih dianggap sebagai karakteristik intrinsik dari entitas itu (contoh: menggonggong akan menjadi karakteristik intrinsik suatu Dog
entitas, bahkan jika itu tidak mengubah Kondisi anjing )? Haruskah kita memasukkan perilaku ini dalam suatu entitas atau haruskah mereka dipindahkan ke objek lain?
2)
Sejauh memindahkan perilaku ke objek lain, penulis mengacu pada objek nilai secara khusus.
Meskipun kutipan saya tidak mencantumkannya, tetapi penulis tidak menyebutkan dalam paragraf yang sama bahwa dalam beberapa kasus perilaku (dan atribut ) juga akan dipindahkan ke entitas lain (meskipun saya memahami manfaat dari memindahkan perilaku ke VO)
3) Dengan asumsi MyEntity
(lihat pertanyaan 3. di posting asli saya) tidak melanggar SRP, akan kita katakan bahwa tanggung jawab dari MyEntity
yang antara lain juga terdiri dari:
Sebuah. A_resp
+ B_resp
+ AB_resp
( AB_resp
koordinat objek a
dan b
)
atau
b. AB_resp
+ mendelegasikan A_resp
dan B_resp
ke objek ( a
dan b
) yang terkait dengan MyEntity
?
4) buku DDD Eric Evan, hal. 94:
CustomerID adalah satu-satunya pengidentifikasi dari ENTITY Pelanggan (gambar 5.5), tetapi nomor telepon dan alamat akan sering digunakan untuk menemukan atau mencocokkan Pelanggan. Nama tidak mendefinisikan identitas seseorang, tetapi sering digunakan sebagai bagian dari cara untuk menentukannya.
Dalam contoh ini, atribut telepon dan alamat pindah ke Pelanggan, tetapi pada proyek nyata, pilihan itu akan tergantung pada bagaimana pelanggan domain biasanya dicocokkan atau dibedakan. Misalnya, jika Pelanggan memiliki banyak nomor telepon kontak untuk tujuan yang berbeda, maka nomor telepon tersebut tidak dikaitkan dengan identitas dan harus tetap dengan Kontak Penjualan.
Sebuah)
CustomerID adalah satu-satunya pengidentifikasi dari ENTITY Pelanggan (gambar 5.5), tetapi nomor telepon dan alamat akan sering digunakan untuk menemukan atau mencocokkan Pelanggan. Nama tidak mendefinisikan identitas seseorang, tetapi sering digunakan sebagai bagian dari cara untuk menentukannya.
Kutipan menyatakan bahwa hanya atribut yang terkait dengan identitas yang harus tetap dalam entitas . Saya berasumsi penulis berarti bahwa entitas hanya boleh berisi atribut - atribut yang sering digunakan untuk menemukan atau cocok dengan entitas ini , sedangkan SEMUA atribut lainnya harus dipindahkan?
b) Tetapi bagaimana / di mana atribut lainnya dipindahkan? Sebagai contoh (asumsi di sini adalah bahwa atribut alamat tidak digunakan untuk menemukan atau mencocokkan Customer
dan dengan demikian kita ingin pindah atribut alamat dari Customer
):
jika alih-alih memiliki Customer.Address
(tipe string
) kita membuat properti Customer.Address
tipe Address
, apakah kita memindahkan atribut alamat ke objek VO terkait (yang bertipe Address
) atau akankah kita mengatakan bahwa Customer
masih berisi atribut alamat ?
c)
Dalam contoh ini, atribut telepon dan alamat pindah ke Pelanggan, tetapi pada proyek nyata, pilihan itu akan tergantung pada bagaimana pelanggan domain biasanya dicocokkan atau dibedakan. Misalnya, jika Pelanggan memiliki banyak nomor telepon kontak untuk tujuan yang berbeda, maka nomor telepon tersebut tidak dikaitkan dengan identitas dan harus tetap dengan Kontak Penjualan.
Bukan salah penulis di sini, karena jika kita asumsikan masing-masing dari banyak nomor telepon kontak yang Customer
hanya milik nomor itu Customer
, maka saya akan mengatakan nomor telepon ini terkait dengan identitas sama seperti ketika Customer
hanya memiliki satu nomor telepon ?
5)
Alasan penulis menyarankan untuk melepaskan entitas adalah ketika seseorang awalnya menciptakan entitas Pelanggan, ada kecenderungan untuk mengisinya dengan atribut apa pun yang dapat dipikirkan terkait dengan pelanggan. Ini adalah pendekatan data-sentris yang mengabaikan perilaku yang pada akhirnya mengarah ke model domain anemia.
Off topic, tapi saya pikir model domain anemia hasil dari bergerak perilaku dari suatu entitas , sedangkan contoh Anda mengisi sebuah entitas dengan banyak atribut , yang akan mengakibatkan Customer
memiliki terlalu banyak perilaku (karena kita mungkin juga termasuk di Customer
dalam perilaku yang memodifikasi atribut tambahan ini ) dan dengan demikian melanggar SRP?
Terima kasih
Jawaban:
Perilaku dalam konteks ini mengacu pada perilaku semantik. Misalnya, properti di kelas (yaitu atribut pada objek domain) yang digunakan untuk mengidentifikasi secara unik itu memiliki perilaku. Meskipun ini tidak direpresentasikan dalam kode secara langsung. Perilaku yang diharapkan adalah bahwa tidak akan ada nilai duplikat untuk properti itu. Sesuatu seperti Alamat yang mungkin memiliki identitasnya sendiri, tetapi tidak ada di luar konteks Entitas Orang harus tetap dipindahkan ke objeknya sendiri. Dengan demikian mempromosikan Entitas menjadi Root Agregat.
Lebih jauh, properti seperti Age tidak memiliki konteks di luar Entitas Orang, dan karenanya, tidak masuk akal untuk pindah ke objek yang berbeda. Konteksnya akan hilang, dan karenanya Anda dapat dengan aman menentukan bahwa itu adalah nilai yang penting bagi Entitas Pribadi. Anda tidak dapat menemukan nilai sebaliknya. Namun informasi itu dapat dengan mudah disimpan di lokasi terpisah yang menjadi pengidentifikasi unik, karenanya menjadi rancu referensi perilaku . Usia bisa menjadi nilai yang dimuat malas.
Jadi, untuk menjawab pertanyaanmu. Tidak, itu tidak melanggar Prinsip Tanggung Jawab Tunggal. Ini mearly menyatakan bahwa Seseorang harus hanya memiliki barang-barang orang, dan bukan sesuatu seperti Alamat, yang lebih kompleks dan terkait dengan seseorang, harus ada sebagai entitasnya sendiri.
Anda dapat dengan mudah memiliki operasi khusus untuk Alamat seperti verifikasi bahwa itu adalah alamat yang valid. Anda mungkin tidak tahu itu pada waktu desain, tetapi seluruh konsep ini adalah untuk memecah benda menjadi bagian terkecil mereka sehingga sesuatu seperti ini relatif sederhana ketika dilakukan setelah fakta.
Pembaruan: 1) Dalam kebanyakan kasus, validasi identitas ini dilakukan setelah menyimpan objek ke penyimpanan data. Yang berarti bahwa kode yang mewakili validasi entitas ada, tetapi ada di tempat lain. Biasanya ada dengan kode yang bertanggung jawab untuk mengeluarkan nilai identitas. Itulah sebabnya saya menyatakan bahwa keunikan tidak terwakili secara langsung dalam kode untuk entitas.
2) Pernyataan yang benar
Age
adalah atribut yang memiliki perilaku. Anda perlu mendokumentasikan fakta bahwa Age malas dimuat sehingga pengembang yang mengonsumsi properti itu dapat membuat keputusan yang akurat tentang cara mengonsumsi properti itu3)
DateOfBirth
biasanya merupakan objek yang berbeda; Objek tanggal yang sudah memiliki operasi yang sudah ditentukan sebelumnya. Dalam beberapa bahasa objek tanggal sudah memiliki seluruh model domain yang ditentukan di atasnya. Misalnya dalam c # Anda dapat menentukan zona waktu, jika tanggal adalah UTC, tambahkan dan kurangi tanggal untuk mendapatkan rentang waktu. Jadi asumsi Anda tentang bergerakDateOfBirth
akan benar.4) Jika satu-satunya hal yang
MyEntity
dilakukan adalah delegasi dan koordinasi maka tidak ada yang tidak melanggar SRP. Tanggung jawab tunggal adalah untuk mendelegasikan dan mengoordinasikan dan disebut sebagai pola Fasadsumber
Pertanyaan yang sangat bagus SRP seharusnya tidak diambil secara literal. Identifikasi / pencarian bukanlah tanggung jawab entitas terkait dengan SRP. Orang lain bertanggung jawab untuk memberikannya ID (yaitu toko) dan untuk mencarinya (yaitu Repositori ).
Tujuan utama suatu entitas adalah untuk mewakili konsep-konsep yang ditemukan oleh model. Satu-satunya perbedaan antara Entitas dan Obyek Nilai adalah bahwa Entitas memiliki makna di luar atribut yang tidak mengidentifikasi. Sebagai contoh jika seseorang mengubah namanya, dia masih orang yang sama, hanya dengan nama yang berbeda.
sumber
Jika identitas didirikan maka ya entitas tidak perlu yang lain untuk diidentifikasi. Perilaku yang penulis maksudkan adalah perilaku yang terkait dengan entitas. Ini adalah perilaku yang mengubah keadaan entitas. Misalnya,
Customer
entitas mungkin memilikiMakePreferred
perilaku. Alasan penulis menyarankan untuk menghilangkan entitas adalah ketika seseorang awalnya membuatCustomer
entitas, ada kecenderungan untuk mengisinya dengan atribut apa pun yang dapat dipikirkan terkait dengan pelanggan. Ini adalah pendekatan data-sentris yang mengabaikan perilaku yang pada akhirnya mengarah ke model domain anemia.Sejauh memindahkan perilaku ke objek lain, penulis mengacu pada objek nilai secara khusus. Alasan itu adalah ide yang baik untuk memindahkan perilaku ke VO adalah karena VO biasanya "lebih kecil" dari entitas, sehingga lebih fokus. Selain itu, aspek-aspek seperti imutabilitas dan penutupan operasi menyederhanakan penalaran tentang kode sementara juga membuatnya lebih SOLID .
Bersama dengan VO, suatu entitas berfungsi sebagai semacam jangkar yang mengoordinasikan berbagai VO yang menerapkan perilakunya.
Sehubungan dengan SRP, kebingungan Anda tidak beralasan. Satu masalah dengan implementasi OOP stereotip dari entitas adalah penyatuan identitas dan negara. Memang, dari perspektif perilaku, identitas tidak ada hubungannya dengan perilaku. Dengan kata lain, identitas suatu entitas tidak diperlukan untuk perilakunya. Ada implementasi di mana conflation ini dihilangkan, seperti AggregateSource atau pendekatan fungsional yang saya jelaskan di sini .
Masalah lainnya adalah bahwa, sampai batas tertentu, SRP dapat menjadi ukuran kualitatif. Siapa pun dapat memberikan definisi tanggung jawab tunggal yang dilanggar oleh beberapa kelas. Seseorang dapat mengatakan bahwa tanggung jawab entitas adalah untuk menerapkan perilaku yang diperlukan entitas itu. Dalam hal itu, ia memiliki tanggung jawab tunggal. Lebih jauh, ketika suatu entitas mendelegasikan perilaku kepada VO konstituen, itu tidak melanggar SRP. SRP tidak melarang komposisi semacam itu. Itu memang memperingatkan seseorang untuk mengurangi kopling antara objek ke minimum absolut, menjaga antarmuka semirip mungkin, dll.
MEMPERBARUI
Ya, meskipun ada pengecualian ...
Dapat diterima bagi entitas untuk mengandung metode pabrik untuk membuat instance entitas akan secara efektif entitas anak, tetapi di mana referensi objek tidak digunakan untuk traversal. Dalam hal ini, entitas anak perlu dipertahankan oleh layanan aplikasi. Layanan aplikasi menggunakan entitas induk untuk membangun entitas anak.
Anda melihat tanggung jawab dari perspektif implementasi. Sebaliknya, anggap entitas sebagai semacam kotak hitam dengan tanggung jawab. Cara menangani itu tidak menarik bagi Anda sebagai seseorang yang melihat dari luar. Pemisahan tanggung jawab di antara VO atau bahkan entitas lain adalah masalah implementasi.
Lebih khusus lagi, atribut yang tidak diperlukan untuk perilaku atau mencari seharusnya tidak menjadi bagian dari entitas. Kenapa mengganggu? Selain itu, dengan sesuatu seperti pola baca-model , entitas tidak memerlukan apa pun di luar atribut yang diperlukan untuk perilaku.
Ya, pada dasarnya, tidak ada perbedaan antara alamat string atau alamat VO.
Saya tidak 100% pada maksud penulis, tapi saya pikir dia hanya menggambarkan bagaimana persyaratan pencarian entitas dapat mengubah bagaimana entitas dan VO yang sesuai adalah struktur.
Banyak atribut tidak menyiratkan banyak perilaku. Bahkan, biasanya menyarankan sebaliknya. Banyak atribut dengan getter dan setter, tetapi tidak ada perilaku enkapsulasi.
sumber
TL; DR: Anda terlalu memikirkan ini. Namun, saya bersenang-senang memikirkannya bersama Anda. Jadi kencangkan sabuk pengaman ....
Tidak, itu tidak benar. Tanggung jawab tunggal suatu entitas adalah kontinuitas.
Identitas adalah konsekuensi yang muncul dari kontinuitas. Pemodelan identitas sebagai gagasan yang dapat dipisahkan adalah pengoptimalan kinerja.
Berikut ini contohnya: Seorang pelindung restoran memberi mobil kepada pelayan. Satu jam kemudian, pelindung restoran meminta mobil. Haruskah pelayan memberikannya?
Sangat mudah untuk mengatakan bahwa pelayan harus memberikan mobil jika pelindungnya "sama". Tapi, apa arti sebenarnya? Cara yang tepat untuk menentukan itu adalah mulai dengan pelindung "sekarang", dan cari ke belakang melalui sejarah pelindung itu untuk melihat apakah pemberian mobil kepada pelayan adalah bagian dari sejarah itu.
Tentu saja kita tidak bisa melakukan itu. Kita mengalami kesulitan melacak sejarah kita sendiri dengan tepat, apalagi sejarah sesuatu yang tidak bersama kita sepanjang waktu. Jadi alih-alih menggunakan sejarah pelindung, kami mengambil jalan pintas. Apakah pelindung memiliki potongan tiket yang memiliki nomor yang sama dengan tag yang saat ini terikat pada kunci? Apakah SIM di dompet pelindung cocok dengan nama pada judul di DMV, apakah gambar pada SIM itu menyerupai wajah pelindung. Dll
Singkatnya: alih-alih memeriksa riwayat patron, kami memeriksa status patron saat ini, untuk melihat apakah kondisi saat ini konsisten dengan riwayat yang mencakup periode antara kedatangan mobil dan permintaan pengembaliannya.
Saat memodelkan entitas, kami menggunakan optimasi analog. Kami memberikan semua entitas tanggung jawab bersama
Saya tidak menggambarkan tanggung jawab kedua dari entitas di sini; entitas masih bertanggung jawab atas kontinuitas - memastikan bahwa sejarah adalah narasi yang konsisten. Tanggung jawab pengidentifikasi hanyalah subset yang umum untuk semua entitas.
Kami belum memiliki penegakan keunikan. Itu tidak mungkin dalam satu entitas, karena keunikan memerlukan akses ke keadaan semua entitas; di mana satu entitas hanya memiliki akses ke entitasnya sendiri.
Sekali lagi, memeriksa semua pengidentifikasi setiap saat tidak praktis, jadi alih-alih kami memuaskan keunikan dengan cara mudah: Kode yang menghasilkan pengidentifikasi berikutnya tidak boleh diulang.
Pada akhirnya, ini berarti bahwa kita dapat memverifikasi kontinuitas dengan menguji kesetaraan dua bagian keadaan dalam memori, menghemat banyak kesulitan dalam mencoba kueri grafik asiklik.
Anda juga tampaknya telah mengacaukan Prinsip Tanggung Jawab Tunggal (yang merupakan ide yang sangat bagus) dengan prinsip tanggung jawab atom. Mengurai tanggung jawab menjadi bagian-bagian yang lebih kecil dan lebih mudah dikelola kompatibel dengan SRP.
sumber
Yah, itu tergantung pada bagaimana Anda ingin melihatnya.
Cara lain adalah: "Apakah Prinsip Tanggung Jawab Tunggal melanggar Entitas Domain?"
Keduanya adalah pedoman. Tidak ada "prinsip" di mana pun dalam desain perangkat lunak. Namun, ada desain yang bagus dan desain yang buruk. Kedua konsep ini dapat digunakan dengan cara yang berbeda, untuk mencapai desain yang baik.
sumber