4

多年来,我一直在编写软件,并且一直试图创建富有表现力、清晰可读、可维护、健壮的代码。最近,我加入了一个使用 Spring 托管对象开发 Web 应用程序的团队。但我对这项技术感到非常不舒服。对我来说,感觉就像所有封装和信息隐藏原则,几十年软件工程的成果,都被抛弃了。我清楚地看到使用控制反转容器的优点,将系统依赖项从程序代码移到配置文件中。但是现在,我看到 Spring 的使用方式,我觉得,只是增加了一堆不必要的复杂性,而没有产生任何好处。

使用 Spring 创建 webapp 支持 bean,对象不再清晰地组织在模块中,并且不再具有最小的可见性。相反,现在有一个单一的、全局的 bean 名称空间。正因为如此,对象往往会得到像“pendingOrderCustomerName”这样糟糕的名称,更糟糕的是,这些名称甚至无法清楚地标识一个定义良好的实体,因为 bean 定义可以来自各种定义源,从公开指定的位置收集: Spring beans 不是简单地定义为包中的类,而是从 xml 文件组装而成,具有自由覆盖的可能性和松散定义的关系。

例如,当我在普通 java 中拥有一个类型“Account”时,在包“my.webstore”中,我通常可以在一个地方了解该类型的属性、关系和能力,即“my/webstore/Account. java”文件。“帐户”的实例作为与帐户一起使用的对象中的引用存在,任何实例的状态都由该类精确定义。然而,使用 Spring bean,事情变得更加复杂:“Account”实例现在存在于全局名称下,在容器管理的范围内,具有从 xml 文件组装的状态,沿着基于命名模式的文件搜索路径找到...

过去,要了解对象的作用和行为方式,您只需阅读其程序源代码即可。今天,您需要对象的 java 源代码(可能很复杂,难以理解),而且您必须找到任何可能改变该对象的配置文件,这并不容易,因为您必须找出配置可能来自的所有方式你必须找出它们相互覆盖的顺序

也许这只是口味问题,但我也想知道为什么人们更喜欢冗长、笨拙的 xml 语法,例如:

  <bean id="p1" class="Point" scope="prototype">
    <property name="x">
      <value>20</value>
    </property>
    <property name="y">
      <value>80</value>
    </property>
  </bean>

对此:

  p1 = new Point(20,80);

这个例子可能看起来很夸张,但我告诉你我见过更糟的!

我无意批评 Spring 框架本身,它在许多情况下非常强大并且是一个极好的成分。我关心的是如何防止误用,如何保持可维护性,如何保证质量和稳定性,如何找到依赖关系,如何记录代码......你的经验是什么?

4

2 回答 2

2

如您所见,如果您没有正确理解面向对象设计的原则,就很容易误用 Spring。Spring IoC 容器(让我们暂时忘记其余的,因为在 Spring 保护伞下有大量的库)当您使用它时真的会发光:

  • 定义组件模型(例如控制器、服务、存储库及其依赖项)
  • 集中组件依赖查找(例如替换您的服务定位器、JNDI 查找或其他无状态组件检索策略)
  • 用技术方面(例如事务管理、缓存、访问控制等)装饰组件

Spring 或任何 IoC 容器将允许您拥有统一的组件模型,删除大量样板代码,并将横切关注点隔离到集中的方面。它还应该推动你实现一个由松散耦合的组件组成的系统,专注于实现业务逻辑,从长远来看,这将提高可读性、可测试性和可维护性。

Account当然,如果您开始将s 和Points 定义为 Spring 组件,您将不会获得任何东西(实际上会损失很多) 。这些仍应设计为实体或值对象。它们仍然应该是正确包的一部分,并且应该应用适当的可见性修饰符。如果您的应用程序没有利用 IoC 容器,它们仍应使用您将使用的策略进行实例化、操作和管理。

看起来你已经知道声音设计原则,所以我鼓励你相信你的直觉。如果一个类是可重用(通常是无状态)组件,则将其声明为 Spring 组件并将其注入适当的位置。如果您不确定,请将其保留为普通的非托管类并正常使用。您将看到声明组件的地方和不声明组件的地方。

我还鼓励您研究如何利用@Component<context:component-scan>声明来减少 XML 占用。

祝你好运。

于 2013-06-20T05:06:48.750 回答
0

Spring 的许多特性都被滥用了。我曾经和你一样思考,但最近当我了解更多 Spring 时,我开始喜欢它,尽管任何依赖注入框架都可以,如果我有选择的话,我可能更喜欢Guice而不是 Spring。

问题似乎是人们知道如何使用 Spring,但不知道为什么。尤其是不用的时候。当您有多个实现时,Spring bean 很有用。这就是依赖注入大放异彩的地方。在您的示例中,我当然希望 Point 没有任何其他实现,因此它再次被 Spring 误用。

对我来说,Guice 的动机促使我更多地了解依赖注入,它同样适用于 Spring。

也就是说,您可以查看Spring 的注释以了解如何将您的配置和代码保存在一个地方。

于 2013-06-05T08:01:05.663 回答