0

我正在开发一个 Web 服务(在 Ruby 中),它需要为它收到的每条消息做一些不同的事情。

在我的 Web 服务可以处理消息之前,它必须做不同的事情:

  • 消毒(例如删除 HTML/JS)
  • 检查格式(例如提供的有效电子邮件?)
  • 检查黑名单中的IP
  • 调用第 3 方 Web 服务
  • 加上 10-30 个其他东西

我正在考虑实现一个过滤器/复合过滤器架构,其中每个步骤/阶段都是一个过滤器。例如,我可以有这些过滤器

  • 清理输入过滤器
  • 电子邮件过滤器
  • 国家代码过滤器
  • 黑名单过滤器

每个过滤器都应该可以拒绝一条消息,所以我正在考虑过滤器应该引发/抛出异常。

这将提供很大的灵活性,并希望有一个易于理解的代码库。

你会怎么做?以上设计的优缺点是什么?

4

1 回答 1

1

对于过滤器本身实际发生故障(例如黑名单不可用等)并通过true/false返回值或如您还建议的那样抛出标签来指示有效/无效状态的情况,我会留下例外。

如果您不想在第一次失败时停止,但无论如何都要执行所有过滤器,您应该选择布尔返回类型并将它们连接在一起(success &= next_filter(msg)

如果我正确理解了您的情况,过滤器既可以修改消息,也可以检查其他来源的有效性(例如黑名单)。

所以我会这样做:

module MessageFilters

  EmailValidator = ->(msg) do
    throw :failure unless msg.txt =~ /@/
  end

  HTMLSanitizer = ->(msg) do
    # this filter only modifies message, doesn't throw anything
    # msg.text.remove_all_html!
  end
end

class Message

  attr_accessor :filters
  def initialize
    @filters = []
  end

  def execute_filters!
    begin
      catch(:failure) do
        filters.each{|f| f.call self}
        true # if all filters pass, this is returned, else nil
      end
    rescue => e
      # Handle filter errors
    end
  end
end

message = Message.new

message.filters << MessageFilters::EmailValidator
message.filters << MessageFilters::HTMLSanitizer

success = message.execute_filters!  # returns either true or nil
于 2012-10-11T14:48:59.983 回答