Tumpahan Informasi Melintasi Batas Objek

10

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?

Winston Ewert
sumber
4
Pada pandangan pertama tampaknya kelas InventoryItem berusaha melakukan terlalu banyak dengan menghitung harga, mengembalikan harga yang diberikan adalah satu hal tetapi harga jual dan aturan bisnis khusus tidak boleh alamat di InventoryItem. Luncurkan kelas untuk menghitung harga Anda dan biarkan menangani kebutuhan data dari Pesanan, Inventaris, dan Pelanggan dan sebagainya.
Chris
@ Chris, ya, membagi logika harga mungkin adalah ide yang bagus. Masalah saya adalah bahwa objek seperti itu akan digabungkan dengan erat ke semua objek terkait urutan. Itulah bagian yang menggangguku dan bagian aku bertanya-tanya apakah aku bisa menghindari.
Winston Ewert
1
Jika sesuatu, saya tidak ingin menyebutnya apa-apa, memerlukan semua informasi itu maka entah bagaimana ia harus mengkonsumsi informasi ini untuk menghasilkan hasil yang diinginkan. Jika Anda memiliki inventaris, barang, pelanggan dan sebagainya sudah dibangun, maka menerapkan logika bisnis di bidangnya sendiri adalah yang paling masuk akal. Saya tidak punya solusi yang lebih baik.
Chris

Jawaban:

6

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.

Walter
sumber
2
Jika ragu tambahkan kelas lain.
Chris
1

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)atau Discount.applyTo(Order)atau serupa.

John Bode
sumber
Saya bisa melihat di mana menempatkan kode dalam Diskon daripada di objek Inventaris akan lebih baik. Tetapi objek diskon sepertinya masih harus mengakses informasi dari semua objek yang berbeda untuk menyelesaikan tugasnya. Jadi itu tidak, setidaknya sejauh yang saya bisa lihat, menyelesaikan masalah.
Winston Ewert
2
Saya pikir objek Diskon adalah ide yang bagus, tetapi saya akan membuatnya menerapkan pola pengamat ( en.wikipedia.org/wiki/Observer_pattern ), dengan Diskon sebagai subjek pola
BlackICE
1

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 (...)

Pemda
sumber
Tidak apa-apa untuk meminta data dari kelas yang terkait erat. Masalah muncul ketika saya mengakses data dari kelas yang tidak langsung terkait. Untuk mengimplementasikan logika itu di kelas Order akan membutuhkan kelas Order untuk berurusan langsung dengan objek Inventory (yang berisi data harga yang diperlukan). Itulah bagian yang mengganggu saya karena menggabungkan Orde ke kelas yang (idealnya) tidak tahu apa-apa tentangnya.
Winston Ewert
Intinya, ide Anda adalah untuk menghilangkan OrderItem dan bukannya Order yang melacak semua informasi itu sendiri. Maka mudah untuk meneruskan informasi itu ke objek lain untuk informasi penetapan harga. Itu bisa berhasil. (Dalam skenario khusus contoh ini secara longgar didasarkan pada OrderItem terlalu rumit dan benar-benar perlu menjadi objeknya sendiri)
Winston Ewert
Yang tidak masuk akal bagi saya adalah mengapa Anda ingin Inventory direferensikan menggunakan nomor id daripada referensi objek. Tampaknya jauh lebih baik bagi saya untuk melacak referensi dan jumlah objek daripada id item dan referensi.
Winston Ewert
Saya tidak menyarankan itu sama sekali. Saya pikir Anda masih harus memiliki kelas atau struktur untuk memesan barang. Saya hanya tidak berpikir bahwa objek barang inventaris individual harus memiliki harga di dalamnya terutama karena saya tidak yakin bagaimana Anda akan mendapatkannya di sana tanpa menanyakan semacam database. Item pesanan atau inventaris akan berupa kelas data yang berisi pengidentifikasi item dan kuantitas. Urutan itu sendiri akan memiliki daftar benda-benda ini.
Pemdas
Saya tidak begitu yakin apa yang Anda minta di komentar kedua. Tidak semuanya harus menjadi objek. Saya benar-benar tidak yakin bagaimana Anda akan menemukan item tertentu tanpa semacam id.
Pemdas
0

Setelah memikirkan hal ini lebih lanjut, saya membuat strategi alternatif sendiri.

Tentukan kelas Harga. Inventory.GetPrice()mengembalikan objek harga

Price OrderItem::GetPrice()
{
    return inventory.GetPrice().quantity(quantity);
}

Currency OrderItem::GetTotal()
{
    Price price = empty_price();
    for(item in order_items)
    {
         price = price.combine( item.GetPrice() )
    }
    price = price.date(date).customer(customer);
    return price.GetActualPrice();
}

Sekarang 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.

Winston Ewert
sumber