2

У меня есть структура данных RuleTree, которая представляет дерево правил, которые используются для обработки входящих элементов данных.Включая изменяемое состояние в API для обработки правила

  • RuleTree в настоящее время является неизменной структурой данных, содержащей произвольное количество (возможно, вложенных) правил.
  • Существует несколько потоков, которые будут одновременно применять один и тот же RuleTree к различным элементам входных данных.
  • RuleTree применяется для ввода данных в один или несколько фаз. Для того, чтобы определить, какие этапы нужно применять, зависит от кода вызова.

Типичный поток управления будет что-то вроде:

ruleTree.applyStage1(data); 
.. 
// other stuff happens 
.. 
ruleTree.applyStage2(data); 
.. 
// other stuff happens 
.. 
ruleTree.applyStage3(data); 

Это в настоящее время работает нормально. Однако теперь у меня есть требование рассчитать некоторую дополнительную информацию о состоянии во время обработки RuleTree (например, подсчет количества совпадений для определенного правила в дереве). Насколько я понимаю, у меня есть несколько вариантов:

  • сделать RuleTree изменяемыми и позволяет ей сохранять информацию о состоянии, которое можно прочитать позже. Это сделает совпадение более сложным, так как различным потокам понадобятся разные копии RuleTrees.
  • Добавить поток-локальное состояние в RuleTrees - чтобы информация состояния могла быть вычислена и сохранена в RuleTree, но разные потоки не будут топтать информацию о состоянии друг друга. Однако это означает, что все фазы должны быть гарантированы для работы на одном и том же потоке.
  • Имейте отдельный объект для информации о состоянии, который может быть передан в качестве дополнительного параметра в ruletree, e.g. ruleTree.applyStage1(data, state). Это сохраняет правильность и неизменность RuleTrees, но делает их более сложными для вызывающего, поскольку вызывающий код теперь должен отдельно настраивать и управлять данными состояния.

Какой подход, вероятно, будет лучшим и почему?

ответ

2

Используйте подход «отдельный объект для информации о состоянии», поскольку он не страдает от недостатков, присущих другим подходам, которые вы рассматриваете. Более того, главный недостаток модели «отдельный объект», который требует, чтобы пользователь передавал состояние каждому методу 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) 
... 

состояние объекта содержит аксессоров получить полезную информацию об обработке, проводимой RuleTree:

matches = proxy.state.numberOfMatches 

Если вы требуют, чтобы различные фазы могли выполняться в разных потоках, либо либо убедитесь, что ни один из двух потоков не попытается работать в экземпляре RuleTreeProxy одновременно, либо добавьте соответствующую синхронизацию в RuleTreeProx у.

+0

спасибо за ответ - мне нравится идея использования прокси-объекта! – mikera

+0

@mikera - Спасибо за интересный вопрос! –