在其应用程序中使用Spring Framework的开发人员很好地谈论了依赖注入的好处。 不幸的是,他们并不是很好地利用它的好处,例如单一负责的原则和在应用程序中关注点的分离 。 如果我们看一下任何基于Spring的Web应用程序,很可能会通过使用以下常见且同样错误的设计原则来实现该应用程序:
- 域模型对象仅用于存储应用程序的数据。 换句话说,领域模型遵循贫血领域模型反模式 。
- 业务逻辑位于服务层中,该服务层管理域对象的数据。
- 服务层对应用程序的每个实体都有一个服务类。
问题是:如果这是如此普遍,那怎么可能是错误的呢? 让我们找出答案。
旧习难改
Spring Web应用程序之所以这样看,是因为这是一成不变的方式,旧习惯很难消除,特别是如果它们是由高级开发人员或软件架构师实施的。 问题是这些人非常擅长捍卫自己的观点。 他们最喜欢的论点之一是,我们的应用程序遵循关注点分离原则,因为它已分为几层,每一层都有特定的职责。
典型的Spring Web应用程序具有以下几层:
- Web层负责处理用户的输入并将正确的响应返回给用户。 Web层仅与服务层通信。
- 充当事务边界的服务层 。 它还负责授权,并包含我们应用程序的业务逻辑。 服务层管理域模型对象,并与其他服务和存储库层进行通信。
- 存储库/数据访问层 ,负责与使用的数据存储进行通信。
关注点分离原则定义如下:
关注点分离(Soc)是一种用于将计算机程序分为不同部分的设计原理,这样每个部分都可以解决一个单独的关注点。 尽管确实有一个典型的Spring Web应用程序在一定程度上遵循了这一原理,但现实情况是该应用程序具有一个整体的服务层,它承担了太多的责任。 更具体地说,服务层有两个主要问题:
首先,从服务层找到应用程序的业务逻辑。
这是一个问题,因为业务逻辑分散在服务层周围。 如果我们需要检查特定业务规则的实施方式,则必须首先找到它。 这可能并不容易。 另外,如果多个服务类别中需要相同的业务规则,则很可能会将规则简单地从一个服务复制到另一个服务。 这导致了维护的噩梦。
其次,服务层在每个域模型类中都有一个服务类。
这违反了如下定义的单一责任原则:单一责任原则规定每个类都应具有单一责任,并且该责任应完全由该类封装。 它的所有服务都应严格地与这一责任保持一致。
服务类具有很多依赖关系和很多循环依赖关系 。 典型的Spring Web应用程序的服务层并不由松散耦合的服务组成,这些服务仅具有一种责任。 它更像是紧密耦合的整体服务网络。 这使得难以理解,维护和重用。 这听起来可能有点苛刻,但是服务层通常是Spring Web应用程序中最有问题的部分。 对我们来说幸运的是,所有希望都没有丢失。
挣脱
当前的情况很糟,但并非完全没有希望。 让我们找出如何摆脱旧习惯。
首先,我们必须将应用程序的业务逻辑从服务层移到域模型类。
如果考虑以下示例,应该使我们明白这一点的理由:
假设我是服务类,而您是域模型对象。 如果有人告诉您从屋顶上跳下来,您是否愿意对我的决定拥有否决权?
将业务逻辑从服务层移到域模型类将为我们带来三个好处:
- 我们代码的职责以逻辑方式划分。 服务层负责应用程序逻辑,而我们的域模型类负责业务逻辑。
- 我们的应用程序的业务逻辑可从一个地方找到。 如果我们需要验证特定业务规则的实施方式,那么我们总是知道在哪里寻找。
- 服务层的源代码更干净,不包含任何复制粘贴代码。
其次,我们必须将特定于实体的服务划分为仅用于单一目的的较小服务。
例如,如果我们的应用程序具有单个服务类,该服务类为人员和与用户帐户相关的操作提供CRUD操作,则应将其分为两个单独的服务类:
- 第一项服务为人员提供CRUD操作。
- 第二服务提供与用户帐户有关的操作。
这给了我们三大优势:
- 每个服务类都有一套逻辑职责。
- 每个服务类别的依存关系都较少,这意味着它们不再是紧密耦合的巨人。 它们是较小的且松散耦合的组件。
- 服务类更易于理解,维护和重用。
这两个简单的步骤将帮助我们清理应用程序的体系结构,并提高开发人员的工作效率和满意度。
现在,我们可能想知道这是否真的必要?如果需要,何时解决这些问题至关重要?
有时生活是黑白的
我经常听到一个论点,指出我们不应该过多关注“体系结构”,因为我们的应用程序既小又简单。 尽管这种说法有一定道理,但我们必须记住, 从小做起的项目可以成长为更大的项目 。
如果我们在发生这种情况时没有考虑到这一点,那么我们就被搞砸了。
在未知的水域中航行可能听起来是个坏主意,但我们必须记住,泰坦尼克号被沉没的冰山撞到时正沿着熟悉的路线航行。 现在我们的应用程序可能正在发生同样的事情。
当事情失控时,我们必须有勇气喊叫停止 。
PS:如果您准备服用红色药丸,建议您阅读“ 哎呀! Olivier Gierke的架构在哪里去了(或观看他关于同一主题的SpringOne2GX演示 )。 但是请注意,兔子洞比您想象的要深得多。
翻译自: https://www.javacodegeeks.com/2013/06/the-biggest-flaw-of-spring-web-applications.html