Поведение службы в сущности - как избежать внедрения службы в сущность? - PullRequest
4 голосов
/ 30 июня 2010

У меня есть структура объекта следующим образом:

IManager: IDeletable
{
IEnumerable<IFund> Funds {get;}
IFailureNotification Delete();
}

IFund : IDeletable
{
IEnumerable<IFundClass> FundClasses
IFailureNotification Delete();
}

IFundClass: IDeletable, IInvestable
{
IFailureNotification Delete();
}

И у меня есть служба, которая берет IDeletable и вызывает на ней команду Delete.В зависимости от возвращаемого значения он либо фиксирует транзакцию, либо откатывает ее обратно.Я использую NHibernate для сохранения классов, поэтому не могу поместить RI в БД и поймать исключение (что мне бы не понравилось в любом случае).

Это классический случай полиморфизма и Managerперебирает свои Funds и удаляет их перед удалением, Fund в свою очередь удаляет FundClass es перед удалением, поэтому служба может просто взять любую сущность, реализующую IDeletable, и знать, что удаление выполнитдействия на всех уровнях.

Вот проблема: классы фондов должны определить, используются ли они в совершенно отдельном контексте, используя интерфейс IInvestable, о котором они ничего не знают.Для этого требуется служба - IInvestmentCalculationService.

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

Я немного искушенпо модели «События домена» здесь: http://www.udidahan.com/2009/06/14/domain-events-salvation/ но я не уверен, что это правильно, так как я пытаюсь получить данные обратно из обработчика сработавших событий - который будет работать, но пахнет немного неправильно, и всепримеры показывают только огонь и забывают ситуации.

У кого-нибудь есть предложения?

Ответы [ 4 ]

2 голосов
/ 01 ноября 2010

Спасибо всем за помощь, я был очень впечатлен аудиторией, которую я привлек!Мне особенно понравилась философия mcintyre, и с тех пор она искренне повлияла на мое мышление.В этом случае, хотя мы пошли для двойной отправки.Чувствует себя немного более стабильно.

Приветствия

2 голосов
/ 02 июля 2010

«Очевидно, я не хочу вводить InvestmentCalculationService».

Это слово «очевидно», которое мне не нравится. Я до сих пор не чувствовал себя вдохновленным результатами поиска в Google «инъекций услуг в сущности». Верхние посты по теме сводятся к тому, что «это не правильно, и вы можете использовать доменные события / двойную рассылку, чтобы сделать это в любом случае, поэтому не делайте этого».

Лично я считаю, что это нормально - внедрять сервисы в сущности и считаю, что вам следует перестать беспокоиться об этом и делать это. Возможно, не внедрите весь InvestmentCalculationService, но добавьте BitsOfInvestmentCalculationServiceThatINeedToKnowAboutService, если вы чувствуете, что объект не должен иметь доступ ко всему этому.

События домена бесполезны в вашей ситуации, если вы не добавите возвращаемое значение (которое, по сути, превращает его в наряженный локатор службы) и с двойной диспетчеризацией то, что вы вводите, должно исходить из более высокого уровня стека вызовов - вероятно, введенное значение в класс точки входа, который, по всей вероятности, не использует эту зависимость.

Просто внедрите InvestmentCalculationService в организацию и продолжайте свою жизнь.

1 голос
/ 30 июня 2010

Одна вещь, которую мы сделали в подобных ситуациях, - это чтобы Delete не выполнял фактическое удаление, а вместо этого использовал параметр сбора для вещей, которые нужно удалить.Метод Delete () регистрирует себя и любые другие объекты, которые затем воспроизводятся другим сервисом.

0 голосов
/ 24 июля 2010

Как насчет интерфейса

public interface ICanBeDeleted<T>
{
    bool CanBeDeleted(T itemToBeDeleted);
}

Перед тем, как действительно удалить, спросите свой контейнер обо всех реализациях этого интерфейса, вызовите функцию CanBeDeleted и, если что-либо вернет false, не удаляйте. Ваш InvestmentCalculationService реализует ICanBeDeleted<FundClass> и зарегистрируется в контейнере.

...