Apakah "Pembalikan Kontrol" mempromosikan "Model Domain Anemik"?

32

Ketika saya menggunakan IoC Container di proyek terakhir saya, saya berakhir dengan entitas anemia dan sebagian besar logika bisnis saya di Layanan Stateless.

Saya telah melihat proyek yang ditulis oleh pengembang lain yang memanfaatkan "Inversion of Control" dan mereka selalu "Anemik".

Karena "Anemic Domain Model" anti-pola, apakah mungkin menggunakan IoC dan Rich Domain? Apakah ada contoh bagus mereka, proyek sumber terbuka yang melakukan itu?

Mag20
sumber
Saya pikir kita perlu melihat beberapa contoh spesifik dari kasus khusus Anda untuk membantu.
Martijn Verburg
1
Maaf, maksud saya cuplikan kode :)
Martijn Verburg

Jawaban:

11

Sebagai permulaan: DI dan IoC bukan sinonim. Saya minta maaf tetapi saya harus menunjukkan itu (menurut saya Anda pikir mereka).

Adapun pertanyaan Anda ... Yah, Ketergantungan Injeksi hanyalah alat. Bagaimana Anda akan menggunakan alat ini adalah hal yang sepenuhnya terpisah. Ada juga alat lain (pola desain) yang bisa menambah masalah. Sebagai contoh, saya merasa bahwa adopsi luas dari pola MVC adalah salah satu unsur utama untuk membentuk anti-pola Model Domain Anemik: Pengontrol (dalam aplikasi yang lebih sederhana, dalam aplikasi yang lebih rumit yang akan menjadi Lapisan Layanan tambahan) bertanggung jawab untuk memvalidasi aturan bisnis , menegakkan mereka serta mentransformasikan entitas DB menjadi sesuatu yang bermanfaat, sedangkan Layer Bisnis berubah menjadi Layer Akses Data sederhana yaitu ORM polos dengan pemetaan satu-ke-satu ke entitas basis data.

Tentu saja ini adalah cara Anda mendesain aplikasi Anda - Anda dapat membuat Model Domain yang benar jika Anda mau, dan semua IoC, DI, MVC ini tidak menghentikan Anda. Apa yang bisa menghentikan Anda adalah tim Anda. Anda perlu meyakinkan mereka untuk menggunakan jalur yang benar dan mungkin sulit karena banyak Pengembang Perangkat Lunak tidak memiliki latar belakang arsitektur yang kuat.

Paweł Dyda
sumber
Saya akan menambahkan ini bahwa mungkin Anda bisa mengintip pendekatan DDD yang didukung oleh Eric Evans et al.
Martijn Verburg
1
Saya memang membaca buku Eric Evans. Ini bagus untuk metodologi umum dan bahasa di mana-mana, tetapi agak kurang dalam contoh dunia nyata.
Mag20
Terima kasih telah menunjukkan perbedaan antara DI dan IoC. Saya pikir masalah ini lebih berkaitan dengan IOC daripada DI. Mengubah pertanyaan untuk mencerminkan hal itu.
Mag20
Dalam pengalaman saya dengan DI kerangka / kontainer (musim semi DI, CDI, Unity), mereka memang tidak menghentikan Anda dari menciptakan "benar Domain Model", yang bagi saya berarti bahwa pengembang tidak harus dibatasi dari menggunakan benar (yaitu, stateful) obyek . Tapi DI tidak begitu mendukung itu.
Rogério
8

Sebagian besar (jika tidak semua) aplikasi adalah campuran dari masalah infrastruktur dan domain. Ketika Anda mencapai tingkat kompleksitas tertentu Anda akan membuatnya lebih mudah untuk dikelola jika domain dipisahkan dari infrastruktur sehingga lebih mudah untuk dipertimbangkan dan dapat berkembang secara mandiri.

Tentu saja model domain masih perlu berkomunikasi dengan seluruh sistem dan biasanya ini akan dengan layanan stateless (yang merupakan bagian dari domain) yang memiliki masalah infrastruktur (seperti akses database) disuntikkan ke dalamnya. Menggunakan wadah IoC tidak menghilangkan ketergantungan ini, ia memindahkan konfigurasinya ke area terpisah - sekali lagi membuatnya lebih mudah untuk dipertimbangkan dan dipelihara.

Entitas adalah negara penyimpan dan harus bertanggung jawab atas aturan bisnis. Jika layanan Anda menerapkan semua invarian dan aturan bisnis lainnya, maka kemungkinan logika berada di tempat yang salah.

Sekarang jika Anda memiliki logika di tempat yang tepat dan masih berakhir dengan layanan yang tidak lebih dari pembungkus hal infrastruktur dan entitas yang hanya tas properti, maka sangat mungkin bahwa domain tersebut tidak cukup kompleks untuk dibenarkan. overhead modelnya sendiri. Apa saja yang Anda baca tentang DDD akan berisi penafian yang sebenarnya hanya ditujukan untuk domain yang kompleks, tetapi ini sepertinya terlalu sering dilupakan.

FinnNk
sumber
7

Pergi ke sumbernya. Mulailah dengan karya Fowler tentang Model Domain Anemik . Dia merujuk Eric Evan's Domain Driven Design sebagai contoh praktik yang baik. Kode sumber untuk itu ada di sini . Unduh itu.

