2-1-1-所有痛苦来自边界不清
2.1.1 所有痛苦来自边界不清
引言
软件开发中的大部分问题不是技术问题,而是边界问题。
- "这个功能应该在前端还是后端处理?"
- "这个逻辑属于用户模块还是订单模块?"
- "这个配置应该在代码里还是数据库里?"
当边界不清时:
- 代码职责混乱
- 修改一处影响多处
- 团队协作困难
- Bug 无处不在
清晰的边界是软件架构的基石。
边界的本质
边界定义了"关注点"
# 边界不清:所有逻辑混在一起
@app.route('/api/orders', methods=['POST'])
def create_order():
# HTTP 层逻辑
data = request.get_json()
# 验证逻辑
if 'items' not in data:
return {'error': 'Missing items'}, 400
# 业务逻辑
total = 0
for item in data['items']:
product = db.query(Product).get(item['id'])
total += product.price * item['qty']
# 数据持久化
order = Order(user_id=data['user_id'], total=total)
db.session.add(order)
db.session.commit()
# 外部服务调用
send_email(data['user_id'], 'Order created')
return {'order_id': order.id}, 201
问题:HTTP、验证、业务、数据库、外部服务全混在一起,边界模糊。
# 边界清晰:分层架构
# === HTTP 层(处理请求/响应)===
@app.route('/api/orders', methods=['POST'])
def create_order_endpoint():
data = request.get_json()
try:
order = order_service.create_order(data)
return {'order_id': order.id}, 201
except ValidationError as e:
return {'error': str(e)}, 400
# === 业务逻辑层(领域规则)===
class OrderService:
def create_order(self, data):
# 验证
validate_order_data(data)
# 业务逻辑
total = calculate_order_total(data['items'])
order = Order(user_id=data['user_id'], total=total)
# 持久化
order_repository.save(order)
# 副作用
notification_service.send_order_created(order)
return order
# === 数据访问层(数据库操作)===
class OrderRepository:
def save(self, order):
db.session.add(order)
db.session.commit()
return order
# === 外部服务层(第三方集成)===
class NotificationService:
def send_order_created(self, order):
send_email(order.user_id, 'Order created')
好处:每一层有清晰的职责,修改某一层不影响其他层。
常见的边界混乱
混乱1:前端/后端边界不清
// 前端代码
function submitOrder(items) {
// 错误:业务逻辑放在前端
let total = 0;
items.forEach(item => {
total += item.price * item.quantity;
// 折扣逻辑也在前端
if (user.isVIP) {
total *= 0.9;
}
});
// 直接发送计算好的总价
api.post('/orders', { items, total });
}
问题:
- 用户可以修改前端代码,改变 total
- 业务逻辑重复(前后端都要写)
- 前后端逻辑不一致时,出现 bug
// 正确:前端只负责收集数据和展示
function submitOrder(items) {
// 前端只发送原始数据
api.post('/orders', { items });
}
// 后端负责业务逻辑
@app.route('/orders', methods=['POST'])
def create_order():
data = request.get_json()
# 后端计算总价
total = calculate_total(data['items'], current_user)
# ...
混乱2:模块职责边界不清
# user.py
class User:
def __init__(self, id, name, email):
self.id = id
self.name = name
self.email = email
# 错误:订单逻辑混入用户模块
def create_order(self, items):
total = sum(item.price * item.qty for item in items)
order = Order(user_id=self.id, total=total)
db.save(order)
return order
# 错误:邮件发送逻辑也在用户模块
def send_welcome_email(self):
smtp.send(self.email, "Welcome", "...")
问题:
- User 类做太多事情
- 修改订单逻辑要改 User 类
- 违反单一职责原则
# 正确:清晰的模块边界
# user.py - 只负责用户相关
class User:
def __init__(self, id, name, email):
self.id = id
self.name = name
self.email = email
def is_vip(self):
return self.membership_level == 'vip'
# order.py - 只负责订单相关
class OrderService:
def create_order(self, user, items):
total = self._calculate_total(items, user)
order = Order(user_id=user.id, total=total)
self.order_repo.save(order)
return order
# notification.py - 只负责通知相关
class NotificationService:
def send_welcome_email(self, user):
smtp.send(user.email, "Welcome", "...")
混乱3:数据/逻辑边界不清
# 错误:逻辑和数据混在一起
orders_data = [
{'id': 1, 'user_id': 100, 'total': 99.9},
{'id': 2, 'user_id': 101, 'total': 150.0}
]
# 处理逻辑直接操作字典
for order_dict in orders_data:
if order_dict['total'] > 100:
order_dict['shipping'] = 'free' # 修改原始数据
else:
order_dict['shipping'] = 10
# 问题:逻辑分散,数据结构暴露
# 正确:用对象封装数据和逻辑
class Order:
def __init__(self, id, user_id, total):
self.id = id
self.user_id = user_id
self.total = total
def calculate_shipping(self):
"""业务逻辑封装在对象内"""
return 0 if self.total > 100 else 10
# 使用
orders = [
Order(1, 100, 99.9),
Order(2, 101, 150.0)
]
for order in orders:
shipping = order.calculate_shipping()
如何划分边界
原则1:按变化原因划分
不同的变化原因 = 不同的模块
# 订单相关的变化原因:
# - 订单业务规则变化(折扣、税费)
# - 订单数据模型变化
→ Order 模块
# 用户相关的变化原因:
# - 用户权限规则变化
# - 用户资料字段变化
→ User 模块
# 通知相关的变化原因:
# - 通知渠道变化(邮件、短信、推送)
# - 通知模板变化
→ Notification 模块
原则2:按职责划分
单一职责原则(SRP):一个模块只做一类事情。
# 好的划分
class UserAuthentication: # 职责:认证
def login(self, username, password): ...
def logout(self, session): ...
class UserProfile: # 职责:用户资料
def get_profile(self, user_id): ...
def update_profile(self, user_id, data): ...
class UserPermissions: # 职责:权限管理
def has_permission(self, user, permission): ...
def grant_permission(self, user, permission): ...
原则3:按依赖方向划分
核心业务 ← 基础设施
# 错误:业务逻辑依赖具体实现
class OrderService:
def create_order(self, data):
# 直接依赖 MySQL
mysql.execute("INSERT INTO orders ...")
# 正确:业务逻辑依赖抽象
class OrderService:
def __init__(self, order_repository):
# 依赖抽象接口
self.repo = order_repository
def create_order(self, data):
order = Order(**data)
self.repo.save(order) # 不关心底层是 MySQL 还是 PostgreSQL
# 具体实现在外层
class MySQLOrderRepository:
def save(self, order):
mysql.execute("INSERT INTO orders ...")
边界的表现形式
形式1:包/模块
project/
├── domain/ # 核心领域逻辑
│ ├── user.py
│ └── order.py
├── application/ # 应用服务
│ ├── user_service.py
│ └── order_service.py
├── infrastructure/ # 基础设施
│ ├── database.py
│ └── email.py
└── interfaces/ # 接口层
├── api.py
└── cli.py
形式2:接口/契约
from abc import ABC, abstractmethod
# 定义边界:抽象接口
class OrderRepository(ABC):
@abstractmethod
def save(self, order):
pass
@abstractmethod
def get(self, order_id):
pass
# 实现1:MySQL
class MySQLOrderRepository(OrderRepository):
def save(self, order):
# MySQL 具体实现
...
# 实现2:MongoDB
class MongoOrderRepository(OrderRepository):
def save(self, order):
# MongoDB 具体实现
...
形式3:API契约
# HTTP API 定义边界
# 前端只需要知道这个契约,不需要知道后端实现
"""
POST /api/orders
Request:
{
"user_id": 123,
"items": [
{"product_id": 1, "quantity": 2}
]
}
Response:
{
"order_id": 456,
"total": 99.90,
"status": "pending"
}
"""
边界混乱的症状
症状1:修改一处影响多处
# 症状:改订单逻辑,用户模块也要改
# 原因:边界不清,职责混乱
症状2:难以测试
# 症状:测试订单创建,必须启动整个系统
# 原因:边界不清,依赖太多
症状3:团队协作困难
# 症状:两个开发者同时修改同一个文件
# 原因:边界不清,职责集中在少数文件
重构边界的策略
策略:识别混乱点
# 问自己
1. 这个类/函数做了几件事?(超过1件 = 边界混乱)
2. 修改这个需求需要改几个地方?(超过1个模块 = 边界混乱)
3. 这个模块有几个修改的理由?(超过1个 = 边界混乱)
策略:渐进式重构
# 不要一次性大重构
# 每次只重构一个边界
# 步骤1:提取接口
class UserService:
def create_order(self, items):
# 先提取订单创建逻辑到独立函数
return self._create_order_logic(items)
# 步骤2:独立模块
class OrderService:
def create_order(self, user_id, items):
# 移到独立模块
...
# 步骤3:修改调用方
class UserService:
def __init__(self, order_service):
self.order_service = order_service
def create_order(self, items):
return self.order_service.create_order(self.user_id, items)
总结
所有痛苦来自边界不清:
- 边界定义职责——每个模块只做一件事
- 清晰的边界让系统可维护——修改局部不影响全局
- 边界通过接口表达——依赖抽象而非具体
- 边界按变化原因划分——不同原因 = 不同模块
- 渐进式重构边界——不要一次性大改
记住:
当你不知道一段代码应该放在哪里时,说明边界不清。
好的架构让每个模块的职责一目了然。
花时间厘清边界,能节省未来数倍的维护时间。

浙公网安备 33010602011771号