Как обрабатывать исключения в DCI

Представьте, что у вас есть контекст, который обрабатывает денежные переводы между учетными записями пользователей.

class Account < ActiveRecord::Base
  belongs_to :user
end

class MoneySender < SimpleDelegator

  class NotEnoughBalanceError < StandardError ; ; end

  def initialize(account)
    super(account)
  end

  def send_money(destination_account, amount)
    raise NotEnoughBalanceError unless can_send?(amount)
    self.transaction do
      self.balance -= amount
      destination_account.balance += amount
    end
    self.balance
  end

  def can_send?(amount)
    self.balance >= amount
  end

end

class HandleMoneyTransferContext

  def initialize(source, destination, amount)
    @source = source
    @destination = destination
    @amount = amount
  end

  def transfer
    sender = MoneySender.new(@source
    sender.send_money(@destination, @amount)
  end

end

И денежные переводы запускаются веб-приложением и контроллером рельсов, который обрабатывает эти операции, что-то вроде этого

class AccountsController < AplicationController

  def transfer
    source = Account.find(params[:id])
    destination = Account.find(params[:destination_account])
    HandleMoneyTransferContext.new(source, destination, params[:amount]).transfer
    render 'success_page'
  rescue MoneySender::NotEnoughBalanceError => e
    flash[:error] = t(accounts.transfer.not_enough_money)
    render 'error_page', status: 400
  end

end

Итак, мой вопрос: нормально ли, чтобы контекст вызывал исключения? Должен ли я поймать исключение роли в контексте и вызвать исключение контекста? (Пользователи контекста не должны знать, какие роли используются). Есть ли лучшее решение?

Спасибо

1 ответ

Контекст - это просто объект (да, есть ограничения, поэтому не все объекты являются контекстами), и в рамках операции объекта есть некоторые исключения в порядке. Например, ArgumentNil может быть действительным, если вместо того, что должно было быть RolePlayer, будет nil. Итак, чтобы ответить на ваш вопрос. Так что да, контекст может выдавать исключения, если они связаны с системными операциями, которые инкапсулирует контекст.

Тем не менее, я не вижу много DCI в вашем примере кода. Например, в контексте нет ролевых методов, и кажется, что фактическое поведение принадлежит классу, а не роли или объекту. На сайте fulloo.info есть пример перевода денег, а также один из примеров бордового камня. Вы можете прочитать больше об использовании maroon для создания DCI в ruby (хотя синтаксис был упрощен после написания этой статьи вместе с примерами, он все же должен быть хорошей отправной точкой)

Другие вопросы по тегам