我正在被使用类似动态路由器+ dep.injection图案的系统,特别是:动态路由器和控制消息
- 路由器对象使用配置来实例化模块对象。模块是独立的,可能很多。
- 路由器对象的一个实例被依赖注入到模块构造函数中,并用作API引用/指针(可能与问题无关,但在这里为了清晰起见)
- 模块使用API添加链接规则输入模式以特定的模块的方法
- 路由器接收输入,检查它靠在规则集,并调用匹配
- 结果由路由器收集并传递到输出处理器
模块构造器该模块的方法:
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'));
}