Objek Bisnis - Wadah atau fungsional?

19

Ini adalah pertanyaan yang saya tanyakan beberapa waktu lalu di SO, tetapi mungkin bisa didiskusikan lebih baik di sini ...

Di mana saya bekerja, kami telah bolak-balik tentang hal ini beberapa kali dan mencari cek kewarasan. Inilah pertanyaannya: Haruskah Objek Bisnis menjadi wadah data (lebih seperti DTO ) atau haruskah mereka juga berisi logika yang dapat melakukan beberapa fungsi pada objek itu.

Contoh - Ambil objek pelanggan, mungkin berisi beberapa properti umum (Nama, Id, dll), haruskah objek pelanggan itu juga menyertakan fungsi (Simpan, Calc, dll.)?

Satu baris alasan mengatakan pisahkan objek dari fungsionalitas (prinsip tanggung jawab tunggal) dan letakkan fungsionalitas dalam lapisan atau objek Logika Bisnis.

Alur penalaran lainnya mengatakan, tidak, jika saya memiliki objek pelanggan, saya hanya ingin menelepon Pelanggan. Simpan dan selesaikan. Mengapa saya perlu tahu tentang kelas lain untuk menyelamatkan pelanggan jika saya mengkonsumsi objek?

Dua proyek terakhir kami memiliki objek yang terpisah dari fungsi, tetapi perdebatan telah dimunculkan lagi pada proyek baru.

Mana yang lebih masuk akal dan mengapa ??

Walter
sumber
1
Bisakah Anda memberi tahu kami lebih banyak tentang proyek Anda? Sifat proyek Anda akan menentukan solusi mana yang lebih baik.

Jawaban:

5

Jika Anda menganggap bahwa Pelanggan adalah bagian dari model domain, maka masuk akal (terutama dalam konteks DDD tetapi tidak terbatas pada itu) memiliki properti dan operasi untuk objek tersebut.

Namun demikian, saya berpendapat bahwa contoh yang Anda gunakan adalah yang buruk, dan merupakan penyebab dari argumen tersebut. Jika Anda berbicara tentang kegigihan, maka Pelanggan umumnya tidak 'menyelamatkan' diri mereka sendiri; apa pun yang Anda gunakan untuk kegigihan akan. Masuk akal bahwa segala jenis kegigihan harus dimiliki oleh lapisan / partisi kegigihan. Ini umumnya pemikiran di balik pola repositori. ** Metode seperti Customer.UpgradeWarranty () atau Customer.PromoteToPreferred () membuat argumen lebih jelas.

Ini juga tidak menghilangkan kemungkinan memiliki DTO . Sebagai contoh, pertimbangkan situasi di mana Anda akan meneruskan informasi pelanggan ke layanan jarak jauh. Mungkin tidak masuk akal bagi pelanggan untuk membuat DTO itu sendiri untuk transportasi, itu masalah arsitektur, tetapi kasus dapat dibuat untuk itu dalam kegigihan atau lapisan jaringan / partisi / kode / apa pun yang Anda miliki. Dalam hal itu, objek seperti itu dapat memiliki metode yang terlihat seperti ini

public static CustomerDTO GetDTO(Customer c) { /* ... */ }

public static Customer GetCustomer(CustomerDTO cdto) { /* ... */ }

Jadi, dalam ringkasan, sangat masuk akal untuk memiliki operasi pada objek domain yang kongruen dengan operasi logis di domain.

Google untuk 'Ketidaktahuan Ketekunan' untuk sejumlah diskusi yang baik tentang masalah ini ( pertanyaan SO ini , dan jawaban yang diterima adalah tempat yang baik untuk memulai).

** Ini akan sedikit kacau dengan perangkat lunak OR / M tertentu di mana Anda dipaksa untuk mewarisi dari basis persisten yang memiliki metode 'Simpan'.

Steven Evers
sumber
3

Saya sebenarnya baru-baru ini mengerjakan ulang beberapa kode untuk memisahkan objek dari data. Alasannya adalah bahwa data diperoleh melalui layanan terpisah, dan jauh lebih mudah untuk hanya meneruskan data mentah ke / dari server daripada melewati seluruh objek bolak-balik dan harus berurusan dengan kesalahan validasi pada server.

