Внедрение инфракрасного интерфейса в сервис приложения - PullRequest
0 голосов
/ 08 мая 2011

У меня есть две совокупности: рекламодатель и оплата.

Я использую платежный шлюз Paypal и Authorize.net.Поэтому я создал интерфейс на нижнем уровне.

interface IPaymentMethod
{
   void ProcessPayment(PaymentInfo paymentInfo);
}

и снова реализовал его на нижнем уровне.

Public class PaypalPaymentGateway : IPaymentMethod
{
    public void ProcessPayment(PaymentInfo paymentInfo)
    {
        // call Paypal api and pass paymentinfo
    }
}

// То же самое для шлюза оплаты authorize.net. Ниже приведен мой класс обслуживания приложения

public class PaymentGatewayService : IPaymentGatewayService
{

    IPaypalMethod paypalMethod;

    public PaymentGatewayService(IPaypalMethod paypalMethod)
    {            
        this.paypalMethod = paypalMethod;
        if (paypalMethod == null)
          throw new Exception("PaypalMethod not initialized");
    }

     public void DepositFundInAdvertiser
       (PaymentInfo paymentInfo, RegistrationID advertiserRegistrationID)
     {
        if (paymentMethod != null)            
            throw new Exception("PaymentMethod empty.");

        PaymentResult paymentResult= 
          paymentMethod.ProcessPayment(paymentInfo);
        Advertiser advertiser = advertiserRepository
          .Find(advertiserRegistrationID);
        advertiser.AddAdvertiserFund(paymentInfo.PaymentTotal);
        advertiserRepository.Save(advertiser);
    }
}

На уровне приложения - могу ли я внедрить интерфейс PaypalMethod в конструктор уровня приложения и сделать следующее в методе DepositFundInAdvertiser?

Помните, IPaypalMethod создан и реализован на нижнем уровне.

Ответы [ 2 ]

1 голос
/ 09 мая 2011

Чтобы прокомментировать мой комментарий. Я бы также поставил PaymentService на инфраструктурный уровень как инфраструктурный сервис. Но, как сказал Арнис, вы также должны подумать, как модель отреагирует на это действие - Pay.

У меня (не уверен), вероятно, был бы какой-то вид PaymentService в слое обслуживания приложений, который работает как с сущностями Advertiser, так и с Payment (через IAdvertiserRepository и IPaymentRepository, внедренный через конструктор).

В методе (запись этого метода в memcode): PaymentService.PayAdvert (Рекламодатель рекламодателя, Рекламное объявление, Payment paymentInfo) { advertiser.BuyAdvertising (AdvertPayment.Create (объявление, paymentInfo)) }

Метод BuyAdvertising переводит и Advert, и Payment в класс AdvertPayment (у которого есть статический метод create для самого ctor. Этот класс может быть полезен, если вы хотите получить коллекцию PaymentHistory для Advertiser, которая содержит AdvertPayments в порядке дат. Но BuyAdvertising создает событие домена BuyAdvertisingEvent, которое запускает обработчик событий на уровне приложений BuyAdvertisingEventHandler.

В этом обработчике событий ваш IPaypalGatewayService внедрен в конструктор. С событием у нас есть информация об оплате. Если платеж выполнен успешно, EventHandler может также добавить IAdvertiserRepository в ctor и сохранить AdvertPayment в коллекцию истории платежей Advertiser.

тогда BuyAdvertising может определить результат платежной транзакции, проверив, оплачено ли объявление и добавлено ли оно в коллекцию истории.

Надеюсь, вы поняли картину. Таким образом, у вас есть несколько инструментов, таких как событие, которое объявляется в модели домена и запускается рекламодателем. Модель начинает действовать, и вы переместили логику в области технологий против PayPal через DomainEventHandler, но не полностью локализовали логику на уровне приложений. Элемент управления находится в домене, но детали, которые не заботятся о домене, размещены на нижнем уровне.

По моему опыту, эти сценарии являются общими для меня, и вы обычно идете легким путем, позволяя сервису приложений выполнять все разговоры с инфраслоем. Но затем вы закрываете анемичный дизайн модели, потому что что остается модели делать? Просто проверка свойств? Просто управление агрегатами и коллекциями? Я думаю, что это еще не все. Он также должен содержать множество методов действия сущности (я их так называю ... :)), таких как BuyAdvertisment.

/ Приветствие

1 голос
/ 09 мая 2011

Ваш подход кажется достаточно хорошим.

Только я бы определил IPayer абстракцию внутри уровня домена вместо уровня инфраструктуры.

Потому что (скорее всего) ответственность за модель доменного имени состоит в том, чтобы решить, как реагировать, если платеж [не] успешен.

//in domain model
public class IPayer{
  bool Pay(Money amountToBePaid, BankAccount account);;
}
public class Payment{
  public void Pay(IPayer payer){
   EnsurePaymentCanBePaid();
   IsPaid=payer.Pay(AmountToBePaid,Account);
   if(!IsPaid) throw new Exception("Payment failed!");
  }
}
//in infrastructure layer
public class PayPalPayer:IPayer{
  public bool Pay(Money amountToBePaid, BankAccount account){
    //bla bla
  }
}
...