一、泥球定律:代码是怎么烂掉的
小陈的预感没错。进入第八个月,云间书店的代码库已经变成了一个"大泥球":
- 结算、库存、会员、支付、报表……逻辑全都缠在一起;
- 一个功能改一处,崩三个地方;
- 新人入职三个月,还没摸清代码全貌;
- 每次"小改动"都要全组心惊胆战。
老周带小陈看代码:
# 结算模块(第 872 行)——为什么这里会 import 库存模块?!
from inventory import check_stock
from members import get_member_level
from reports import gen_report # 报表也混进来了??
def checkout(cart, user):
# 结算逻辑里硬塞了会员积分、库存扣减、甚至报表生成……
check_stock(cart)
level = get_member_level(user)
points = level * 10
gen_report(cart, points)
return "ok"
"看出来了吗?结算模块不该知道库存怎么扣、积分怎么算、报表怎么生成。 但它全都知道——这就是耦合(Coupling)过高。模块之间纠缠不清,牵一发而动全身。"
"这就是 Big Ball of Mud(大泥球) 架构:没有边界、没有分层、所有东西互相依赖。 泥球不是一天形成的,是一年一年'顺手加功能'堆出来的。"
小陈:"那怎么办?推倒重写?"
老周摇头:"推倒重写是最大的陷阱——重写期间业务还在跑,你边写边补,最后写出第二个泥球。正确姿势是'演进式重构':把泥球一点一点切开。这一章教你怎么切。"
二、架构治理的第一原则:边界
"架构(Architecture)的本质是什么?"老周问,"很多人以为是'用微服务'、'用高并发'……都不对。架构的本质是划边界——决定什么该在一起,什么该分开。"
好架构的标志:
- 模块之间边界清晰(这个模块不该知道那个模块的内部)
- 改动局部化(改库存,不动结算)
- 依赖单向(上层依赖下层,不循环)
- 可测试(每个模块能独立测试)
坏架构的标志(泥球):
- 到处 import,循环依赖
- 改一处崩三处
- 没人能说清系统全貌
- "这个函数为什么在这?"——没人知道
"架构治理,就是一套'防止泥球继续变大的规矩'。"
三、分层架构:最简单有效的第一刀
"切开泥球的第一步:分层(Layering)。"老周画了个经典的三层架构:
┌─────────────────────┐
│ 表现层(界面/API) │ ← 接收请求,展示数据
├─────────────────────┤
│ 业务逻辑层(服务) │ ← 核心业务规则(打折/满减/积分)
├─────────────────────┤
│ 数据访问层(数据库) │ ← 只管读写数据库
└─────────────────────┘
依赖方向:从上往下,单向!
"铁律:上层可以调用下层,下层绝不能反向调用上层;同层之间也要松耦合。 表现层不知道数据库长什么样,数据层不知道页面长什么样。"
# 分层后的结算模块
# 表现层:只管收请求、返回结果
@app.route("/checkout")
def checkout_api(cart, user_id):
result = checkout_service.checkout(cart, user_id) # 调业务层
return jsonify(result)
# 业务层:只管业务规则,不知道 HTTP、不知道数据库
class CheckoutService:
def checkout(self, cart, user_id):
total = self.calc_total(cart) # 业务规则
if not self.inventory.check(cart): # 通过接口依赖,不直接碰库存表
raise OutOfStock()
return total
# 数据层:只管读写数据库
class InventoryRepo:
def query(self, book_id):
return db.fetchone("SELECT stock FROM books WHERE id=?", book_id)
"分层是最古老也最实用的架构模式。对云间书店这种体量,三层就够了,别一上来就上微服务。"
四、领域驱动设计(DDD):按"业务"划边界,不是按"技术"划
"分层是按技术切(界面/业务/数据)。但还有另一种切法:按业务领域切。"老周说,"这就引出 DDD(Domain-Driven Design,领域驱动设计)。"
"DDD 的核心思想:软件的边界,应该跟业务的边界对齐。 书店的业务天然分成几个'域':"
云间书店的领域划分:
├── 订单域(下单、结算、退款)
├── 库存域(入库、出库、盘点)
├── 会员域(等级、积分、优惠券)
├── 支付域(收款、对账、退款)
└── 报表域(统计、导出)
每个领域内部自成一体:
- 有自己的模型(订单、库存快照、会员等级……)
- 有自己的数据(不随便读别人域的表!)
- 通过明确的"接口"与其他域通信(领域服务/事件)
"关键概念:限界上下文(Bounded Context)——'会员'这个词,在会员域和订单域里含义不同(会员域管等级积分,订单域只关心'这个用户有没有会员折扣')。每个域在自己的边界内定义自己的模型,别互相渗透。"
"DDD 的实战价值:当业务很复杂时,代码的边界跟着业务走,业务专家和程序员用同一套语言沟通。 但对简单业务别过度设计——DDD 是为复杂业务准备的武器。"
五、微服务:不是银弹,是"分布式泥球"
"媒体天天吹微服务,但我要给你泼冷水。"老周说,"微服务(Microservices)就是把大泥球切成很多个小泥球,再用网络连起来。 它解决'大团队并行开发'和'独立扩缩容'的问题,但引入了一大堆新问题:"
微服务的代价:
- 分布式事务(跨服务扣款,怎么保证原子性?)
- 服务间调用失败(网络会断,怎么重试/降级?)
- 调试困难(一个请求跨 5 个服务,日志怎么串起来?)
- 运维复杂度爆炸(部署、监控、版本兼容……)
所以行业共识:
- 团队 < 15 人:别碰微服务,模块化单体(Modular Monolith)更合适
- 单体 → 微服务,应该是"业务自然长成这样",不是为了赶时髦
"云间书店现在这个规模,老老实实把'模块化单体'做好——代码按领域分包,边界清晰,但还是一个应用一起部署。等哪天某个域(比如支付)流量爆炸、需要单独扩容,再把它拆出去。"
六、架构治理机制:怎么防止泥球复活
"架构不光是设计,更是治理——没有机制,过两个月又糊回去。"老周列出四个机制:
6.1 架构评审:大改动先过审
架构评审规则:
- 涉及跨模块的重大改动 → 提前拉架构评审会
- 评审看什么:边界是否清晰?依赖方向对不对?有没有引入泥球?
- 结论要记录(ADR),防止同样的问题吵第二次
6.2 依赖规则检查:让机器守边界
"人的评审会漏,让机器盯!用工具强制依赖方向:"
# 依赖检查工具(如 Python 的 import-linter)
# 规则:reports 模块禁止 import models.inventory 内部的类
# 违反规则 → CI 红灯,合并被拦
"把架构规则写进 CI,让机器强制执行——这是架构治理最硬的一招。"
6.3 演进式架构:小步重构,不搞革命
"切泥球不搞'周末大重构',要小步演进:"
演进式重构步骤:
1. 找最痛的一小块(如:结算模块里 import 报表那行)
2. 用"绞杀者模式":新代码走新路径,旧代码暂时保留
3. 新路径稳定后,删掉旧代码
4. 每次改动都跑测试(第四章的测试兜底)
5. 一次只切一小块,两周内可完成,风险可控
"就像给老房子改造:一堵墙一堵墙地改,改完一堵再改下一堵,房子一直在住。 千万别'推倒重建'——那叫拆迁,不叫改造。"
6.4 架构决策记录(ADR):为什么这么定
"最后,每个重大架构决策,写一份 ADR(Architecture Decision Record):"
ADR-007:结算模块采用分层架构
背景:结算逻辑混入库存/积分/报表,耦合过高,改动频繁崩
决策:按表现层/业务层/数据层分层,业务层通过接口依赖数据层
后果:改动局部化,可测试性提升;代价是需要逐步迁移(约 6 周)
替代方案:直接上微服务 —— 被否,团队 8 人,复杂度不匹配
"ADR 是团队的'为什么档案'——半年后新人问'为什么这里这么设计',不用猜,看文档。"
七、章末:老周的第十一层总结
第十一层:架构与治理
├── 边界 → 架构的本质是划边界(什么该在一起,什么该分开)
├── 分层架构 → 表现层/业务层/数据层,依赖单向
├── 领域驱动(DDD) → 边界跟着业务走,限界上下文
├── 微服务 → 不是银弹,小团队用模块化单体
└── 治理机制 → 架构评审 / 依赖检查进CI / 演进式重构 / ADR
"小陈,这一层讲完,软件工程管理的'人的部分'就基本齐了:需求、协作、质量、流程、风险、架构……每一层都是在回答同一个问题:怎么让一群人长期、稳定、高质量地做软件。"
老周正要收白板,手机响了。他看了一眼,表情变得微妙起来。
"师傅,怎么了?"
"王姐说,她要给技术部买一个'AI 编程助手',让大家都用上。"老周放下手机,"她还说,隔壁公司已经在用 AI 自动写代码、自动修 bug 了,我们再不跟上就落后了。"
小陈眼睛发光:"AI 写代码!师傅,这会不会把咱们都替代了?"
老周笑了:"问得好。这正是我们要讲的最后一层——AI 时代的软件工程。走吧,这一章,我们聊聊:当 AI 加入团队,管理会发生什么变化。"