Muitas vezes, meus objetos de negócios tendem a ter situações em que as informações precisam cruzar os limites de objetos com muita frequência. Ao fazer OO, queremos que as informações estejam em um objeto e, tanto quanto possível, todo código que lida com essas informações esteja nesse objeto. No entanto, as regras de negócios não seguem esse princípio, causando problemas.
Como exemplo, suponha que tenhamos um Pedido que tenha vários OrderItems que se refiram a um InventoryItem que tenha um preço. Invoco Order.GetTotal () que soma o resultado de OrderItem.GetPrice () que multiplica uma quantidade por InventoryItem.GetPrice (). Por enquanto, tudo bem.
Mas então descobrimos que alguns itens são vendidos com um acordo de dois por um. Podemos lidar com isso fazendo com que OrderItem.GetPrice () faça algo como InventoryItem.GetPrice (quantidade) e deixe InventoryItem lidar com isso.
No entanto, descobrimos que o acordo de dois por um dura apenas um período de tempo específico. Esse período precisa ser baseado na data do pedido. Agora, alteramos OrderItem.GetPrice () para InventoryItem.GetPrice (quatity, order.GetDate ())
Porém, precisamos oferecer suporte a preços diferentes, dependendo de quanto tempo o cliente está no sistema: InventoryItem.GetPrice (quantidade, pedido.GetDate (), pedido.GetCustomer ())
Porém, as transações de dois por um se aplicam não apenas à compra de vários itens do mesmo inventário, mas também a vários itens de uma categoria de inventário. Nesse ponto, levantamos as mãos e fornecemos o item de pedido ao InventoryItem e permitimos que ele percorra o gráfico de referência do objeto por meio de acessadores para obter as informações necessárias: InventoryItem.GetPrice (this)
TL; DR Quero ter um baixo acoplamento de objetos, mas as regras de negócios geralmente me forçam a acessar informações de todo o lugar para tomar decisões específicas.
Existem boas técnicas para lidar com isso? Outros acham o mesmo problema?
fonte
Respostas:
Tivemos basicamente a mesma experiência em que trabalho e resolvemos isso tendo uma classe OrderBusinessLogic. Na maioria das vezes, o layout que você descreveu funciona para a maioria dos nossos negócios. É agradável, limpo e simples. Mas nas ocasiões em que você compra 2 desta categoria, tratamos isso como uma "execução comercial" e a classe OrderBL recalcula os totais percorrendo os objetos necessários.
É uma solução perfeita, não. Ainda temos uma classe sabendo muito sobre as outras classes, mas pelo menos transferimos essa necessidade dos objetos de negócios para uma classe de lógica de negócios.
fonte
Parece que você precisa de um objeto separado de desconto (ou uma lista deles) que mantém o controle de todas as coisas, e depois aplicar (s) o desconto à Ordem, algo como
Order.getTotal(Discount)
ouDiscount.applyTo(Order)
ou similar.fonte
Não há problema em acessar dados de outras classes. No entanto, você deseja que este seja um relacionamento direcional. Por exemplo, suponha que ClassOrder acesse CallItem. Idealmente, ClassItem não deve acessar ClassOrder. O que acho que está faltando na sua classe de pedidos é algum tipo de lógica comercial que pode ou não justificar uma classe como a sugerida por Walter.
Edit: Resposta ao comentário de Winston
Eu não acho que você precise de um objeto de item de inventário ... pelo menos da maneira que você está usando. Em vez disso, eu teria uma classe de inventário que gerenciava um banco de dados de inventário.
Eu me referiria a itens de inventário por um ID. Cada pedido conteria uma lista de IDs de inventário e uma quantidade correspondente.
Então eu calcularia o total do pedido com algo assim.
Inventory.GetCost (Itens, customerName, date)
Então você pode ter outra função auxiliar como:
Inventory.ItemsLefts (int ID do item)
Inventory.AddItem (int ID do item, quantidade int)
Inventory.RemoveItem (int itemID, quantidade int)
Inventory.AddBusinessRule (...)
Inventory.DeleteBusinessRule (...)
fonte
Depois de pensar mais sobre isso, criei minha própria estratégia alternativa.
Defina uma classe de preço.
Inventory.GetPrice()
retorna um objeto de preçoAgora, a classe Price (e possivelmente algumas classes relacionadas) encapsula a lógica do preço e o pedido não precisa se preocupar com isso. O preço não sabe nada sobre Order / OrderItem, apenas fornece informações.
fonte