Thông tin tràn qua ranh giới đối tượng


10

Nhiều lần các đối tượng kinh doanh của tôi có xu hướng gặp phải tình huống thông tin cần vượt qua ranh giới đối tượng quá thường xuyên. Khi thực hiện OO, chúng tôi muốn thông tin nằm trong một đối tượng và càng nhiều càng tốt tất cả các mã xử lý thông tin đó phải nằm trong đối tượng đó. Tuy nhiên, các quy tắc kinh doanh không tuân theo nguyên tắc này mang lại cho tôi rắc rối.

Như một ví dụ giả sử rằng chúng ta có một Đơn hàng có một số OrderItems đề cập đến một InventoryItem có giá. Tôi gọi Order.GetTotal () tính tổng kết quả của OrderItem.Getprice () nhân số lượng của InventoryItem.Getprice (). Càng xa càng tốt.

Nhưng sau đó chúng tôi phát hiện ra rằng một số mặt hàng được bán với giá hai cho một giao dịch. Chúng ta có thể xử lý việc này bằng cách yêu cầu OrderItem.Getprice () làm một cái gì đó như InventoryItem.Getprice (số lượng) và để InventoryItem giải quyết việc này.

Tuy nhiên, sau đó chúng tôi phát hiện ra rằng thỏa thuận hai đối một chỉ kéo dài trong một khoảng thời gian cụ thể. Khoảng thời gian này cần được dựa trên ngày đặt hàng. Bây giờ chúng tôi thay đổi OrderItem.Getprice () thành InventoryItem.Getprice (quatity, order.GetDate ())

Nhưng sau đó, chúng tôi cần hỗ trợ các mức giá khác nhau tùy thuộc vào thời gian khách hàng đã ở trong hệ thống: InventoryItem.Getprice (số lượng, order.GetDate (), order.GetCustomer ())

Nhưng sau đó, hóa ra các giao dịch hai đối một không chỉ áp dụng cho việc mua nhiều mặt hàng tồn kho giống nhau mà là nhiều giao dịch cho bất kỳ mặt hàng nào trong InventoryC Category. Tại thời điểm này, chúng tôi giơ tay và chỉ đưa cho InventoryItem mục đặt hàng và cho phép nó đi qua biểu đồ tham chiếu đối tượng thông qua các bộ truy cập để có được thông tin về nhu cầu của nó: InventoryItem.Getprice (cái này)

TL; DR Tôi muốn có sự kết nối thấp trong các đối tượng, nhưng các quy tắc kinh doanh thường buộc tôi phải truy cập thông tin từ khắp mọi nơi để đưa ra quyết định cụ thể.

Có kỹ thuật tốt để đối phó với điều này? Những người khác tìm thấy cùng một vấn đề?


4
Thoạt nhìn, dường như lớp InventoryItem đang cố gắng làm quá nhiều bằng cách tính giá, trả lại một mức giá nhất định là một điều nhưng giá bán và quy tắc kinh doanh đặc biệt không nên là địa chỉ trong InventoryItem. Đưa ra một lớp để tính giá của bạn và để nó xử lý nhu cầu dữ liệu từ Đơn hàng, Hàng tồn kho và Khách hàng, v.v.
Chris

@Chris, vâng, tách ra logic giá có lẽ là một ý tưởng tốt. Vấn đề của tôi là một đối tượng như vậy sẽ được gắn chặt với tất cả các đối tượng liên quan đến trật tự. Đó là phần làm phiền tôi và phần tôi tự hỏi liệu tôi có thể tránh được không.
Winston Ewert

1
Nếu một cái gì đó, tôi không muốn gọi nó là bất cứ điều gì, cần tất cả thông tin đó thì bằng cách nào đó nó phải tiêu thụ thông tin này để tạo ra kết quả mong muốn. Nếu bạn có hàng tồn kho, vật phẩm, khách hàng và vv đã được xây dựng, thì việc triển khai logic kinh doanh trong khu vực riêng của nó có ý nghĩa nhất. Tôi không thực sự có một giải pháp tốt hơn.
Chris

Câu trả lời:


6

Về cơ bản, chúng tôi đã có cùng trải nghiệm khi tôi làm việc và chúng tôi đã giải quyết nó bằng cách có một lớp OrderBusinessLogic. Đối với hầu hết các phần bố trí bạn đã mô tả hoạt động cho phần lớn doanh nghiệp của chúng tôi. Thật đẹp, sạch sẽ và đơn giản. Nhưng trong những trường hợp bạn đã mua bất kỳ 2 từ danh mục này, chúng tôi coi đó là một "hoạt động kinh doanh" và có lớp OrderBL tính toán lại tổng số bằng cách duyệt qua các đối tượng cần thiết.

Có phải là một giải pháp hoàn hảo, không. Chúng ta vẫn có một lớp biết quá nhiều về các lớp khác, nhưng ít nhất chúng ta đã chuyển nhu cầu đó ra khỏi các đối tượng kinh doanh và thành một lớp logic kinh doanh.


2
Khi nghi ngờ thêm một lớp khác.
Chris

1

Âm thanh như bạn cần một đối tượng riêng biệt chiết khấu (hoặc một danh sách của họ) mà theo dõi tất cả những thứ đó, và sau đó áp dụng chiết khấu (s) vào thứ tự, một cái gì đó giống như Order.getTotal(Discount)hoặc Discount.applyTo(Order)hoặc tương đương.


