重构大型项目的DI

use*_*723 15 c# refactoring dependencies dependency-injection code-injection

我在一个大型平台项目上工作,支持大约10个使用我们代码的产品.

到目前为止,所有产品都使用了我们平台的全部功能:
- 从数据库中检索配置数据
- 远程文件系统访问
- 安全授权
- 基本逻辑(我们付费提供的东西)

对于新产品,我们被要求在没有平台带来的基础设施的情况下支持较小的功能子集.我们的架构很旧(从2005年左右开始编码),但相当稳固.

我们相信我们可以在我们现有的课程中使用DI来做到这一点,但估计这样做的时间从5到70周不等,取决于你与谁交谈.

有很多文章告诉你如何做DI,但我找不到任何告诉你如何以最有效的方式重构DI?是否有工具可以执行此操作而不必通过30.000行代码并且必须按CTRL + R来移除接口并将它们添加到构造函数中太多次?(如果有帮助,我们有resharper)如果没有,你发现什么是快速实现这一目标的理想工作流程?

use*_*723 4

感谢所有的答复。我们\xe2\x80\x99现在又快一年了,我想我基本上可以回答我自己的问题了。

\n\n

正如 lasseeskildsen 指出的那样,我们当然只转换了平台中要在新产品中重复使用的部分。由于这只是代码库的部分转换,因此我们采用 DIY 方法进行依赖注入。

\n\n

我们的重点是使这些部件可用而不带来不需要的依赖项,而不是对它们进行单元测试。这会影响您处理问题的方式。在这种情况下,没有真正的设计更改。

\n\n

所涉及的工作很平凡,因此问题是如何快速甚至自动完成这项工作。\n答案是它不能自动化,但使用一些键盘快捷键和重新锐化器可以非常快地完成。对我来说,这是最佳流程:

\n\n
    \n
  1. 我们致力于多种解决方案。我们创建了一个临时 \xe2\x80\x9cmaster\xe2\x80\x9d 解决方案,其中包含所有解决方案文件中的所有项目。尽管重构工具并不总是足够聪明,能够识别二进制和项目引用之间的差异,但这至少会让它们部分地跨多个解决方案工作。

  2. \n
  3. 创建需要删除的所有依赖项的列表。按功能对它们进行分组。在大多数情况下,我们能够同时处理多个相关的依赖关系。

  4. \n
  5. 您\xe2\x80\x99 将在许多文件中进行许多小的代码更改。此任务最好由一名开发人员完成,最多两名开发人员,以避免不断合并更改。

  6. \n
  7. 首先摆脱单例:\n将它们转换为脱离此模式后,提取一个接口(resharper -> 重构 -> 提取接口)\n删除单例访问器以获取构建错误列表。继续步骤 6。

  8. \n
  9. 要删除其他引用:\na。如上所述提取接口。\nb. 注释掉原来的实现。这将为您提供构建错误的列表。

  10. \n
  11. Resharper 现在成为一个很大的帮助:

    \n\n
      \n
    • Alt + Shift + pg 向下/向上快速导航损坏的引用。
    • \n
    • 如果多个引用共享一个公共基类,请导航到其构造函数并按 ctrl + r + s (\xe2\x80\x9cchange 方法签名\xe2\x80\x9d) 将新接口添加到构造函数中。Resharper 8 为您提供了通过调用 tree\xe2\x80\x9d 来解决 \xe2\x80\x9cresolve 的选项,这意味着您可以使继承类自动更改其签名。这是一个非常巧妙的功能(看起来是版本 8 中的新功能)。
    • \n
    • 在构造函数主体中将注入的接口分配给不存在的属性。按 alt + Enter 选择 \xe2\x80\x9ccreate property\xe2\x80\x9d,将其移动到需要的位置,然后 \xe2\x80\x99 就完成了。取消注释 5b 中的代码。
    • \n
  12. \n
  13. 测试!冲洗并重复。

  14. \n
\n\n

为了在原始解决方案中使用这些类而不需要进行重大代码更改,我们创建了重载构造函数,通过服务定位器检索它们的依赖项,正如 Brett Veenstra 提到的那样。这可能是一种反模式,但适用于这种情况。在所有代码都支持 DI 之前,\xe2\x80\x99 不会被删除。

\n\n

我们在大约 2-3 周内(1.5 人)将大约四分之一的代码转换为 DI。\n又过了一年,我们现在将所有代码转换为 DI。当焦点转移到单元可测试性时,情况就不同了。我认为上面的一般步骤仍然有效,但这需要一些实际的设计更改来强制执行 SOC。

\n