写点什么

Spring Web 应用的最大瑕疵

  • 2013-11-08
  • 本文字数:2065 字

    阅读完需:约 7 分钟

众所周知, 现在的 Spring 框架已经成为构建企业级 Java 应用事实上的标准了,众多的企业项目都构建在 Spring 项目及其子项目之上,特别是 Java Web 项目,很多都使用了 Spring 并且遵循着 Web、Service、Dao 这样的分层原则,下层向上层提供服务;不过 Petri Kainulainen 在其博客中却指出了众多 Spring Web 应用的最大瑕疵,请继续阅读看看文中所提到的问题是否也出现在你的项目当中。

使用 Spring 框架构建应用的开发者很乐于谈论依赖注入的好处。但遗憾的是,他们很多人并没有在其应用中很好地利用其优势,如单一职责原则关注分离原则。如果仔细看看基于 Spring 的 Web 应用,你会发现很多都是使用如下这些常见且错误的设计原则来实现的:

  • 领域模型对象只是用来存储应用的数据。换句话说,领域模型使用了贫血模型这种反模式。
  • 业务逻辑位于服务层中,管理域对象的数据。
  • 在服务层中,应用的每个实体对应一个服务类。

可问题是:如果这种做法很普遍,那为什么说是不对的呢?下面来阐述一下。

旧习难改

Spring Web 应用之所以看起来是这个样子原因在于这是人们长久以来的做法,旧习难改,特别是在高级开发者或是软件架构师强制开发人员这样做的时候。问题在于这些人非常擅于捍卫自己的观点。他们喜欢的一个论调就是应用应该遵循关注分离原则,因为它被划分成了几个层次,每个层次都有自己具体的职责。

一个典型的 Spring Web 应用会有如下几个层次:

  • Web 层:负责处理用户的输入并向用户返回正确的响应。Web 层只会与服务层通信。
  • 服务层:作为事务边界。它还负责授权并包含了应用的业务逻辑。服务层管理着领域对象模型并且与其他服务及存储层通信。
  • 存储 / 数据访问层:负责与所用的数据存储进行通信。

关注分离原则的定义是这样的:关注分离(Soc)是一种将计算机程序划分到不同部分的一种设计原则,这样每一部分都会有单独的关注点。虽然一个典型的 Spring Web 应用也在一定程度上遵循了这个原则,不过实际情况却是应用拥有一个整体的服务层,它包含了太多的职责了。更具体一些,服务层主要有两个问题:

首先,应用的业务逻辑来自于服务层。

这是个问题,因为业务逻辑散落在服务层。如果需要查看某个业务规则是如何实现的,我们需要先找到它才行,这可不是那么轻松的事情。此外,如果有多个服务类都需要相同的业务规则,那么开发人员很可能会将这个业务规则从一个服务复制到另一个服务中,这会导致维护的梦魇。

其次,每个领域模型类在服务层中都有一个服务类。

这违背了单一职责原则:单一职责原则表明每个类都应该只有一个职责,这个职责应该完全被这个类所封装。它的所有服务都应该与这个职责保持一致。

服务类存在大量的依赖和大量的循环依赖。一个典型的 Spring Web 应用的服务层没有包含只拥有一个职责的松耦合的服务,它更像是一个紧耦合的大量服务的集合。这使得它很难理解、维护与重用。看起来有点苛刻,不过服务层经常是 Spring Web 应用最容易出现问题的一环。幸好对我们来说还存在着希望。

推翻

目前的状况并不好,不过也不是完全没有希望的。下面我们来看看如何打破旧有的习惯。

首先,我们需要将应用的业务逻辑从服务层移动到领域模型类中。

为何要这么做呢,看看下面这个例子:

假设我是个服务类,你是个领域模型对象。如果我告诉你从房顶跳下来,那么你是否会拒绝呢?

将服务层的业务逻辑移动到领域模型类中有如下 3 个好处:

  • 根据合理的方式划分代码的职责。服务层会负责应用的逻辑,而领域模型类则负责业务逻辑。
  • 应用的业务逻辑只会位于一处。如果需要验证特定的业务规则是如何实现的,我们总是知道该去哪里寻找。
  • 服务层的源代码将会变得更加整洁,再不会包含任何复制粘贴的代码了。

其次,我们需要将特定于实体的服务划分为更小的服务,每个服务只有一个目标。

比如说,如果应用有一个服务类,它为与用户帐户相关的人与操作提供了 CRUD 操作,那么我们就应该将其划分到两个单独的服务类中:

  • 第 1 个服务提供人的 CRUD 操作。
  • 第 2 个服务提供与用户帐户相关的操作。