Untuk proyek-proyek kecil, memiliki objek mengandung logika bisnis dan data mungkin baik-baik saja, tetapi untuk proyek-proyek besar, atau proyek yang mungkin berkembang seiring waktu, saya pasti akan memisahkan lapisan-lapisannya.

Rachel
sumber
3

Saya pikir kedua cara melakukannya dapat memiliki manfaat, tetapi saya akan melihatnya dari tampilan berorientasi objek atau domain: apa tanggung jawab kelas dan objek yang berbeda.

Jadi, saya akan bertanya pada diri saya sendiri, dalam kasus konkret Anda: haruskah seorang pelanggan tahu bagaimana cara menyelamatkan diri?

Bagi saya, jawabannya adalah tidak: secara logis bagi saya itu tidak masuk akal, dan seorang pelanggan seharusnya tidak perlu tahu apa-apa tentang kerangka kerja sama sekali (pemisahan tanggung jawab).

Adapun contoh SnOrfus dengan Customer.UpgradeWarranty () atau Customer.PromoteToPreferred (), mereka jelas lebih berorientasi pada logika bisnis daripada Customer.Save (). Ada beberapa pendekatan yang berbeda untuk ini, tetapi sekali lagi jika Anda bertanya pada diri sendiri apakah seorang pelanggan seharusnya dapat meningkatkan garansi, jawabannya mungkin ya atau tidak, tergantung pada bagaimana Anda melihatnya:

  • ya: seorang pelanggan tentu saja dapat meningkatkan jaminannya
  • tidak: seorang pelanggan dapat meminta untuk ditingkatkan, tetapi peningkatan itu dilakukan oleh orang lain

Kembali ke pertanyaan awal Anda; cara mana yang lebih masuk akal mungkin akan tergantung pada siapa yang Anda tanyakan dan metode pilihan mereka, tetapi hal yang paling penting adalah tetap berpegang pada satu cara untuk melakukannya.

Namun, dalam pengalaman saya, memisahkan data dan logika (bisnis) membuat arsitektur lebih sederhana, meskipun tidak semenarik mungkin.

Vetle
sumber
2

Saya pikir Anda secara khusus berbicara tentang perbedaan antara ActiveRecordpola dan Repositorypola. Dalam yang pertama, entitas tahu bagaimana bertahan diri, dan yang terakhir, repositori tahu tentang kegigihan. Saya pikir yang terakhir menawarkan pemisahan kekhawatiran yang lebih baik.

Dalam arti yang lebih luas, jika entitas bertindak lebih seperti struktur data, maka mereka seharusnya tidak memiliki perilaku, tetapi jika mereka memiliki perilaku, maka mereka tidak boleh digunakan seperti struktur data. Contoh:

Struktur data:

class CustomerController
{
    public int MostRecentOrderLines(Customer customer)
    {
        var o = (from order in customer.Orders
                orderby order.OrderDate desc
                select order).First();
        return o.OrderLines.ToList().Count;
    }
}

Struktur Non-Data:

class Customer
{
    public int MostRecentOrderLines()
    {
        // ... same ...
    }
}

Dalam kasus pertama, Anda dapat menavigasi struktur data struktur model Anda tanpa masalah, dari mana saja dalam kode kerja Anda, dan itu tidak masalah, karena Anda memperlakukannya seperti struktur data. Dalam kasus terakhir, Pelanggan lebih seperti layanan untuk pelanggan tertentu, jadi Anda tidak boleh memanggil metode pada hasilnya. Semua hal yang ingin Anda ketahui tentang Pelanggan harus tersedia dengan memanggil metode pada objek Pelanggan.

Jadi, apakah Anda ingin entitas Anda menjadi struktur data atau layanan? Untuk konsistensi, tampaknya lebih baik tetap menggunakannya. Dalam kasus sebelumnya, letakkan "type" -type logic Anda di tempat lain, bukan di entitas.

Scott Whitlock
sumber
1

Saya tidak dapat menjawab pertanyaan Anda, tetapi saya merasa lucu bahwa kami juga mengadakan diskusi ini di salah satu proyek kami di sekolah. Saya ingin memisahkan logika dari data. Tetapi banyak teman sekelas saya mengatakan bahwa objek tersebut harus menampung semua logika DAN data.

