为什么使用框架的功能被认为是错误的
Why is using the framework's features considered wrong
我作为初级开发人员加入了一家公司,我被分配去维护和修复各种应用程序。
在我必须在团队中工作的每个项目中,我总是听到抱怨我的代码过于“框架耦合”并且我应该使用普通 Java 而不是使用 Spring 框架的功能(哎呀,我什至因为使用 @Autowired 而不是构造函数注入而大喊大叫)
我对这件事真的很沮丧,我想知道我是不是错了。框架的特性不是程序员使用该框架的主要原因吗?
通常,这种思维方式背后的原因是,在美好的一天以最少的工作量将您今天使用的框架换成其他框架会更容易。你可能会争辩说这不是很常见的事情或者你经常这样做,但是,即使理由不能说服你,通常最好的做法是尽量将你的代码与底层框架分离,以实现多种原因(除了刚才提到的一个,您还可以更轻松地进行单元测试)。
关于 @Autowired
主题,构造函数注入通常是首选,主要原因有两个:
- 您清楚地定义了 class 正常工作的依赖关系;
- 对它进行单元测试会更容易,因为如果您可以通过构造函数“注入”它们,则模拟其依赖关系会更容易。
请不要混淆两个不同的概念:“特定项目的条件标准”和“最佳实践”- 如果您是初级开发人员,您只需要接受条件标准,如果您是团队领导,则应该仔细评估“最佳实践”是否真的是最好的。 Spring 框架不仅是 DI 框架,它还提供了许多其他有用的功能(外部化配置、post-处理器、AOP、事务管理、转换器等 - 很多),如果你的团队决定不与 Spring 框架结合,这意味着他们缺少很多功能(或者需要从头开始实现这些功能),以便将来切换 DI 框架的假设可能性。
关于“字段注入”的邪恶,问题是“构造函数注入”的传道者完全忽略了一个事实,即在很多情况下它根本不起作用,例如考虑以下代码:
@Component
@RequiredArgsConstructor
class A {
private final B b;
}
@Component
@RequiredArgsConstructor
class B {
private final A a;
}
DI-framework 将无法 bootstrap 由于循环依赖的那些 bean,您可以通过以下选项使其工作:
- 不使用构造函数注入
- 在“某处”放置@Lazy 注释(或创建您自己的代理以避开Spring)。放在哪里?实际上在 类 中,因为行为取决于依赖解析的根:如果我们从
A
开始,那么 B
需要是 @Lazy,反之亦然。但问题是这个解决方法只是将问题从 bootstrap 阶段转移到运行时
- 接受你的代码有异味并重构它,但始终记住 bootstrap 阶段可能随时失败,即做 DI 框架应该做的工作
我作为初级开发人员加入了一家公司,我被分配去维护和修复各种应用程序。
在我必须在团队中工作的每个项目中,我总是听到抱怨我的代码过于“框架耦合”并且我应该使用普通 Java 而不是使用 Spring 框架的功能(哎呀,我什至因为使用 @Autowired 而不是构造函数注入而大喊大叫)
我对这件事真的很沮丧,我想知道我是不是错了。框架的特性不是程序员使用该框架的主要原因吗?
通常,这种思维方式背后的原因是,在美好的一天以最少的工作量将您今天使用的框架换成其他框架会更容易。你可能会争辩说这不是很常见的事情或者你经常这样做,但是,即使理由不能说服你,通常最好的做法是尽量将你的代码与底层框架分离,以实现多种原因(除了刚才提到的一个,您还可以更轻松地进行单元测试)。
关于 @Autowired
主题,构造函数注入通常是首选,主要原因有两个:
- 您清楚地定义了 class 正常工作的依赖关系;
- 对它进行单元测试会更容易,因为如果您可以通过构造函数“注入”它们,则模拟其依赖关系会更容易。
请不要混淆两个不同的概念:“特定项目的条件标准”和“最佳实践”- 如果您是初级开发人员,您只需要接受条件标准,如果您是团队领导,则应该仔细评估“最佳实践”是否真的是最好的。 Spring 框架不仅是 DI 框架,它还提供了许多其他有用的功能(外部化配置、post-处理器、AOP、事务管理、转换器等 - 很多),如果你的团队决定不与 Spring 框架结合,这意味着他们缺少很多功能(或者需要从头开始实现这些功能),以便将来切换 DI 框架的假设可能性。
关于“字段注入”的邪恶,问题是“构造函数注入”的传道者完全忽略了一个事实,即在很多情况下它根本不起作用,例如考虑以下代码:
@Component
@RequiredArgsConstructor
class A {
private final B b;
}
@Component
@RequiredArgsConstructor
class B {
private final A a;
}
DI-framework 将无法 bootstrap 由于循环依赖的那些 bean,您可以通过以下选项使其工作:
- 不使用构造函数注入
- 在“某处”放置@Lazy 注释(或创建您自己的代理以避开Spring)。放在哪里?实际上在 类 中,因为行为取决于依赖解析的根:如果我们从
A
开始,那么B
需要是 @Lazy,反之亦然。但问题是这个解决方法只是将问题从 bootstrap 阶段转移到运行时 - 接受你的代码有异味并重构它,但始终记住 bootstrap 阶段可能随时失败,即做 DI 框架应该做的工作