这么做有如下 3 个好处:

  • 每个服务类都有一套合理的职责。
  • 每个服务类的依赖会更少,这意味着他们不再是紧耦合的庞然大物了。他们是更加小巧且松耦合的组件。
  • 服务类更易于理解、维护与重用。

这两个简单的步骤可以帮助我们清理应用的架构,提升开发者的生产力和幸福度。现在,我们想知道如果所有这些都是必要的,那么该何时解决这些问题呢?

有时生命是黑白的

我经常听到有人说我们不应该过多的关注于“架构”,因为我们的应用很小并且很简单。虽然这个论调有一定的正确性,不过我们必须要记住一开始很小的项目最后会变得很大。如果不考虑这种情况,那么一旦发生状况,我们就会陷入到巨大的麻烦当中。在未知的水域中航行可不是个好做法,但我们必须要知道,泰坦尼克号在撞到冰山沉没时是在熟悉的航线中航行的。这种事情也会发生在我们的应用中。当事情变得无法控制时,我们必须要有勇气说不。

如果你打算改变,那么我推荐你阅读一下Olivier Gierke 所写的“ Whoops! Where did my architecture ”(或是观看他在 SpringOne2GX 上关于这个项目的演讲)。但请注意,习惯的力量还是很强大的。

2013-11-08 11:329786
用户头像

发布了 88 篇内容, 共 269.6 次阅读, 收获喜欢 9 次。

关注

评论

发布
暂无评论
发现更多内容

GitHub星标4000!清华大牛的CTF竞赛入门指南,真的太香了!

我再BUG界嘎嘎乱杀

黑客 网络安全 信息安全 PWN CTF竞赛

充分发挥数字经济赋能效应,Flexus X实例协助企业高效转型

轶天下事

掀起性能巨浪:华为云Flexus X实例定义业务负载多面手

YG科技

聚焦中小企业上云用云需求,华为云Flexus X实例带来双倍性能、跃级体验

YG科技

手把手教你如何参与开源,详细实用~

XIAOJUSURVEY

GitHub 开源 PR 贡献者 Issue

SpringBoot项目中HTTP请求体只能读一次?试试这方案

小明同学的学长

springboot java

双倍性能、跃级体验!华为云Flexus X实例助力企业轻松上云

轶天下事

顺应数字化浪潮,华为云Flexus X实例助力中小企业破局崛起

轶天下事

性能易用二合一!华为云Flexus X实例加快中小企数字转型

YG科技

华为云Flexus X实例,以创新技术打造中小企业高质量发展新引擎

轶天下事

重塑云服务,华为云Flexus X实例破解云服务传统难题

YG科技

华为云Flexus X实例性能出众,降本显著,促进中小企业高质量发展

YG科技

华为云Flexus X实例全方位为中小企业护航,加速迈进“专精特新”

YG科技

生成式 AI 时代数据库与大模型的融合探索

编程猫

数字化转型正当时!华为云Flexus X实例助力中小企业高效便捷上云

轶天下事

华为云Flexus X实例创新柔性算力技术,助力企业提质、增效、降本

轶天下事

无缝升级云服务,华为云Flexus X实例带来零门槛极致体验

YG科技

直击中小企业痛点!Flexus X实例让中小企业也可以上好云、用好云

YG科技

数字转型得力伙伴:华为云Flexus X实例打造云计算应用新标杆

轶天下事

自动化业务状态码设计

三七互娱后端技术团队

效率 自动化 状态码

中小企业数字化转型难点凸显,华为云Flexus X实例革新上云体验

YG科技

顺应数字化趋势!Flexus X实例助力中小企业开启数字转型“必修课”

轶天下事

华为云Flexus X实例:最高6倍算力提升,满足中小企业多元需求

轶天下事

华为云Flexus X实例创新柔性算力!直击中小企业数字化转型痛点

轶天下事

华为云Flexus X实例全方位创新,开拓企业数字化发展新边界

YG科技

华为云Flexus X实例依托生态优势,破解中小企业数字化转型困局

YG科技

激发云服务效能,华为云Flexus X实例助力破除中小企上云痛点

YG科技

数字化转型正当时!华为云Flexus X实例助力中小企业高效便捷上云

轶天下事

聚焦中小企业实际需求,华为云Flexus X实例推动中小企业数字化转型愿转敢转

轶天下事

低代码实践:题型物料化设计(四)

XIAOJUSURVEY

低代码 schema 源码解读 配置化 设置器

Spring Web应用的最大瑕疵_架构_张龙_InfoQ精选文章