Tôi có thể thấy nơi đặt mã trong Giảm giá thay vào đó trong đối tượng Khoảng không quảng cáo sẽ tốt hơn. Nhưng đối tượng giảm giá dường như vẫn sẽ phải truy cập thông tin từ tất cả các đối tượng khác nhau để hoàn thành công việc. Vì vậy, điều đó không, ít nhất là như tôi có thể thấy, giải quyết vấn đề.
Winston Ewert

2
Tôi nghĩ rằng đối tượng Giảm giá là một ý tưởng tốt, nhưng tôi sẽ làm cho nó triển khai mô hình người quan sát ( en.wikipedia.org/wiki/Observer_potype ), với Giảm giá là chủ đề của mẫu
BlackICE

1

Hoàn toàn ổn khi truy cập dữ liệu từ các lớp khác. Tuy nhiên, bạn muốn đây là một mối quan hệ một chiều. Ví dụ: giả sử ClassOrder truy cập CallItem. Lý tưởng nhất là ClassItem không nên truy cập ClassOrder. Điều tôi nghĩ rằng bạn đang thiếu trong Lớp Đặt hàng của bạn là một loại logic kinh doanh nào đó có thể hoặc không thể đảm bảo một lớp như Walter đề xuất.

Chỉnh sửa: Phản hồi bình luận của Winston

Tôi không nghĩ rằng bạn cần một đối tượng hàng tồn kho ... ít nhất là theo cách bạn đang sử dụng nó. Thay vào đó tôi sẽ có một lớp kiểm kê quản lý cơ sở dữ liệu hàng tồn kho.

Tôi sẽ đề cập đến các mặt hàng tồn kho bằng một ID. Mỗi đơn hàng sẽ chứa một danh sách ID hàng tồn kho và số lượng tương ứng.

Sau đó, tôi sẽ tính tổng số đơn đặt hàng với một cái gì đó như thế này.
Inventory.GetCost (Mục, tên khách hàng, ngày)

Sau đó, bạn có thể có chức năng trợ giúp khác như:

Inventory.ItemsLefts (int itemID)
Inventory.AddItem (int itemID, int quant) Inventory.RemoveItem (int itemID,
int quant)
Inventory.AddBusinessRule (...)
Inventory.DeleteBusinessRule (...)


Nó hoàn toàn tốt để yêu cầu dữ liệu từ các lớp liên quan chặt chẽ. Vấn đề phát sinh khi tôi truy cập dữ liệu từ các lớp liên quan gián tiếp. Để triển khai logic đó trong lớp Đơn hàng sẽ yêu cầu lớp Đơn hàng phải được xử lý trực tiếp với đối tượng Khoảng không quảng cáo (chứa dữ liệu giá cần thiết). Đó là phần làm phiền tôi vì nó được ghép nối với các lớp mà (lý tưởng nhất) nó sẽ không biết gì về nó.
Winston Ewert

Về cơ bản, ý tưởng của bạn sẽ là loại bỏ OrderItem thay vì Order theo dõi tất cả thông tin đó. Sau đó, thật dễ dàng để chuyển thông tin đó cho một đối tượng khác để biết thông tin về giá. Điều đó có thể làm việc. (Trong bối cảnh cụ thể, ví dụ này dựa trên OrderItem quá phức tạp và thực sự cần phải là đối tượng của chính nó)
Winston Ewert

Điều không có ý nghĩa với tôi là tại sao bạn muốn có Inventory được tham chiếu bằng cách sử dụng số id thay vì tham chiếu đối tượng. Nó có vẻ tốt hơn đối với tôi để theo dõi các tham chiếu đối tượng và số lượng sau đó id mục và tham chiếu.
Winston Ewert

Tôi không thực sự đề nghị điều đó cả. Tôi nghĩ rằng bạn vẫn nên có một lớp hoặc cấu trúc cho các mục đặt hàng. Tôi chỉ không nghĩ rằng các đối tượng vật phẩm tồn kho riêng lẻ nên có giá bên trong chủ yếu bởi vì tôi không chắc chắn làm thế nào bạn có thể lấy nó trong đó mà không hỏi một số loại cơ sở dữ liệu. Đơn hàng hoặc hàng tồn kho sẽ hoàn toàn là một lớp dữ liệu chứa định danh vật phẩm và số lượng. Thứ tự sẽ có một danh sách các đối tượng này.
Pemdas

Tôi không thực sự chắc chắn những gì bạn đang hỏi trong bình luận thứ hai. Không phải tất cả mọi thứ phải là một đối tượng. Tôi thực sự không chắc chắn làm thế nào bạn sẽ xác định vị trí một mục cụ thể mà không có một số loại id.
Pemdas

0

Sau khi suy nghĩ về điều này nhiều hơn, tôi đã đưa ra chiến lược thay thế của riêng mình.

Xác định một lớp Giá. Inventory.GetPrice()trả về một đối tượng giá

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();
}

Bây giờ lớp Giá (và có thể một số lớp liên quan) gói gọn logic của giá và đơn hàng không phải lo lắng về nó. Giá không biết gì về Order / OrderItem thay vào đó chỉ đơn giản là có thông tin được cung cấp cho nó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.