一、架构思维启蒙:什么是软件架构?为什么需要分层?
说实话,我带了这么多年团队,面试过几百个工程师,发现一个很有意思的现象:很多人写了三五年代码,却从来没认真想过一个问题——软件架构到底是什么?
你可能会说,架构不就是画几个方框、连几条线吗?嗯,我以前也这么想。直到有一次,我接手一个遗留系统,代码像一团乱麻,改一个bug能冒出三个新bug。那天晚上我盯着屏幕,突然意识到:没有架构的系统,就像没有骨架的人——站都站不起来。
1.1 从现实世界理解架构
我们先跳出代码,看看现实世界是怎么处理复杂问题的。
公司组织架构就是个好例子。一家公司有CEO、有各部门总监、有经理、有普通员工。CEO不需要去管前台今天用什么语气接电话,前台也不需要操心公司下季度的战略方向。为什么?因为职责被分层了。
再想想图书馆。成千上万本书,怎么找?按类别分:文学、科学、历史……每个类别下再细分。你要找一本《Java编程思想》,不会跑到历史区去翻,对吧?
软件架构也是一样的道理。分层,就是把复杂问题拆成多个相对独立的层次,每层只关心自己的事。
核心观点:架构的本质是组织复杂性。分层是组织复杂性的最有效手段之一。
1.2 什么是软件架构?
我比较认同这个定义:软件架构是系统的高层结构,包括组件、组件之间的关系,以及指导设计和演化的原则。
说白了,架构就是回答这几个问题:
- 系统有哪些部分?(组件划分)
- 各部分怎么通信?(交互方式)
- 各部分怎么部署?(物理分布)
- 系统怎么演化?(扩展性)
我记得有一次给客户做技术评审,对方CTO问我:"我们团队20个人,写一个电商系统,你觉得架构上最需要注意什么?"
我说:"你先告诉我,你们打算怎么分层。"
他愣了一下。其实很多人都会忽略这个问题——分层是架构的起点。
1.3 为什么需要分层?
我总结了几点,都是我在项目中踩过的坑:
| 原因 | 说明 | 反面案例(我踩过的坑) |
|---|---|---|
| 关注点分离 | 每层只做一件事,降低认知负担 | 一个类里既写SQL又写HTML,改起来想哭 |
| 可替换性 | 换数据库、换UI框架,不影响其他层 | 业务逻辑和ORM耦合,换数据库重写一半代码 |
| 可测试性 | 每层可以独立测试 | 测试业务逻辑必须先启动数据库,跑一次5分钟 |
| 团队协作 | 不同团队负责不同层,并行开发 | 前后端耦合,前端等后端接口,后端等前端页面 |
| 演化能力 | 可以逐步升级某层,不用推倒重来 | 没有分层,加个缓存要改所有代码 |
我曾经踩过的坑:刚带团队时,我鼓励"快速实现",结果三个月后,一个简单的需求变更要改7个文件。那次之后,我强制要求所有新项目必须先画分层图,再写一行代码。
1.4 经典分层架构:三层架构
说到分层,最经典的就是三层架构:
- 表现层(UI):用户看到的界面,负责交互
- 业务逻辑层(BLL):核心业务规则,负责处理
- 数据访问层(DAL):和数据库打交道,负责存取
你可能会问:就三层?够用吗?
其实三层是逻辑分层,实际项目中可以继续细分。比如业务层可以拆成应用服务层和领域层,数据层可以拆成仓储层和基础设施层。但核心思想不变:上层依赖下层,下层不依赖上层。
下面这张图,是我每次培训必画的:
1.5 分层的核心原则
光知道分层还不够,得知道怎么分才合理。我总结了三条铁律:
- 单向依赖:上层可以调用下层,下层绝不能反向调用上层。违反这条,分层就形同虚设。
- 接口隔离:层与层之间通过接口通信,而不是直接依赖具体实现。这样换实现就像换插座一样简单。
- 封装变化:把容易变化的部分封装在层内部,对外暴露稳定的接口。数据库从MySQL换成PostgreSQL,业务层不应该感知到。
我的个人习惯:每次设计分层时,我会先问自己三个问题:
- 如果换数据库,要改哪些文件?
- 如果换前端框架,要改哪些文件?
- 如果业务规则变了,要改哪些文件?
答案越少,分层越合理。
1.6 分层不是银弹
说了这么多分层的好处,我也得泼点冷水。分层不是万能的。
我见过一些团队,为了分层而分层,搞出七八层,每层就做一点点事。结果代码跳来跳去,一个简单的查询要经过五六个层,性能差不说,调试起来也让人抓狂。
什么时候不适合过度分层?
- 原型验证阶段:快速验证想法,分层反而拖慢速度
- 小型工具类项目:几百行代码的项目,分层是过度设计
- 性能敏感场景:每层都有开销,极端性能场景要适当扁平化
但话说回来,对于大多数企业级应用,分层是必须的。它带来的维护性、可测试性、团队协作效率,远远超过那点性能损耗。
1.7 本章小结
我们来回顾一下核心要点:
| 概念 | 一句话总结 |
|---|---|
| 软件架构 | 系统的高层结构,包括组件、关系、原则 |
| 分层思想 | 把复杂系统按职责拆成多个独立层次 |
| 三层架构 | 表现层、业务逻辑层、数据访问层 |
| 核心原则 | 单向依赖、接口隔离、封装变化 |
| 适用场景 | 企业级应用、长期维护项目、团队协作 |
记住一句话:架构不是画出来的,是长出来的。但好的架构思维,能让你从一开始就走在正确的方向上。