Perhatikan bahwa ia menggunakan Inversion of Control (cari @Autowired), dan memiliki kelas layanan (BookingService), dan kelas "proses bisnis" (mis. ItineraryUpdater).

Artikel asli Fowler memulai jejak ke contoh yang Anda cari.

jamie
sumber
Aplikasi sampel itu, pada kenyataannya, tidak sesuai dengan DDD seperti yang dijelaskan dalam buku ini. Kontradiksi khusus dengan buku ini adalah bahwa buku itu benar-benar melanggar konsep "infrastruktur", dengan mengizinkannya memuat kode khusus domain; misalnya, VoyageRepositoryHibernatekelas, yang diletakkan di lapisan infrastruktur tetapi sebenarnya tergantung pada lapisan domain.
Rogério
Ya, buku itu mengatakan pada halaman 73 bahwa lapisan infrastruktur "di bawah" lapisan domain dan "seharusnya tidak memiliki pengetahuan khusus tentang domain yang dilayaninya". Ini tidak pernah masuk akal bagi saya. Pertimbangkan sebuah proyek yang memiliki dua implementasi VoyageRepository: VoyageRepositoryHibernate dan kelas VoyageRepositoryJDBC. Implementasinya tentu sangat berbeda, dan spesifik teknologi. Apakah ini termasuk dalam lapisan domain? Atau lapisan infrastruktur? Dalam kode kami, menurut buku, kami melakukannya mundur: lapisan infrastruktur dapat mereferensikan lapisan domain, tetapi tidak sebaliknya.
jamie
Mereka termasuk dalam lapisan domain, ya. Implementasi berbasis JDBC akan berisi kode SQL yang diikat ke tabel dan kolom dalam database aplikasi, yang khusus untuk domain. Menempatkan kode khusus domain atau aplikasi apa pun di lapisan infrastruktur adalah salah, karena "kode infrastruktur" hanya boleh digunakan untuk menyelesaikan masalah teknis, dan (idealnya) dapat digunakan kembali sepenuhnya antara berbagai aplikasi dan domain. Solusi untuk memiliki kode "tingkat rendah" (mis. SQL) di lapisan domain bukan dengan memindahkannya sepenuhnya, tetapi mengimplementasikannya di atas infrastruktur yang lebih baik, seperti ORM.
Rogério
Bagi saya, implementasi save (MyDomainObject foo) adalah masalah teknis semata. YMMV.
jamie
Hanya jika itu tidak menyebabkan Anda melanggar aturan dasar arsitektur berlapis: lapisan bawah tidak bisa bergantung pada lapisan yang lebih tinggi. Jadi, jika Anda menerapkan save(foo)kode yang dapat berubah ketika model domain berubah (misalnya, jika atribut baru ditambahkan ke MyDomainObject), maka harus (menurut definisi) milik lapisan domain; jika tidak, Anda tidak bisa lagi berbicara tentang memiliki "lapisan".
Rogério
7

apakah mungkin menggunakan IoC dan Rich Domain? Apakah ada contoh bagus mereka, proyek sumber terbuka yang melakukan itu?

Saya menganggap maksud Anda DI bukan IoC, dan proyek yang Anda kerjakan menggunakan wadah DI seperti Spring. IoC memiliki dua rasa utama: DI dan pola Locator. Saya tidak melihat mengapa pola Locator menjadi masalah, jadi mari kita fokus pada DI.

Saya tidak berpikir itu mungkin, atau setidaknya akan sangat tidak praktis. Aspek utama dari wadah DI adalah bahwa mereka mengontrol pembuatan objek ketika mereka menyuntikkannya ke orang lain ("objek yang dikelola"). Himpunan objek terkelola yang hidup ketika proyek berjalan independen dari item domain mana yang ada di proyek Anda, tetapi bergantung pada bagaimana objek dikabel dan cakupan mana (singleton, prototipe) yang ditugaskan padanya.

Inilah sebabnya mengapa Anda tidak ingin membiarkan wadah DI mengelola objek domain Anda. Tetapi jika Anda membuat objek secara manual (dengan yang baru), Anda tidak bisa mendapatkan objek lain yang disuntikkan ke objek domain Anda. (Meninggalkan potensi penyelesaian dengan pengkabelan manual.) Karena Anda memerlukan suntikan ini untuk menggantikan implementasi dengan yang lain, Anda tidak dapat mengganti fungsionalitas objek domain kaya menggunakan DI. Karenanya, Anda tidak akan ingin menempatkan fungsionalitas ke objek domain, atau Anda akan kehilangan fitur DI.

Saya tidak melihat bagaimana wadah DI hipotetis bisa bekerja yang tidak mengelola objek Anda, dan tidak ada implementasi yang ada yang memungkinkan itu. Jadi adil untuk mengklaim bahwa DI bergantung pada pengelolaan objek. Karena itu akan selalu menggoda Anda untuk membagi objek Rich Domain potensial menjadi satu kelas anemik dan satu atau beberapa kelas skrip transaksi.

Wolfgang
sumber
Jawaban ini benar-benar mengenai kuku di kepala ketika sampai pada ketegangan antara Model Domain Kaya dan Injeksi Ketergantungan.
jrahhali