对象依赖生命周期¶
bp object-dependency-lifecycle
目前 Keystone 中依赖注入 (DI) 的实现方式实际上并没有真正使用“依赖注入”模式。本规范的重点是改进 Keystone 内部对象生命周期(包括依赖项)。
此规范基于 Kilo Summit 会议:会前阅读
问题描述¶
- 目标
Keystone 中的依赖注入模式应该是什么样的?
我们如何处理可选依赖项?
对象(控制器、管理器等)的生命周期是什么?
- 动机
移除在 API 中未明确定义的属性直接添加到对象上的“魔法”
可选依赖项目前没有以面向对象的方式实现;我们使用依赖项的存在作为一种功能标志
更好的测试接口;特别是可选依赖项
DI 涉及动态构建对象图,其中可以使用某些接口的不同实现。我们实际上并没有这样做。
- 约束
尽可能保持 API 向后兼容(驱动程序肯定如此,管理器和控制器在一定程度上如此)
与 Stevedore 兼容。我们可能希望使用 Stevedore 动态加载驱动程序,并且应该确保我们不会做任何使之更困难或不可能的事情。
什么是依赖注入?¶
维基百科对依赖注入有一个很好的描述。简而言之,该模式是一种将实现业务逻辑的代码与创建对象代码分离的方法。对象将期望将依赖项传递给其构造函数,而不是创建依赖项。这允许对象图(对象树)在对象本身不发生更改的情况下变化。
提议的变更¶
第一阶段 - 手动 DI
遍历并修复类,使其期望通过其 __init__ 传递依赖项
这将消除“魔法”并将依赖项作为对象实际定义的一部分(概念验证 http://paste.openstack.org/show/129171/)
在一个新的 uber factory 中构建对象图(概念验证 http://paste.openstack.org/show/129179/)
这将使注入对象的对象生命周期为单例
这也会保留一个全局注册表
保持当前对象图的单例作用域
使用 __init__ 作为可选 kwargs 实现可选依赖项
这将保持对象的内部代码相同。我们仍然会使用 ‘if self.mydep’
陷阱
我们需要为下一步的事情添加一些东西。现在通过装饰器的“魔法”这只是发生的事情。
第二阶段 - 评估手动 DI
是否需要一个框架?
是否有足够的痛点来使用 DI 框架?
是否需要 DI 框架的一些功能?
Keystone 可能不够复杂,不需要更多东西。
存在一些现有的框架,如 inject 和 snake-guice
我们需要作用域不同的对象吗?请求作用域,其他…
第三阶段 - 修复可选依赖项的模型
我认为可选依赖项应该在现有对象的基础上使用组合来实现。使用 ‘if self.dep’ 的代码是一种不良气味。
例如,keystone.assignment.core.Manager 中的可选 thingee_api 依赖项可以使用装饰器模式包装后端来实现。
其他可选依赖项可能需要以不同的方式处理
备选方案¶
我们可能会全力以赴使用一个功能过于复杂的框架。
我们可以什么都不做,继续扩展“魔法”。
安全影响¶
无。本规范是关于代码结构的内部修改。
通知影响¶
无。本规范是关于代码结构的内部修改。
其他最终用户影响¶
无。本规范是关于代码结构的内部修改。
性能影响¶
无。本规范是关于代码结构的内部修改。
其他部署者影响¶
无。本规范是关于代码结构的内部修改。
开发人员影响¶
这改变了管理器对象的构建方式。
实现¶
负责人¶
- 主要负责人
dstanek
工作项¶
更新对象以期望将依赖项传递给构造函数
Update documentation
依赖项¶
无。
文档影响¶
需要更新开发人员文档以删除/更新显示 keystone.common.dependency 用法的代码示例。这主要是在 doc/source/extension_development.rst 中。
参考资料¶
相关项目