AOP in Ruby
class SnippetsUseCase
  attr_reader :repository, :logger, :snippets

  def initialize(snippets_repository = SnippetsRepository.new, logger = Logger.new)
    @repository = snippets_repository
    @logger = logger

    @snippets = []
  end

  def user_pushes(snippet)
    snippets << snippet

    repository.push(snippet,
                    success: self.method(:user_pushed),
                    failure: self.method(:user_fails_to_push))
  end

  def user_pushed(snippet)
    logger.info "Successfully pushed: #{snippet.name} (#{snippet.language})"
  end

  def user_fails_to_push(snippet, pushing)
    snippets.delete(snippet)

    logger.error "Failed to push the snippet: #{pushing.error}"
  end
end
Refactor with AOP techniques.
class SnippetsUseCase
  attr_reader :snippets

  def initialize
    @snippets = []
  end

  def user_pushes(snippet)
    snippets << snippet
  end

  def user_pushed(snippet); end

  def user_fails_to_push(snippet, pushing)
    snippets.delete(snippet)
  end
end
require 'aquarium'

class SnippetsUseCaseGlue
  attr_reader :usecase, :repository, :logger

  include Aquarium::Aspects

  def initialize(usecase, repository, logger)
    @usecase = usecase
    @repository = repository
    @logger = logger
  end

  def inject!
    Aspect.new(:after, object: usecase, calls_to: :user_pushes) do |join_point, obj, snippet|
      repository.push(snippet,
                      success: usecase.method(:user_pushed),
                      failure: usecase.method(:user_fails_to_push))
    end

    Aspect.new(:after, object: usecase, calls_to: :user_pushed) do |join_point, obj, snippet|
      logger.info "Successfully pushed: #{snippet.name} (#{snippet.language})"
    end

    Aspect.new(:after, object: usecase, calls_to: :user_fails_to_push) do |join_point, obj, snippet, pushing|
      logger.error "Failed to push the snippet: #{pushing.error}"
    end
  end
end
class Application
  def initialize
    @snippets = SnippetsUseCase.new
    @snippets_repository = SinppetsRepository.new
    @logger = Logger.new
    @sinppets_glue = SnippetsUseCaseGlue.new(@snippets, @snippets_repository, @logger)

    @sinppets_glue.inject!
  end
end

我现在对 AOP 的理解是更多的解耦,让 object 更内聚,只关心自己领域内的知识,不用去理会日志,持久化,等等。。