객체 경계에 걸친 정보 유출


10

종종 비즈니스 객체에는 정보가 객체 경계를 너무 자주 넘어야하는 상황이 있습니다. OO를 수행 할 때는 정보가 하나의 객체에 있고 가능한 한 해당 정보를 처리하는 모든 코드가 해당 객체에 있어야합니다. 그러나 비즈니스 규칙은이 원칙을 따르지 않아 문제가 발생합니다.

예를 들어 가격이있는 InventoryItem을 나타내는 많은 OrderItem이있는 Order가 있다고 가정합니다. InventoryItem.GetPrice ()로 수량을 곱하는 OrderItem.GetPrice ()의 결과를 합산하는 Order.GetTotal ()을 호출합니다. 여태까지는 그런대로 잘됐다.

그러나 우리는 일부 품목이 한 거래에 2 개로 판매되는 것을 발견했습니다. OrderItem.GetPrice ()가 InventoryItem.GetPrice (Quantity)와 같은 작업을 수행하고 InventoryItem이이를 처리하게함으로써이를 처리 할 수 ​​있습니다.

그러나 일대일 거래는 특정 기간 동안 만 지속됩니다. 이 기간은 주문 날짜를 기준으로해야합니다. 이제 OrderItem.GetPrice ()를 InventoryItem.GetPrice (quatity, order.GetDate ())로 변경하십시오.

그러나 고객이 시스템에 얼마나 오래 있었는지에 따라 다른 가격을 지원해야합니다. InventoryItem.GetPrice (Quantity, order.GetDate (), order.GetCustomer ())

그러나 일대일 거래는 동일한 인벤토리 항목을 여러 개 구매하는 것뿐만 아니라 InventoryCategory의 모든 항목을 여러 개 구매하는 경우에도 적용됩니다. 이 시점에서 우리는 손을 내밀어 InventoryItem에 주문 항목을 제공하고 접근자를 통해 객체 참조 그래프 위로 이동하여 필요한 정보를 얻도록 허용합니다. InventoryItem.GetPrice (this)

TL; DR 객체에서 낮은 결합을 원하지만 비즈니스 규칙에 따라 특정 결정을 내리기 위해 모든 곳에서 정보에 액세스해야하는 경우가 종종 있습니다.

이것을 다루는 좋은 기술이 있습니까? 다른 사람들도 같은 문제를 발견합니까?


4
언뜻보기에 InventoryItem 클래스는 가격을 계산하여 너무 많은 일을 시도하고, 주어진 가격을 반환하는 것은 하나의 일이지만 판매 가격과 특별 비즈니스 규칙은 InventoryItem의 주소가되어서는 안됩니다. 가격 계산을위한 클래스를 출시하고 주문, 재고 및 고객 등의 데이터 요구를 처리하도록하십시오.
Chris

@Chris, 예, 가격 책정 논리를 분리하는 것이 좋습니다. 내 문제는 그러한 객체가 모든 주문 관련 객체에 단단히 결합된다는 것입니다. 그것이 저를 귀찮게하는 부분과 피할 수 있는지 궁금한 부분입니다.
Winston Ewert가

1
무언가를 부르고 싶지 않고 모든 정보가 필요한 경우 원하는 결과를 얻으려면이 정보를 사용해야합니다. 재고, 품목, 고객 등이 이미 구축 된 경우 자체 영역에서 비즈니스 로직을 구현하는 것이 가장 합리적입니다. 더 나은 해결책이 없습니다.
Chris

답변:


6

우리는 기본적으로 내가 일하는 것과 동일한 경험을했고 OrderBusinessLogic 클래스를 사용하여 해결했습니다. 대부분의 경우 설명하신 레이아웃은 대부분의 비즈니스에서 작동합니다. 멋지고 깨끗하며 간단합니다. 그러나이 범주에서 2 개를 구매 한 경우에는이를 "비즈니스 실행"으로 취급하고 OrderBL 클래스가 필요한 오브젝트를 순회하여 총계를 다시 계산하도록합니다.

완벽한 솔루션입니까? 우리는 여전히 하나의 클래스가 다른 클래스에 대해 너무 많이 알고 있지만 적어도 비즈니스 객체에서 비즈니스 로직 클래스로 필요한 것을 이동했습니다.


2
확실치 않은 경우 다른 클래스를 추가하십시오.
Chris

1

당신 같은 소리는 모든 물건을 추적 별도의 할인 객체 (또는 이들의리스트)가 필요하고 뭔가처럼 주문에 할인 (들)을 적용 Order.getTotal(Discount)하거나 Discount.applyTo(Order)또는 유사한.


