Sering kali objek bisnis saya cenderung memiliki situasi di mana informasi perlu melewati batas objek terlalu sering. Saat melakukan OO, kami ingin informasi berada di satu objek dan sebanyak mungkin semua kode yang berurusan dengan informasi itu harus berada di objek itu. Namun, aturan bisnis tidak mengikuti prinsip ini yang membuat saya kesulitan.
Sebagai contoh, misalkan kita memiliki Pesanan yang memiliki sejumlah ItemItem yang merujuk pada InventoryItem yang memiliki harga. Saya meminta Order.GetTotal () yang merangkum hasil dari OrderItem.GetPrice () yang mengalikan kuantitas dengan InventoryItem.GetPrice (). Sejauh ini bagus.
Tetapi kemudian kami menemukan bahwa beberapa barang dijual dengan dua untuk satu transaksi. Kita dapat menangani ini dengan meminta OrderItem.GetPrice () melakukan sesuatu seperti InventoryItem.GetPrice (jumlah) dan membiarkan InventoryItem berurusan dengan ini.
Namun, kemudian kami mengetahui bahwa kesepakatan dua-untuk-satu hanya berlangsung selama periode waktu tertentu. Periode waktu ini harus didasarkan pada tanggal pesanan. Sekarang kita mengubah OrderItem.GetPrice () menjadi InventoryItem.GetPrice (quatity, order.GetDate ())
Tapi kemudian kita perlu mendukung harga yang berbeda tergantung pada berapa lama pelanggan dalam sistem: InventoryItem.GetPrice (jumlah, pesanan.GetDate (), pesanan.GetCustomer ())
Tetapi kemudian ternyata bahwa dua-untuk-satu transaksi berlaku tidak hanya untuk membeli beberapa item persediaan yang sama tetapi juga beberapa untuk setiap item dalam InventoryCategory. Pada titik ini kita angkat tangan dan hanya memberikan barang pesanan InventoryItem dan memungkinkannya untuk melakukan perjalanan di atas grafik referensi objek melalui pengakses untuk mendapatkan informasi kebutuhannya: InventoryItem.GetHarga (ini)
TL; DR Saya ingin memiliki objek kopling rendah, tetapi aturan bisnis sering memaksa saya untuk mengakses informasi dari semua tempat untuk membuat keputusan tertentu.
Apakah ada teknik yang baik untuk menangani ini? Apakah orang lain menemukan masalah yang sama?
sumber
Jawaban:
Kami pada dasarnya memiliki pengalaman yang sama di mana saya bekerja dan kami mengatasinya dengan memiliki kelas OrderBusinessLogic. Sebagian besar tata letak yang Anda gambarkan berfungsi untuk sebagian besar bisnis kami. Bagus dan bersih dan sederhana. Tetapi pada kesempatan di mana Anda telah membeli 2 dari kategori ini, kami menganggapnya sebagai "eksekusi bisnis" dan meminta kelas OrderBL untuk menghitung ulang total dengan melintasi objek yang dibutuhkan.
Apakah ini solusi sempurna, tidak. Kami masih memiliki satu kelas terlalu banyak mengetahui tentang kelas-kelas lain, tetapi setidaknya kami telah memindahkan kebutuhan itu dari objek-objek bisnis dan ke dalam kelas logika bisnis.
sumber
Kedengarannya seperti Anda memerlukan objek Diskon yang terpisah (atau daftar mereka) yang melacak semua hal itu, dan kemudian menerapkan Diskon tersebut ke Pesanan, sesuatu seperti
Order.getTotal(Discount)
atauDiscount.applyTo(Order)
atau serupa.sumber
Tidak apa-apa mengakses data dari kelas lain. Namun, Anda ingin ini menjadi hubungan satu arah. Misalnya, misalkan ClassOrder mengakses CallItem. Idealnya, ClassItem tidak boleh mengakses ClassOrder. Apa yang saya pikir Anda hilang dalam Kelas Pesanan Anda adalah semacam logika bisnis yang mungkin atau mungkin tidak menjamin kelas seperti yang disarankan Walter.
Sunting: Tanggapan untuk komentar Winston
Saya tidak berpikir Anda memerlukan objek barang inventaris sama sekali ... setidaknya dengan cara Anda menggunakannya. Sebagai gantinya saya akan memiliki kelas inventaris yang mengelola database inventaris.
Saya akan merujuk ke item inventaris dengan ID. Setiap pesanan akan berisi daftar ID inventaris dan jumlah yang sesuai.
Lalu saya akan menghitung total pesanan dengan sesuatu seperti ini.
Inventory.GetCost (Item, nama pelanggan, tanggal)
Maka Anda bisa memiliki fungsi pembantu lainnya seperti:
Inventaris.Barang Barang (int itemID)
Inventory.Tambahkan Item (int itemID, int jumlah)
Inventory.Hapus Item (int itemID, jumlah int)
Inventory.TambahkanBusinessRule (...)
Inventory.DeleteBusinessRule (...)
sumber
Setelah memikirkan hal ini lebih lanjut, saya membuat strategi alternatif sendiri.
Tentukan kelas Harga.
Inventory.GetPrice()
mengembalikan objek hargaSekarang kelas Harga (dan mungkin beberapa kelas terkait) merangkum logika penetapan harga dan pesanan tidak perlu khawatir. Harga tidak tahu apa-apa tentang Pesanan / Pesanan, melainkan hanya memiliki informasi yang dimasukkan ke dalamnya.
sumber