对象依赖生命周期

bp object-dependency-lifecycle

目前 Keystone 中依赖注入 (DI) 的实现方式实际上并没有真正使用“依赖注入”模式。本规范的重点是改进 Keystone 内部对象生命周期(包括依赖项)。

此规范基于 Kilo Summit 会议:会前阅读

问题描述

目标
  • Keystone 中的依赖注入模式应该是什么样的?

  • 我们如何处理可选依赖项?

  • 对象(控制器、管理器等)的生命周期是什么?

动机
  • 移除在 API 中未明确定义的属性直接添加到对象上的“魔法”

  • 可选依赖项目前没有以面向对象的方式实现;我们使用依赖项的存在作为一种功能标志

  • 更好的测试接口;特别是可选依赖项

  • DI 涉及动态构建对象图,其中可以使用某些接口的不同实现。我们实际上并没有这样做。

约束
  • 尽可能保持 API 向后兼容(驱动程序肯定如此,管理器和控制器在一定程度上如此)

  • Stevedore 兼容。我们可能希望使用 Stevedore 动态加载驱动程序,并且应该确保我们不会做任何使之更困难或不可能的事情。

什么是依赖注入?

维基百科对依赖注入有一个很好的描述。简而言之,该模式是一种将实现业务逻辑的代码与创建对象代码分离的方法。对象将期望将依赖项传递给其构造函数,而不是创建依赖项。这允许对象图(对象树)在对象本身不发生更改的情况下变化。

提议的变更

  1. 第一阶段 - 手动 DI

  • 这将使注入对象的对象生命周期为单例

  • 这也会保留一个全局注册表

  • 保持当前对象图的单例作用域

  • 使用 __init__ 作为可选 kwargs 实现可选依赖项

  • 这将保持对象的内部代码相同。我们仍然会使用 ‘if self.mydep’

  • 陷阱

  • 我们需要为下一步的事情添加一些东西。现在通过装饰器的“魔法”这只是发生的事情。

  1. 第二阶段 - 评估手动 DI

  • 是否需要一个框架?

  • 是否有足够的痛点来使用 DI 框架?

  • 是否需要 DI 框架的一些功能?

  • Keystone 可能不够复杂,不需要更多东西。

  • 存在一些现有的框架,如 inject 和 snake-guice

  • 我们需要作用域不同的对象吗?请求作用域,其他…

  1. 第三阶段 - 修复可选依赖项的模型

  • 我认为可选依赖项应该在现有对象的基础上使用组合来实现。使用 ‘if self.dep’ 的代码是一种不良气味。

  • 例如,keystone.assignment.core.Manager 中的可选 thingee_api 依赖项可以使用装饰器模式包装后端来实现。

  • 其他可选依赖项可能需要以不同的方式处理

备选方案

  • 我们可能会全力以赴使用一个功能过于复杂的框架。

  • 我们可以什么都不做,继续扩展“魔法”。

安全影响

无。本规范是关于代码结构的内部修改。

通知影响

无。本规范是关于代码结构的内部修改。

其他最终用户影响

无。本规范是关于代码结构的内部修改。

性能影响

无。本规范是关于代码结构的内部修改。

其他部署者影响

无。本规范是关于代码结构的内部修改。

开发人员影响

这改变了管理器对象的构建方式。

实现

负责人

主要负责人

dstanek

工作项

  • 更新对象以期望将依赖项传递给构造函数

  • Update documentation

依赖项

无。

文档影响

需要更新开发人员文档以删除/更新显示 keystone.common.dependency 用法的代码示例。这主要是在 doc/source/extension_development.rst 中。

参考资料

相关项目