인벤토리 개체 대신 코드를 할인에 넣는 것이 더 나은 곳을 알 수 있습니다. 그러나 할인 개체는 여전히 모든 다른 개체의 정보에 액세스하여 작업을 완료해야합니다. 따라서 적어도 내가 볼 수있는 한 문제를 해결하지 못합니다.
Winston Ewert

2
나는 할인 객체가 좋은 아이디어라고 생각하지만, 나는 그것이 관찰자 패턴 (구현 만들 것 en.wikipedia.org/wiki/Observer_pattern을 패턴의 대상으로 할인 (들)와 함께)
BlackICE에

1

다른 클래스의 데이터에 액세스해도 괜찮습니다. 그러나 이것이 한 방향 관계가되기를 원합니다. 예를 들어, ClassOrder가 CallItem에 액세스한다고 가정하십시오. 이상적으로 ClassItem은 ClassOrder에 액세스하지 않아야합니다. 주문 클래스에서 누락 된 것으로 생각되는 것은 Walter가 제안한 클래스를 보증하거나 보증하지 않는 일종의 비즈니스 논리입니다.

편집 : 윈스턴의 의견에 대한 답변

적어도 당신이 그것을 사용하는 방식으로 인벤토리 아이템 객체가 전혀 필요하지 않다고 생각합니다. 대신 인벤토리 데이터베이스를 관리하는 인벤토리 클래스가 있습니다.

ID로 인벤토리 항목을 참조합니다. 각 주문에는 재고 ID 목록과 해당 수량이 포함됩니다.

그런 다음이 순서로 총계를 계산합니다.
Inventory.GetCost (Items, customerName, date)

그런 다음 다음과 같은 다른 도우미 기능을 가질 수 있습니다.

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


밀접하게 관련된 클래스의 데이터를 요청하는 것이 좋습니다. 간접적으로 관련된 클래스의 데이터에 액세스 할 때 문제가 발생합니다. Order 클래스에서 해당 로직을 구현하려면 Order 클래스가 Inventory 오브젝트 (필요한 가격 책정 데이터 포함)를 직접 처리해야합니다. 그것은 (이상적으로는) 알지 못하는 클래스에 Order를 연결하기 때문에 나를 귀찮게하는 부분입니다.
Winston Ewert

본질적으로 아이디어는 OrderItem을 제거하는 것이 아니라 Order는 모든 정보 자체를 추적합니다. 그런 다음 가격 정보를 위해 해당 정보를 다른 개체로 쉽게 전달할 수 있습니다. 작동 할 수 있습니다. (특정 시나리오에서이 예제는 OrderItem을 기반으로 느슨하게 이루어졌으며 실제로는 고유 한 오브젝트 여야 함)
Winston Ewert

이해가되지 않는 이유는 객체 참조 대신 ID 번호를 사용하여 인벤토리를 참조하려는 이유입니다. 객체 참조 및 수량을 추적 한 다음 항목 ID 및 참조를 추적하는 것이 더 나을 것 같습니다.
Winston Ewert가

나는 그것을 전혀 제안하지 않습니다. 주문 항목에 대한 클래스 또는 구조가 여전히 있어야한다고 생각합니다. 나는 개별 인벤토리 항목 객체가 주로 내부 가격을 가져야한다고 생각하지 않습니다. 왜냐하면 주로 일종의 데이터베이스를 요구하지 않고 어떻게 얻을 수 있는지 확실하지 않기 때문입니다. 주문 또는 재고 품목은 품목 식별자 및 수량을 포함하는 데이터 클래스입니다. 주문 자체에는 이러한 객체의 목록이 있습니다.
Pemdas

나는 당신이 두 번째 의견에서 무엇을 묻고 있는지 잘 모르겠습니다. 모든 것이 객체 일 필요는 없습니다. 어떤 종류의 ID없이 특정 항목을 찾는 방법을 잘 모르겠습니다.
Pemdas

0

이것에 대해 더 많이 생각한 후에, 나는 내 자신의 대안 전략을 생각해 냈습니다.

Price 클래스를 정의하십시오. Inventory.GetPrice()가격 개체를 반환

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

이제 Price 클래스 (및 일부 관련 클래스)는 가격 책정의 논리를 캡슐화하므로 주문에 대해 걱정할 필요가 없습니다. 가격은 주문 / 주문 항목에 대한 정보를 모르는 대신 주문 / 주문 항목에 대해 아무것도 모릅니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.