Language agnostic 在用于规则处理的API中包含可变状态

Language agnostic 在用于规则处理的API中包含可变状态,language-agnostic,architecture,concurrency,immutability,api-design,Language Agnostic,Architecture,Concurrency,Immutability,Api Design,我有一个RuleTree数据结构,它表示用于处理传入数据项的规则树 规则树当前是一个不可变的数据结构,包含任意数量的(可能是嵌套的)规则 有多个线程将同时将同一规则树应用于不同的输入数据项 规则树应用于一个或多个阶段中的输入数据。由调用代码决定应用哪个阶段 典型的控制流程如下所示: ruleTree.applyStage1(data); .. // other stuff happens .. ruleTree.applyStage2(data); .. // other stuff hap

我有一个RuleTree数据结构,它表示用于处理传入数据项的规则树

  • 规则树当前是一个不可变的数据结构,包含任意数量的(可能是嵌套的)规则
  • 有多个线程将同时将同一规则树应用于不同的输入数据项
  • 规则树应用于一个或多个阶段中的输入数据。由调用代码决定应用哪个阶段
典型的控制流程如下所示:

ruleTree.applyStage1(data);
..
// other stuff happens
..
ruleTree.applyStage2(data);
..
// other stuff happens
..
ruleTree.applyStage3(data);
这目前效果很好。但是,我现在需要在规则树处理期间计算一些额外的状态信息(例如,计算树中特定规则的匹配数)。在我看来,我有几个选择:

  • 使规则树可变,并使其能够存储可稍后读取的状态信息。然而,这将使并发变得更加棘手,因为不同的线程需要不同的规则树副本
  • 将线程本地状态添加到规则树中-这样可以计算状态信息并将其存储在规则树中,但不同的线程不会相互践踏状态信息。但是,这意味着必须保证所有阶段都在同一线程上运行
  • 为状态信息提供一个单独的对象,该对象可以作为额外参数传递给规则树,
    ,例如ruletree.applyStage1(数据、状态)
    。这使规则树保持良好和不变,但使调用者使用它们更加复杂,因为调用代码现在必须单独设置和管理状态数据
哪种方法可能是最好的,为什么?

使用“状态信息的单独对象”方法,因为它不会受到您正在考虑的其他方法固有缺陷的影响。更重要的是,“分离对象”模型的主要缺陷,即它要求用户将状态传递给RuleTree的每个方法,可以很容易地处理

考虑RuleTree的代理。我将使用Ruby作为伪代码的可行近似:

class RuleTreeProxy

  def initialize(ruleTree)    # Constructor
    @ruleTree = RuleTree
    @state = RuleTreeState.new
  end

  def state
    return @state
  end        

  def applyStage1(data)
    @rule_tree.applyStage1(@state, data)
  end

  def applyStage2(data)
    @rule_tree.applyStage2(@state, data)
  end

  # etc.

end
@表示对象成员变量

任何需要使用RuleTree的人都会创建RuleTreeProxy并调用它:

proxy = RuleTreeProxy.new(ruleTree)
proxy.applyStage1(data)
proxy.applyStage2(data)
...
state对象包含用于检索有关RuleTree所做处理的有用信息的访问器:

matches = proxy.state.numberOfMatches

如果您要求不同的阶段可以在不同的线程中完成,那么请确保没有两个线程试图同时对RuleTreeProxy实例进行操作,或者向RuleTreeProxy添加适当的同步。

谢谢您的回答-我喜欢使用代理对象系统的想法@米凯拉-谢谢你提出这个有趣的问题!