Saya akan mencoba untuk menambahkan fakta yang mereka kemukakan:

  • Objek kelas bisnis mewakili sesuatu, jadi semua data DAN logika harus dimuat. (mis. jika Anda ingin membuka pintu, Anda melakukannya sendiri, Anda tidak meminta orang lain. contoh buruk saya tahu)

  • Lebih mudah memahami kode dan fungsionalitas objek bu.

  • Kompleksitas kurang dalam desain

Saya mengatakan kepada mereka bahwa mereka malas dan saya akan membuatnya seperti ini:

  • Ya, kelas bisnis mewakili hal-hal, jadi ia menyimpan data. Tetapi merasa salah untuk menyelamatkan diri sendiri, atau bahkan menyalin. Anda tidak dapat melakukannya di rl.

  • Membuat objek bertanggung jawab atas segalanya membuatnya tidak baik untuk ketahanan dan pemeliharaan di masa mendatang. Jika Anda memiliki kelas terpisah yang bertanggung jawab untuk menyimpan, jika Anda menambahkan objek baru ke desain, Anda dapat dengan mudah menerapkan fungsi penyimpanannya. alih-alih mengkode semuanya lagi di kelas itu.

  • Dengan memiliki satu objek yang dapat menyimpan data, objek tersebut dapat menyimpan koneksi basis data dan semua lalu lintas basis data dipandu pada objek tersebut. (pada dasarnya lapisan data acces) jika tidak semua objek Bisnis harus memegang koneksi. (yang menambah kompleksitas)

Baik satu atau lain cara, saya akan bertanya pada guru. Ketika saya telah melakukan itu, saya akan memposting jawabannya di sini juga jika Anda mau. ;)

edit:

Saya lupa menyebutkan proyek ini tentang toko buku.

Emerion
sumber
Teman sekelas Anda benar, kecuali mereka membingungkan logika bisnis dengan bentuk logika lainnya (dalam hal ini, arsitektur atau logika kegigihan).
Steven Evers
1

Jawabannya benar-benar akan tergantung pada apa arsitektur / desain Anda - arsitektur DDD dengan model domain akan sangat berbeda dari model sentris-data CRUD dalam hal desain objek.

Secara umum, ingatlah bahwa dalam desain berorientasi objek Anda mencoba merangkum keadaan dan mengekspos perilaku. Ini berarti bahwa Anda biasanya akan mencoba membuat negara terkait dengan perilaku sedekat mungkin dengan perilaku itu - ketika Anda gagal melakukan ini, Anda dipaksa untuk mengekspos keadaan dalam satu bentuk atau lainnya.

Dalam model domain Anda ingin memisahkan model bisnis dari masalah infrastruktur - jadi Anda benar-benar ingin menghindari metode seperti 'Simpan.' Saya tidak ingat kapan terakhir kali saya "menyelamatkan" seorang pelanggan di kehidupan nyata!

Dalam aplikasi CRUD maka data adalah warga negara kelas satu sehingga ".Save" sepenuhnya sesuai.

Aplikasi dunia nyata yang paling besar akan memiliki campuran paradigma ini - model domain di mana ada perubahan cepat atau aturan bisnis yang kompleks, DTO untuk mentransfer data melintasi batas, CRUD (atau sesuatu antara CRUD dan model domain, seperti activerecord) di tempat lain. Tidak ada satu ukuran yang cocok untuk semua aturan.

FinnNk
sumber
0

Saya telah mempertimbangkan pertanyaan yang sama untuk sementara waktu - saya pikir komponen data dan komponen logika harus terpisah. Saya percaya ini karena itu membawa Anda ke kerangka berpikir yang benar mengenai logika bisnis sebagai antarmuka ke data yang memberikan makna.

Saya juga memodifikasi poin Scott Whitlock dari atas (kecuali saya tidak punya poin menjadi anggota baru), kelas data atau logika bisnis seharusnya tidak perlu khawatir tentang bagaimana objek disimpan secara terus-menerus.

Yang sedang berkata, jika Anda berurusan dengan produk yang sudah ada, selama Anda memiliki antarmuka kontrak yang bersih - tidak apa-apa dan juga dapat dipertahankan ...

heretik
sumber