【问题标题】:How to implement complex message validation/handling flow如何实现复杂的消息验证/处理流程
【发布时间】:2012-10-11 12:41:36
【问题描述】:

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

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

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

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

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

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

这将提供很大的灵活性,并希望代码库是 容易理解。

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

【问题讨论】:

    标签: ruby design-patterns architecture business-logic


    【解决方案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
    

    【讨论】:

    • 谢谢,这正是我想要的。我正在考虑将消息和过滤器解耦,而是使用复合过滤器。再次感谢“验证”我的想法:)
    猜你喜欢
    • 2020-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多