动态路由器和控制消息

时间:2011-02-26 12:09:34

标签: php events exception design-patterns

我正在研究的系统使用的是动态路由器+ dep.injection模式,特别是:

  1. 路由器对象使用config来实例化模块对象。模块是独立的,可能很多。
  2. 路由器对象的一个​​实例被依赖注入到模块构造函数中,并用作API参考/指针(可能与问题无关,但为了清楚起见,这里)
  3. 模块使用API​​添加将输入模式链接到特定模块方法的规则
  4. 路由器接收输入,根据规则集检查输入并调用匹配
  5. 的模块方法
  6. 结果由路由器收集并传递给输出处理器
  7. 模块构造函数:

    class module {
        public function __construct(&$router) {
            $router->addRoute('some-input-pattern', array($this, 'someMethod'));
        }
    
        public function someMethod() {
             return 'some arbitrary result';
        }
    }
    

    无论看起来多么简单,有些情况下模块和路由器需要就与任意返回值无关的内容进行通信。

    例如,有时模块必须触发一个必须由模块本身处理的事件或异常。它可以源自任何模块方法,并且必须由特定方法处理。 (在每种方法中都有大量的try / catch块似乎不对,并且可以处理任何异常的唯一“入口点”在模块之外,在路由器中。模块抛出,模块句柄,但只有路由器可以实际上是抓住了。听起来不错。)

    class module {
        public function __construct(&$router) {
            ...
            $router->addExceptionHandler('dbTableNotFoundException', 
                                         array($this, 'installSchema'));
        }
     }
    

    在其他情况下,路由器本身需要处理事件。例如,模块可以请求路由器继续进行,就像它已经接收到特殊类型的输入一样,忽略了真实的输入。然后路由器必须根据规则集重新检查它,并调用适当的方法。

       public function someMethod(){
             ...
             throw routerRestartException('special-input');
       }
    

    在其他情况下,除了传递给输出之外,事件可能不需要处理,例如仅限于人眼的错误。

       public function someMethod(){
             ...
             throw humanEyesException("You can't do that!");
       }
    

    这实际上让我想到了两个通信方面,因为路由器和模块交换任意返回数据特殊控制消息。

    到目前为止,系统控制消息方面是由抛出异常的模块和路由器捕获实现的。这要求模块注册两种类型的方法 - 一种用于处理输入,另一种用于处理异常,这可能很臭。

    一些例外情况似乎会影响流量控制,我认为使用异常也不是一个好习惯。

    问题在于,路由器对象及其相关模块之间是否存在构建这种双向通信的最佳实践或模式?

    修改

    一路思考:通过从路由器中分离模块内异常处理来改善情况的一种方法是使用Observer模式进行自定义异常:

    public function __construct(&$router){
        ...
        dbTableNotFoundException::addObserver(array($this, 'installSchema'));
    }
    

1 个答案:

答案 0 :(得分:0)

为了让模块对其他模块和API事件做出反应,我会使用Observer模式。您的API可以提供多个可观察的主题(这些主题可以是API可以为每个可观察的主题提供/注册和通知程序)