写点什么

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:329722
用户头像

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

关注

评论

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

NFT盲盒质押分红挖矿dapp系统开发源码搭建

开发微hkkf5566

如何将传统 Web 框架迁移部署到 Serverless 架构?

Serverless Devs

Python 架构 前端

专访|开源之夏最佳质量奖 Apache RocketMQ Committer 黄章衡

Apache RocketMQ

#开源 消息列队

应用瓴羊Quick B,可以有效地提升企业的数据化分析能力

对不起该用户已成仙‖

武汉大数据培训机构怎么样

小谷哥

功能强大的国产API管理神器 Eolink,亲测好用

海拥(haiyong.site)

开发工具 API API测试

多样化功能助力企业精准决策,瓴羊Quick BI数据看板解析

对不起该用户已成仙‖

文盘Rust -- r2d2 实现redis 连接池

TiDB 社区干货传送门

开发语言

为什么很多产品经理,做不了产品管理?

LigaAI

产品经理 敏捷开发 产品管理 产品功能 12 月 PK 榜

java程序员培训好就业吗

小谷哥

CorelDRAW2023永久和谐版本下载安装教程

茶色酒

CorelDraw2023

前端培训学习就业前景怎么样?

小谷哥

RISC-V SIG 推出基于openEuler 的下游发行版 Eulaceura

openEuler

Linux 开源 操作系统 openEuler risc-v

什么是IT资产?如何保障IT资产安全?

行云管家

网络安全 数据安全 IT资产

linux高可用小知识点汇总-行云管家

行云管家

高可用 ha 双机热备

“零代码”的瓴羊Quick BI即席分析,业务人员也能轻松上手

夏日星河

想学习大数据怎么选择培训机构

小谷哥

TiDB Operator部署TiDB集群的监控与告警

TiDB 社区干货传送门

监控 实践案例 集群管理 管理与运维 扩/缩容

跟我学Python图像处理丨带你入门OpenGL

华为云开发者联盟

Python 人工智能 华为云 12 月 PK 榜

Web前端培训机构有哪些?

小谷哥

SpringBoot内置tomcat启动过程及原理

京东科技开发者

tomcat 后端 tomcat源码解读 编程‘ spring-boot

FL Studio正式推出全新21版首发新版DAW(数字音乐工作站)工具

茶色酒

FL STUDIO20.9 FL Studio 21 FL Studio21

RTS超低延时直播技术:保障大型赛事直播零时差互动

阿里云CloudImagine

云计算 阿里云 世界杯

cleanmymac2023免费绿色版下载安装教程

茶色酒

CleanMyMac2023

TiDB 走进东软集团,共建医疗数字化基石

TiDB 社区干货传送门

HMS Core 6.8.0版本发布公告

HarmonyOS SDK

HMS Core

LED电子显示屏加速在生活中的应用

Dylan

LED LED显示屏 led显示屏厂家

不足10人的创业团队,怎么在半个月内上线一个新产品?

LigaAI

创业 敏捷开发管理 创业公司 远程开发 12 月 PK 榜

纷繁复杂见真章,华为云产品需求管理利器CodeArts Req解读

华为云开发者联盟

云计算 需求管理 华为云 12 月 PK 榜

通过TiOperator部署 TiDB

TiDB 社区干货传送门

实践案例 集群管理 管理与运维 扩/缩容 6.x 实践

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