Обращение к пользователю из слоя бизнес-логики
От: MozgC США http://nightcoder.livejournal.com
Дата: 28.03.11 02:47
Оценка:
Здравствуйте,

Похожая тема на этом форуме уже была, но я решил обсудить более сложные случаи.

Не всегда получается избежать обращения к пользователю из методов бизнес-логики. В простых случаях я обычно передаю callback'и — либо интерфейс, либо делегат, т.е. например так:

public void SomeBusinessLogicMethod(..., ISomeCallback callback)
{
  ...
  if(callback.Ask(message) == DialogResult.No)
    return;
  ...
}


Но давайте рассмотрим такую ситуацию. В слое бизнес-логики есть базовый класс и несколько наследников:

class SupplierOrderGenerator { ... }

class StockOrderGenerator : SupplierOrderGenerator { ... }

class AnotherOrderGenerator : SupplierOrderGenerator { ... }

// и т.д.


Конкретный тип выбирается в рантайме с помощью фабричного метода, так же находящегося в слое бизнес-логики

class SupplierService
{
  ...
  public SupplierOrderGenerator GetSupplierOrderGenerator(Supplier supplier)
  {
     ...
  }
  ...
}


И вот теперь, в одном из классов, предположим в StockOrderGenerator, нужно обратиться к пользователю:

class StockOrderGenerator : SupplierOrderGenerator
{
  ...
  public void SomeMethod(...)
  {
    ..
    // здесь нужно, чтобы оператор подтвердил что мы продадим запчасть со склада со скидкой и выбрал по какой цене
    // т.е. если бы я тупо зашился бы на WinForms то это могло бы выглядеть как-то так:
    using(var form = new SomeForm("bla bla bla Customer wants this part for $100 bla bla Please choose lowest possible price bla bla bla", ...))
    {
      if(form.ShowDialog() == DialogResult.Ok)
      {
        decimal chosenPrice = form.ChosenPrice;
        ...
      }
    }
    ...
  }
  ...
}


Получается, что чтобы передать callback данному методу, его надо передать сначала из UI классу SupplierService, тот передаст его фабричному методу GetSupplierOrderGenerator, тот передаст его уже классу StockOrderGenerator. Это при том, что остальным классам наследникам от SupplierOrderGenerator этот коллбек вообще не нужен, но из-за StockOrderGenerator мы его будем тянуть по всей цепочке. Не нравится мне это.

Что посоветуете?

Тут у меня еще мысли находят на паттерн Service Locator, или правильнее наверное тут будет сказать Dependency Injection Container, но мне почему-то кажется что этот паттерн не далеко ушел от глобальных переменных (или я не умею его готовить?). Смущает, что каждый может указать какую-то свою реализацию (читай — изменить значение глобальной переменной), а можно вообще забыть указать конкретную реализацию (если же коллбек явно надо в метод передавать, то точно не пропустишь). Или я заморачиваюсь?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.