1、架构分层初探:为什么需要分层?分层架构的演进历史(单体→分层→微服务)

说实话,我做了十几年软件架构,被问得最多的问题就是:「架构到底怎么分?分几层才合适?」

每次听到这个问题,我都会想起自己刚入行时踩过的坑。那时候写代码,一个 .php 文件搞定所有逻辑——数据库查询、HTML 渲染、业务判断全揉在一起。嗯,现在想想,那叫一个酸爽。

今天咱们就来聊聊,为什么非得分层不可?以及这个分层思想是怎么一步步演变过来的。

1.1 不分层的痛:我亲身经历过的「屎山」

先讲个真实故事。2012年我接手过一个电商后台系统,代码量大概 15 万行。你猜怎么着?所有逻辑都在一个模块里。

  • 用户点击「下单」,同一个函数里既查数据库、又算价格、还发邮件通知
  • 改一个支付逻辑,结果把商品展示页搞崩了
  • 新同事入职第一周,光看懂代码流程就花了三天

说白了,这就是典型的「大泥球」架构。所有组件互相依赖,牵一发而动全身。

核心痛点总结:
  • 耦合度高:改一处,崩一片
  • 可测试性差:没法单独测试某个逻辑
  • 维护成本爆炸:新人上手慢,老人改代码提心吊胆
  • 扩展性为零:想加个新功能,得动整个系统

为什么会这样?因为没有「边界」。代码之间没有清晰的职责划分,就像一群人挤在一个房间里干活,谁碰了谁都不知道。

3.2 分层架构的诞生:给代码划地盘

为了解决这个问题,前辈们想出了一个办法——分层

分层架构的核心思想就一句话:各司其职,单向依赖

我记得最早接触的分层模型是经典的三层架构:

层次 职责 典型技术
表现层(UI) 用户交互、数据展示 HTML、JSP、Vue
业务逻辑层(BLL) 核心业务规则、流程编排 Java Service、C# 类库
数据访问层(DAL) 数据库读写、持久化 JDBC、MyBatis、EF

每一层只依赖它的下一层。表现层调业务层,业务层调数据层。反过来不行——数据层绝对不能直接调用表现层的方法。

我个人习惯:在分层时,我会额外加一个「公共层」或「基础设施层」,放日志、配置、工具类这些横切关注点。这样业务层就不用操心这些杂事了。

3.3 从单体到分层:一次质的飞跃

分层架构出现之前,大家写的是「单体应用」。一个 war 包部署到 Tomcat,所有代码都在里面。

分层之后,代码结构变成了这样:

project/
├── web/              # 表现层
│   └── UserController.java
├── service/          # 业务层
│   └── UserService.java
├── dao/              # 数据层
│   └── UserDao.java
└── common/           # 公共层
    └── LogUtil.java

你看,目录结构本身就说明了职责。新同事一看就知道:改页面去 web 目录,改业务逻辑去 service 目录。

我曾经在一个项目里,把三层架构用到了极致。每个层都定义了清晰的接口,层与层之间通过接口通信。结果呢?

  • 测试可以 mock 掉下层,单独测业务逻辑
  • 换数据库?只需要改 dao 层,业务层完全不动
  • 团队分工明确:前端写 web 层,后端写 service 层
注意:分层不是万能的。我见过很多团队把分层搞成了「形式主义」——目录分了,但代码还是互相乱调。比如在 dao 层里写业务判断,或者在表现层直接查数据库。这样分层等于没分。

3.4 从分层到微服务:当分层不够用了

分层架构解决了大泥球的问题,但它也有自己的天花板。

随着业务越来越复杂,一个应用可能包含几十个业务模块。所有模块还在同一个进程里运行,部署时还是得整个应用一起发布。

这时候,微服务架构出现了。

微服务说白了就是:把分层架构中的「层」拆成独立的「服务」

举个例子:

  • 原来一个电商系统,分表现层、订单层、支付层、库存层
  • 微服务化之后,订单服务、支付服务、库存服务各自独立部署

每个服务内部仍然保持分层结构,但服务之间通过 API 通信(REST 或 RPC)。

维度 单体分层 微服务
部署粒度 整个应用一起部署 每个服务独立部署
技术栈 统一技术栈 每个服务可选不同技术
团队规模 一个团队维护整个应用 每个服务由小团队负责
通信方式 进程内方法调用 网络调用(HTTP/RPC)

你想想看,微服务其实是对分层思想的延续——只不过把「逻辑层」变成了「物理服务」。每一层(服务)仍然各司其职,只不过现在它们跑在不同的进程里。

我的建议:不要为了微服务而微服务。如果你的团队只有 10 个人,业务也不复杂,老老实实用分层架构就够了。微服务带来的分布式事务、服务治理、网络延迟等问题,会让你痛不欲生。我曾经见过一个 5 人团队硬上微服务,结果半年后代码比原来还乱。

3.5 架构演进的本质:控制复杂度

回顾一下这条演进路线:

  1. 单体:所有代码在一起,简单但混乱
  2. 分层:按职责切分,清晰但耦合仍在
  3. 微服务:按业务切分,独立但复杂

你会发现,每一次演进都是在解决上一阶段的问题,但同时也引入了新的复杂度。

说白了,架构设计就是一场「权衡」的游戏。没有银弹,只有最适合当前阶段的方案。

避坑指南:我曾经在项目初期就设计了六层架构,结果开发效率极低——每加一个功能要改四个层。后来我学乖了:先分层,再优化,不要过度设计。分层架构的层数,3-4 层通常是最舒服的。

好了,这一章我们聊了为什么需要分层,以及分层架构的演进历史。下一章我会带你深入每一层,看看具体怎么设计接口、怎么处理层间依赖、怎么避免常见的分层陷阱。

记住一句话:分层的目的是控制复杂度,而不是增加复杂度