学习搭子,你好!前面咱们学习了分层架构的理论知识,但在实际项目中应用时,总会遇到各种"坑"。今天咱们就来盘点一下分层架构实践中的常见误区,并分享经过验证的正确做法。这些经验都是从真实项目中总结出来的,希望能帮你少走弯路!
# 一个简单的查询功能被拆分成7层
# 项目结构:
project/
├── presentation/web/controllers/order_controller.py
├── presentation/web/middlewares/auth_middleware.py
├── application/usecases/get_order_usecase.py
├── application/services/order_query_service.py
├── domain/services/order_domain_service.py
├── domain/repositories/order_repository_interface.py
├── infrastructure/database/repositories/order_repository_impl.py
├── infrastructure/database/models/order_entity.py
└── shared/utils/response_formatter.py
# 调用链:
Controller → Middleware → UseCase → QueryService → DomainService → Repository → Database
# 然后原路返回,加上各种DTO转换和格式化
# 根据项目规模选择合适的分层:
# 小型项目(< 1万行代码) - 经典三层足够
project/
├── controllers/ # 表现层
├── services/ # 业务逻辑层
└── repositories/ # 数据访问层
# 中型项目(1-10万行代码) - 四层架构
project/
├── interfaces/ # 接口层(Web/API)
├── application/ # 应用服务层
├── domain/ # 领域层
└── infrastructure/ # 基础设施层
# 大型项目(> 10万行代码) - 清洁架构/六边形架构
# 在四层基础上增加更严格的边界和适配器
# 判断标准:
# 1. 团队规模:小团队(< 5人)不要过度分层
# 2. 变更频率:频繁变更的领域不要过度抽象
# 3. 测试需求:需要深度测试的领域可以适当分层
# 所有代码混在一个文件或几个大文件中
# app.py - 5000行代码包含:
# - 数据库连接和查询
# - 业务逻辑处理
# - API路由定义
# - 错误处理
# - 配置管理
defhandle_order_request(request):
# 1. 验证参数(表现层职责)
ifnot validate_request(request):
return error_response("参数错误")
# 2. 查询数据库(数据层职责)
conn = mysql.connect(config)
cursor = conn.cursor()
cursor.execute("SELECT * FROM orders WHERE id = %s", (request.order_id,))
order_data = cursor.fetchone()
# 3. 业务逻辑处理(业务层职责)
if order_data['status'] == 'cancelled':
return error_response("订单已取消")
# 4. 计算价格
total = calculate_total(order_data)
# 5. 返回响应(表现层职责)
return {"order": order_data, "total": total}
# 问题:职责混杂,难以维护和测试
# 建立明确的分层规则:
# 规则1:每层只能调用下一层,不能跨层调用
# ✅ 允许:Controller → Service → Repository
# ❌ 禁止:Controller → Repository(跨过Service)
# 规则2:下层不能知道上层的存在
# ✅ 允许:Service知道Repository接口
# ❌ 禁止:Repository知道Service的存在
# 规则3:数据流动方向固定
# 请求:上层 → 下层
# 响应:下层 → 上层
# 实施检查清单:
# 1. 导入语句检查:上层可以导入下层,下层不能导入上层
# 2. 循环依赖检查:使用工具检测循环依赖
# 3. 接口隔离检查:层间必须通过接口通信
# 示例:正确的导入关系
# controller.py
from services.order_service import OrderService # ✅ 导入下层
from domain.models import Order # ✅ 导入领域模型
# order_service.py
from repositories.order_repository import IOrderRepository # ✅ 导入下层接口
from domain.models import Order # ✅ 导入领域模型
# order_repository.py
from domain.models import Order # ✅ 只导入领域模型
# 没有向上层的导入
# 教条地遵守"三层架构",导致不合理的代码组织
# 例子:缓存操作放在哪一层?
# 按照传统三层:
# - 表现层:处理HTTP请求
# - 业务层:业务逻辑
# - 数据层:数据库操作
# 缓存既不是纯业务逻辑,也不是纯数据访问
# 结果:要么放在业务层(污染业务逻辑),要么放在数据层(混合缓存和数据库)
classOrderService:
def__init__(self):
self.cache = RedisCache() # 缓存放在业务层?
self.repository = OrderRepository()
defget_order(self, order_id):
# 先查缓存
cached = self.cache.get(f"order:{order_id}")
if cached:
return cached
# 再查数据库
order = self.repository.get_by_id(order_id)
# 写入缓存
self.cache.set(f"order:{order_id}", order, ttl=300)
return order
# 问题:业务层包含了缓存逻辑,违反单一职责
# 解决方案:引入基础设施层专门处理技术实现
# 项目结构:
project/
├── domain/ # 领域层(纯业务)
│ ├── models/ # 领域模型
│ └── services/ # 领域服务
├── application/ # 应用层
│ └── services/ # 应用服务(协调领域对象)
├── infrastructure/ # 基础设施层
│ ├── cache/ # 缓存实现
│ ├── database/ # 数据库实现
│ └── external/ # 外部服务
└── interfaces/ # 接口层
└── web/ # Web接口
# 缓存实现:
classCacheAwareOrderRepository:
"""带缓存的仓储实现 - 装饰器模式"""
def__init__(self, inner_repository, cache):
self._inner = inner_repository
self._cache = cache
defget_by_id(self, order_id):
# 缓存键
cache_key = f"order:{order_id}"
# 尝试从缓存获取
cached = self._cache.get(cache_key)
if cached isnotNone:
return cached
# 缓存未命中,从实际仓储获取
order = self._inner.get_by_id(order_id)
if order:
# 写入缓存
self._cache.set(cache_key, order, ttl=300)
return order
# 使用:
order_repository = OrderRepository(db_session)
cached_repository = CacheAwareOrderRepository(order_repository, redis_cache)
# 业务层使用缓存仓储,但不知道缓存实现细节
classOrderService:
def__init__(self, repository: IOrderRepository): # 依赖抽象
self.repository = repository
defget_order(self, order_id):
# 业务逻辑
returnself.repository.get_by_id(order_id) # 透明使用缓存
2.1 误区4:贫血模型(Anemic Domain Model)
# 领域模型只有数据,没有行为
# 所有业务逻辑都在Service中
@dataclass
classOrder:
"""贫血的订单模型"""
id: int
items: List[OrderItem]
status: str
total_amount: float
created_at: datetime
# 没有任何业务方法
# 所有操作都需要通过OrderService
classOrderService:
"""承担了所有业务逻辑"""
defcreate_order(self, user_id, items):
# 验证逻辑
ifnot items:
raise ValueError("订单不能为空")
# 计算逻辑
total = sum(item.price * item.quantity for item in items)
# 创建订单
order = Order(
id=None,
items=items,
status='pending',
total_amount=total,
created_at=datetime.now()
)
# 保存逻辑
returnself.repository.save(order)
defcancel_order(self, order_id):
order = self.repository.get_by_id(order_id)
# 业务规则:已发货的订单不能取消
if order.status == 'shipped':
raise ValueError("已发货的订单不能取消")
order.status = 'cancelled'
returnself.repository.save(order)
# 问题:
# 1. Order对象只是数据容器,没有封装业务规则
# 2. 业务逻辑分散在多个Service方法中
# 3. 难以保证业务规则的一致性
# 将业务逻辑移入领域模型
@dataclass
classOrderItem:
product_id: int
product_name: str
unit_price: Money # 值对象
quantity: int
@property
deftotal_price(self) -> Money:
return Money(self.unit_price.amount * self.quantity,
self.unit_price.currency)
@dataclass
classOrder:
"""丰富的订单模型"""
id: Optional[int]
user_id: int
items: List[OrderItem]
status: str
created_at: datetime
updated_at: datetime
_events: List[DomainEvent] = field(default_factory=list)
def__post_init__(self):
ifself.idisNone:
self.id = self._generate_id()
@property
deftotal_amount(self) -> Money:
ifnotself.items:
return Money(0, 'CNY')
total = Money(0, self.items[0].unit_price.currency)
for item inself.items:
total = total.add(item.total_price)
return total
defadd_item(self, product_id: int, product_name: str,
unit_price: Money, quantity: int):
"""添加订单项 - 业务逻辑封装在实体内部"""
if quantity <= 0:
raise ValueError("数量必须大于0")
ifself.status != 'pending':
raise ValueError("只有待处理订单可以添加商品")
item = OrderItem(
product_id=product_id,
product_name=product_name,
unit_price=unit_price,
quantity=quantity
)
self.items.append(item)
self.updated_at = datetime.now()
# 发布领域事件
self._events.append(OrderItemAdded(
order_id=self.id,
product_id=product_id,
quantity=quantity
))
defcancel(self):
"""取消订单 - 业务规则内聚"""
ifself.status in ['shipped', 'delivered']:
raise ValueError(f"订单状态为{self.status},不能取消")
ifself.status == 'paid'andself.created_at < datetime.now() - timedelta(hours=24):
raise ValueError("支付超过24小时的订单不能直接取消")
self.status = 'cancelled'
self.updated_at = datetime.now()
# 发布领域事件
self._events.append(OrderCancelled(
order_id=self.id,
cancelled_at=self.updated_at
))
defmark_as_paid(self, payment_id: str):
"""标记为已支付"""
ifself.status != 'pending':
raise ValueError(f"订单状态为{self.status},不能标记为已支付")
self.status = 'paid'
self.updated_at = datetime.now()
self.payment_id = payment_id
self._events.append(OrderPaid(
order_id=self.id,
payment_id=payment_id,
amount=self.total_amount.amount
))
defget_events(self) -> List[DomainEvent]:
"""获取待处理的领域事件"""
events = self._events.copy()
self._events.clear()
return events
# Service变得精简,主要负责协调
classOrderService:
def__init__(self, repository: IOrderRepository):
self.repository = repository
defcreate_order(self, user_id, items_data):
# 创建订单
order = Order(
id=None,
user_id=user_id,
items=[],
status='pending',
created_at=datetime.now(),
updated_at=datetime.now()
)
# 添加订单项
for item_data in items_data:
order.add_item(**item_data)
# 保存订单
saved_order = self.repository.save(order)
# 处理领域事件
self._handle_events(saved_order.get_events())
return saved_order
def_handle_events(self, events):
# 发布事件到事件总线
for event in events:
event_bus.publish(event)
# 将所有逻辑都塞进领域模型,导致模型过于臃肿
classOrder:
def__init__(self, ...):
# ... 初始化
defcalculate_total(self):
# 计算总额
pass
defapply_discount(self, coupon):
# 应用优惠券
pass
defgenerate_invoice(self):
# 生成发票
pass
defsend_notification(self):
# 发送通知
pass
defexport_to_excel(self):
# 导出到Excel
pass
defprint_receipt(self):
# 打印小票
pass
defvalidate_shipping_address(self):
# 验证配送地址
pass
defcalculate_shipping_cost(self):
# 计算运费
pass
# ... 几十个方法,涵盖所有可能的业务场景
# 问题:
# 1. 模型职责过多,违反单一职责原则
# 2. 包含了技术细节(如Excel导出、打印)
# 3. 难以理解和维护
# 使用领域驱动设计(DDD)的概念划分职责
# 核心域(Core Domain):订单的核心业务逻辑
classOrder:
"""订单核心域"""
def__init__(self, ...):
# 核心属性
pass
defadd_item(self, item):
"""核心业务:添加商品"""
# 只包含与订单状态直接相关的逻辑
pass
defcancel(self):
"""核心业务:取消订单"""
# 只包含订单状态变化的业务规则
pass
defmark_as_paid(self, payment_id):
"""核心业务:标记支付"""
pass
# 支撑域(Supporting Domain):支持核心域的功能
classInvoiceService:
"""发票服务 - 支撑域"""
defgenerate_invoice(self, order: Order):
"""生成发票 - 支撑功能"""
# 发票生成逻辑
pass
defsend_invoice_email(self, order: Order, email: str):
"""发送发票邮件 - 支撑功能"""
pass
classNotificationService:
"""通知服务 - 支撑域"""
defsend_order_confirmation(self, order: Order):
"""发送订单确认 - 支撑功能"""
pass
defsend_shipping_notification(self, order: Order):
"""发送发货通知 - 支撑功能"""
pass
# 通用域(Generic Domain):通用技术功能
classExcelExportService:
"""Excel导出服务 - 通用域"""
defexport_orders(self, orders: List[Order]):
"""导出到Excel - 通用功能"""
pass
classPrinterService:
"""打印服务 - 通用域"""
defprint_receipt(self, order: Order):
"""打印小票 - 通用功能"""
pass
# 划分原则:
# 1. 核心域:只有改变领域对象状态的逻辑
# 2. 支撑域:为核心域提供支持,但不改变核心状态
# 3. 通用域:与技术实现相关的通用功能
# 直接依赖具体实现,而不是接口
classOrderService:
def__init__(self):
# 直接依赖MySQL数据库
self.db = mysql.connector.connect(
host='localhost',
user='root',
password='secret',
database='orders'
)
defget_order(self, order_id):
cursor = self.db.cursor()
cursor.execute('SELECT * FROM orders WHERE id = %s', (order_id,))
return cursor.fetchone()
# 问题:
# 1. 难以替换数据库(如换到PostgreSQL)
# 2. 难以单元测试(需要真实的MySQL连接)
# 3. 配置硬编码,不灵活
# 步骤1:定义接口
from abc import ABC, abstractmethod
from typing importOptional, List
classIOrderRepository(ABC):
"""订单仓储接口"""
@abstractmethod
defget_by_id(self, order_id: int) -> Optional['Order']:
pass
@abstractmethod
defsave(self, order: 'Order') -> 'Order':
pass
@abstractmethod
defget_by_user_id(self, user_id: int) -> List['Order']:
pass
# 步骤2:实现接口
classMySQLOrderRepository(IOrderRepository):
"""MySQL实现"""
def__init__(self, connection_config: dict):
self.config = connection_config
self._connection = None
def_get_connection(self):
ifself._connection isNoneornotself._connection.is_connected():
self._connection = mysql.connector.connect(**self.config)
returnself._connection
defget_by_id(self, order_id: int):
conn = self._get_connection()
cursor = conn.cursor(dictionary=True)
cursor.execute('SELECT * FROM orders WHERE id = %s', (order_id,))
row = cursor.fetchone()
if row:
return Order(**row)
returnNone
# ... 其他方法实现
classPostgreSQLOrderRepository(IOrderRepository):
"""PostgreSQL实现"""
def__init__(self, connection_string: str):
self.conn_string = connection_string
defget_by_id(self, order_id: int):
import psycopg2
conn = psycopg2.connect(self.conn_string)
cursor = conn.cursor()
cursor.execute('SELECT * FROM orders WHERE id = %s', (order_id,))
row = cursor.fetchone()
if row:
# 转换为Order对象
pass
# ... 其他方法实现
# 步骤3:通过依赖注入使用
classOrderService:
def__init__(self, repository: IOrderRepository): # 依赖抽象
self.repository = repository
defget_order(self, order_id: int):
# 业务逻辑
returnself.repository.get_by_id(order_id)
# 使用:
# 配置驱动,而不是代码驱动
config = load_config('database.yml')
if config['type'] == 'mysql':
repository = MySQLOrderRepository(config['mysql'])
elif config['type'] == 'postgresql':
repository = PostgreSQLOrderRepository(config['postgresql'])
else:
raise ValueError(f"不支持的数据库类型: {config['type']}")
service = OrderService(repository)
# 测试时可以使用Mock
classMockOrderRepository(IOrderRepository):
defget_by_id(self, order_id):
return Order(id=order_id, status='pending')
test_service = OrderService(MockOrderRepository())
# 将所有服务都注册为单例,不考虑实际需求
container.register_singleton(IDatabase)
container.register_singleton(IUserRepository)
container.register_singleton(IOrderRepository)
container.register_singleton(UserService)
container.register_singleton(OrderService)
container.register_singleton(EmailService)
container.register_singleton(CacheService)
# 问题:
# 1. 状态污染:单例对象在不同请求间共享状态
# 2. 线程不安全:Python的GIL不能解决所有并发问题
# 3. 内存泄漏:单例对象永远不会被回收
# 4. 测试困难:单例状态在测试间相互影响
# 不同服务使用不同的生命周期:
# 1. 基础设施服务:单例(创建成本高,无状态)
# - 数据库连接池
# - Redis连接
# - HTTP客户端连接池
# - 配置服务
container.register_singleton(IDatabaseConnectionPool)
container.register_singleton(RedisClient)
container.register_singleton(HttpClientPool)
container.register_singleton(ConfigService)
# 2. 仓储服务:作用域生命周期(每个请求一个实例)
# - 数据库仓储
# - 缓存仓储装饰器
container.register_scoped(IOrderRepository, OrderRepository)
container.register_scoped(IUserRepository, UserRepository)
# 3. 应用服务:瞬时生命周期(每次解析都新建)
# - 业务逻辑服务
# - 计算服务
# - 验证服务
container.register_transient(OrderService)
container.register_transient(PaymentService)
container.register_transient(ValidationService)
# 4. 工厂服务:工厂模式
# - 复杂对象的创建
# - 需要参数的对象
container.register_factory(ReportGenerator, create_report_generator)
# 生命周期选择标准:
#
# 选择单例(Singleton):
# - 创建成本高昂(数据库连接、外部API客户端)
# - 无状态或线程安全
# - 全局配置或工具类
#
# 选择作用域(Scoped):
# - 需要请求上下文(如数据库事务)
# - 需要在同一请求中共享状态
# - Web请求、消息处理上下文
#
# 选择瞬时(Transient):
# - 有状态且状态不应共享
# - 轻量级对象,创建成本低
# - 每次使用都需要新实例
#
# 选择工厂(Factory):
# - 创建逻辑复杂
# - 需要运行时参数
# - 需要控制创建过程
# 在Controller中直接返回领域对象
@router.get("/orders/{order_id}")
defget_order(order_id: int):
order = order_service.get_order(order_id)
# 直接返回领域对象
return {
"success": True,
"data": order # Order领域对象直接暴露
}
# 问题:
# 1. 暴露内部实现细节
# 2. 可能包含敏感数据
# 3. API响应结构不可控
# 4. 前端耦合领域模型
# 步骤1:定义DTO
from dataclasses import dataclass
from typing importList
from datetime import datetime
@dataclass
classOrderItemDTO:
product_id: int
product_name: str
unit_price: float
quantity: int
total_price: float
@dataclass
classOrderDTO:
"""订单数据传输对象"""
id: int
user_id: int
status: str
total_amount: float
items: List[OrderItemDTO]
created_at: datetime
updated_at: datetime
@classmethod
deffrom_entity(cls, order: Order) -> 'OrderDTO':
"""从领域对象转换"""
return cls(
id=order.id,
user_id=order.user_id,
status=order.status,
total_amount=order.total_amount.amount,
items=[
OrderItemDTO(
product_id=item.product_id,
product_name=item.product_name,
unit_price=item.unit_price.amount,
quantity=item.quantity,
total_price=item.total_price.amount
)
for item in order.items
],
created_at=order.created_at,
updated_at=order.updated_at
)
defto_dict(self) -> dict:
"""转换为字典(适合JSON序列化)"""
return {
'id': self.id,
'user_id': self.user_id,
'status': self.status,
'total_amount': self.total_amount,
'items': [
{
'product_id': item.product_id,
'product_name': item.product_name,
'unit_price': item.unit_price,
'quantity': item.quantity,
'total_price': item.total_price
}
for item inself.items
],
'created_at': self.created_at.isoformat(),
'updated_at': self.updated_at.isoformat()
}
# 步骤2:在应用层使用DTO
classGetOrderUseCase:
def__init__(self, order_service: OrderService):
self.order_service = order_service
defexecute(self, order_id: int) -> OrderDTO:
order = self.order_service.get_order(order_id)
return OrderDTO.from_entity(order)
# 步骤3:Controller返回DTO
@router.get("/orders/{order_id}")
defget_order(order_id: int, usecase: GetOrderUseCase = Depends()):
try:
order_dto = usecase.execute(order_id)
return {
"success": True,
"data": order_dto.to_dict()
}
except ValueError as e:
return {
"success": False,
"error": str(e)
}
# DTO的好处:
# 1. 控制API暴露的数据
# 2. 可以添加API特定的字段(如格式化时间)
# 3. 解耦领域模型和API契约
# 4. 方便版本管理(不同API版本返回不同DTO)
# 只在Controller层做简单的参数验证
# 业务层的验证缺失或不完整
@router.post("/orders")
defcreate_order(order_data: dict):
# 简单的参数验证
if'items'notin order_data:
return {"error": "缺少items参数"}
# 直接调用业务层
order = order_service.create_order(order_data)
return {"success": True, "order_id": order.id}
classOrderService:
defcreate_order(self, data: dict):
# 假设数据已经验证过,直接使用
items = data['items'] # 可能为空列表或格式错误
# 业务验证缺失
order = Order(items=items)
returnself.repository.save(order)
# 问题:
# 1. 验证逻辑分散
# 2. 业务规则可能被绕过
# 3. 数据一致性无法保证
# 建立多层次的验证体系:
# 层次1:输入验证(表现层)
# - 基本格式检查
# - 必填字段检查
# - 类型转换
from pydantic import BaseModel, validator
from typing importList
classCreateOrderRequest(BaseModel):
"""API请求DTO,包含输入验证"""
user_id: int
items: List['OrderItemRequest']
@validator('user_id')
defvalidate_user_id(cls, v):
if v <= 0:
raise ValueError('用户ID必须大于0')
return v
classOrderItemRequest(BaseModel):
product_id: int
quantity: int
@validator('quantity')
defvalidate_quantity(cls, v):
if v <= 0:
raise ValueError('数量必须大于0')
if v > 100:
raise ValueError('单次购买数量不能超过100')
return v
# 层次2:业务规则验证(领域层)
# - 业务逻辑检查
# - 数据一致性验证
# - 约束条件检查
classOrder:
def__init__(self, user_id: int, items: List[OrderItem]):
self.user_id = user_id
self.items = items
self.status = 'pending'
self._validate()
def_validate(self):
"""领域对象内部验证"""
ifnotself.items:
raise ValueError("订单必须包含至少一件商品")
# 检查商品是否重复
product_ids = [item.product_id for item inself.items]
iflen(product_ids) != len(set(product_ids)):
raise ValueError("订单中包含重复商品")
# 业务规则:单个订单总金额不能超过10000
ifself.total_amount.amount > 10000:
raise ValueError("单个订单金额不能超过10000元")
defadd_item(self, item: OrderItem):
"""添加商品时的验证"""
# 检查是否已存在相同商品
for existing_item inself.items:
if existing_item.product_id == item.product_id:
raise ValueError(f"商品{item.product_id}已存在于订单中")
self.items.append(item)
self._validate() # 添加后重新验证
# 层次3:数据完整性验证(仓储层)
# - 唯一性约束
# - 外键关系检查
# - 事务一致性
classOrderRepository:
defsave(self, order: Order) -> Order:
"""保存前的验证"""
# 检查用户是否存在
user = self.user_repository.get_by_id(order.user_id)
ifnot user:
raise ValueError(f"用户{order.user_id}不存在")
# 检查商品是否都存在
for item in order.items:
product = self.product_repository.get_by_id(item.product_id)
ifnot product:
raise ValueError(f"商品{item.product_id}不存在")
# 保存到数据库
returnself._save_to_db(order)
# 使用:
@router.post("/orders")
defcreate_order(request: CreateOrderRequest):
try:
# 层次1:输入验证(Pydantic自动完成)
# 转换为领域对象
order_items = [
OrderItem(
product_id=item.product_id,
quantity=item.quantity
)
for item in request.items
]
# 层次2:业务规则验证(在Order构造方法中)
order = Order(user_id=request.user_id, items=order_items)
# 层次3:数据完整性验证(在Repository中)
saved_order = order_repository.save(order)
return {
"success": True,
"order_id": saved_order.id
}
except ValueError as e:
return {
"success": False,
"error": str(e)
}
# 每层都进行数据转换,导致性能下降
# 调用链中的转换:
# 1. 数据库行 → 领域对象(Repository层)
# 2. 领域对象 → 业务DTO(Service层)
# 3. 业务DTO → API响应DTO(Controller层)
defget_order_details(order_id):
# Repository: 数据库行 → Order实体
order = order_repository.get_by_id(order_id) # 转换1
# Service: Order实体 → OrderDetailsDTO
details = order_service.get_order_details(order) # 转换2
# Controller: OrderDetailsDTO → OrderResponse
response = order_controller.format_response(details) # 转换3
return response
# 问题:
# 1. 多次内存拷贝
# 2. 对象创建开销
# 3. 在热点路径上可能成为瓶颈
# 优化策略:
# 策略1:选择性转换
# 只在需要的地方进行转换,避免不必要的转换
classOrderService:
defget_order_summary(self, order_id):
"""获取订单摘要 - 只需要部分字段"""
order = self.repository.get_by_id(order_id)
# 直接返回需要的字段,不创建完整的DTO
return {
'id': order.id,
'status': order.status,
'total': order.total_amount.amount,
'item_count': len(order.items)
}
defget_order_full_details(self, order_id):
"""获取订单完整详情 - 需要完整DTO"""
order = self.repository.get_by_id(order_id)
return OrderFullDTO.from_entity(order)
# 策略2:使用惰性加载
# 延迟加载不立即需要的数据
classOrderRepository:
defget_by_id_with_lazy(self, order_id):
"""获取订单,关联数据惰性加载"""
order = self._get_order_from_db(order_id)
# 设置惰性属性
order._load_items = lambda: self._get_items_for_order(order_id)
order._load_user = lambda: self._get_user_for_order(order.user_id)
return order
# 策略3:批量操作优化
# 减少层间调用次数
classOrderService:
defbatch_get_orders(self, order_ids):
"""批量获取订单 - 减少多次单独调用"""
# 一次性从Repository获取所有订单
orders = self.repository.get_by_ids(order_ids)
# 批量处理,减少转换次数
return [OrderSummaryDTO.from_entity(order) for order in orders]
defget_orders_by_user(self, user_id, page=1, page_size=20):
"""分页查询 - 在数据层完成分页"""
# Repository支持分页,避免加载全部数据
returnself.repository.get_by_user_paged(user_id, page, page_size)
# 策略4:缓存优化
# 合理使用缓存减少层间数据传递
classCachingOrderService:
def__init__(self, inner_service, cache):
self.inner = inner_service
self.cache = cache
defget_order(self, order_id):
# 首先尝试缓存
cached = self.cache.get(f"order:{order_id}")
if cached isnotNone:
return cached
# 缓存未命中,调用内部服务
order = self.inner.get_order(order_id)
# 写入缓存(可以缓存DTO,避免重复转换)
self.cache.set(f"order:{order_id}", order, ttl=300)
return order
# 性能监控指标:
# 1. 各层方法调用耗时
# 2. 对象创建和GC压力
# 3. 内存使用情况
# 4. 数据库查询次数和耗时
# 在项目初期就设计复杂的、支持未来扩展的架构
# 但实际上业务需求还不明确
# 例子:一个简单的博客系统
# 却设计了支持微服务、事件溯源、CQRS的架构
project/
├── user-service/ # 用户服务
├── post-service/ # 文章服务
├── comment-service/ # 评论服务
├── event-bus/ # 事件总线
├── api-gateway/ # API网关
└── saga-orchestrator/ # 分布式事务协调器
# 问题:
# 1. 开发效率极低
# 2. 运维复杂
# 3. 过度设计,大部分功能用不上
# 4. 团队学习曲线陡峭
# 原则:从简单开始,按需演进
# 阶段1:单体应用(MVP阶段)
# 目标:快速验证业务想法
# 架构:简单的三层架构
project/
├── controllers/ # Web接口
├── services/ # 业务逻辑
├── repositories/ # 数据访问
└── models/ # 领域模型
# 阶段2:模块化单体(业务增长)
# 目标:提高可维护性
# 架构:按业务模块划分
project/
├── modules/
│ ├── user/ # 用户模块
│ ├── post/ # 文章模块
│ └── comment/ # 评论模块
└── shared/ # 共享代码
# 阶段3:微服务架构(需要独立扩展)
# 目标:独立部署和扩展
# 前提:
# 1. 团队规模足够(> 20人)
# 2. 业务复杂度高
# 3. 需要不同的技术栈
# 4. 需要不同的扩展策略
services/
├── user-service/
├── post-service/
├── comment-service/
├── api-gateway/
└── shared-infra/
# 演进决策框架:
defshould_split_to_microservice(module):
"""判断模块是否应该拆分为微服务"""
criteria = {
'team_size': len(get_team_for_module(module)) > 5,
'deployment_frequency': get_deployment_freq(module) > 10,
'scaling_needs': get_scaling_needs(module) != 'same_as_others',
'tech_stack': get_tech_stack(module) != 'main_stack',
'failure_domain': get_failure_impact(module) == 'high',
'data_isolation': needs_data_isolation(module)
}
# 计算得分
score = sum(1for value in criteria.values() if value)
# 决策规则
if score >= 4:
returnTrue, "强烈建议拆分"
elif score >= 2:
returnFalse, "可以考虑,但不是必须"
else:
returnFalse, "不建议拆分"
# 架构演进检查点:
# 1. 团队规模翻倍时
# 2. 用户量增长10倍时
# 3. 出现明显的性能瓶颈时
# 4. 需要新技术栈时
# 5. 业务模式发生重大变化时
# 所有测试都集中在Service层
# 或者测试覆盖不全
# 常见问题:
# 1. Controller层不测试或测试不足
# 2. Repository层使用真实数据库,测试慢且不可靠
# 3. 领域对象不单独测试
# 4. 集成测试缺失
# 测试金字塔倒置:
# /\
# / \ <- 大量端到端测试
# / \
# /______\ <- 少量单元测试
# 建立分层的测试策略:
# 层次1:单元测试(最多)
# - 测试领域对象、值对象
# - 测试纯函数
# - 快速、可靠
# tests/unit/domain/test_order.py
classTestOrder:
deftest_order_creation(self):
"""测试订单创建"""
order = Order(user_id=1, items=[])
assert order.status == 'pending'
assert order.user_id == 1
deftest_add_item(self):
"""测试添加商品"""
order = Order(user_id=1, items=[])
item = OrderItem(product_id=1, quantity=2)
order.add_item(item)
assertlen(order.items) == 1
assert order.items[0].product_id == 1
deftest_total_amount_calculation(self):
"""测试总额计算"""
order = Order(
user_id=1,
items=[
OrderItem(product_id=1, quantity=2, unit_price=Money(100, 'CNY')),
OrderItem(product_id=2, quantity=1, unit_price=Money(50, 'CNY'))
]
)
assert order.total_amount.amount == 250
# 层次2:服务层测试(较多)
# - 测试业务逻辑服务
# - 使用Mock替代外部依赖
# tests/unit/services/test_order_service.py
classTestOrderService:
deftest_create_order(self):
"""测试订单创建服务"""
# Mock仓储
mock_repo = Mock(spec=IOrderRepository)
mock_repo.save.return_value = Order(id=1, user_id=1, items=[])
service = OrderService(mock_repo)
result = service.create_order(user_id=1, items_data=[])
assert result.id == 1
mock_repo.save.assert_called_once()
# 层次3:集成测试(中等)
# - 测试层间集成
# - 使用测试数据库
# tests/integration/test_order_flow.py
classTestOrderFlow:
@pytest.fixture
deftest_db(self):
"""使用内存数据库进行测试"""
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
return engine
deftest_create_and_get_order(self, test_db):
"""测试创建和获取订单的完整流程"""
# 创建仓储
repo = OrderRepository(test_db)
# 创建服务
service = OrderService(repo)
# 创建订单
order = service.create_order(
user_id=1,
items_data=[{'product_id': 1, 'quantity': 2}]
)
# 验证
retrieved = repo.get_by_id(order.id)
assert retrieved isnotNone
assert retrieved.user_id == 1
# 层次4:端到端测试(较少)
# - 测试完整的业务流程
# - 模拟真实用户操作
# tests/e2e/test_order_api.py
classTestOrderAPI:
deftest_create_order_via_api(self):
"""通过API测试订单创建"""
# 启动测试服务器
with TestClient(app) as client:
# 调用API
response = client.post('/api/orders', json={
'user_id': 1,
'items': [
{'product_id': 1, 'quantity': 2}
]
})
assert response.status_code == 200
data = response.json()
assert data['success'] == True
assert'order_id'in data['data']
# 层次5:契约测试(微服务场景)
# - 测试服务间接口契约
# - 确保前后端兼容性
# tests/contract/test_order_contract.py
classTestOrderContract:
deftest_order_api_contract(self):
"""测试订单API契约"""
# 使用OpenAPI规范验证
spec = load_openapi_spec('openapi/orders.yaml')
# 验证响应符合契约
validator = OpenAPISpecValidator(spec)
# 测试各个端点
test_cases = [
('GET', '/api/orders/{id}'),
('POST', '/api/orders'),
('PUT', '/api/orders/{id}'),
]
for method, path in test_cases:
validator.validate_endpoint(method, path)
# 测试覆盖率目标:
# 单元测试:80-90%(领域核心)
# 集成测试:70-80%(主要流程)
# 端到端测试:50-60%(关键路径)
# 强行引入复杂架构,不考虑团队实际能力
# 例子:团队都是初级开发者
# 却引入DDD、CQRS、事件溯源等复杂概念
# 结果:
# 1. 开发效率极低
# 2. 代码质量差
# 3. 团队士气低落
# 4. 项目延期严重
# 根据团队现状选择合适的技术栈:
# 团队成熟度评估:
defassess_team_maturity(team):
"""评估团队技术成熟度"""
factors = {
'senior_ratio': len([m for m in team if m.level == 'senior']) / len(team),
'avg_experience': sum(m.years_exp for m in team) / len(team),
'training_completed': sum(1for m in team if m.trained_in_ddd),
'existing_codebase_complexity': assess_codebase_complexity(),
'business_domain_complexity': assess_business_complexity()
}
# 计算成熟度分数
score = (
factors['senior_ratio'] * 0.3 +
factors['avg_experience'] * 0.2 +
factors['training_completed'] * 0.2 +
factors['existing_codebase_complexity'] * 0.15 +
factors['business_domain_complexity'] * 0.15
)
# 分类
if score >= 0.8:
return'advanced', "可以引入复杂架构"
elif score >= 0.5:
return'intermediate', "适合经典分层架构"
else:
return'beginner', "从简单三层架构开始"
# 技术栈选择矩阵:
# | 团队成熟度 | 推荐架构 | 关键技术 | 注意事项 |
# |------------|----------|----------|----------|
# | 初级团队 | 经典三层 | 简单ORM、基础DI | 避免过度抽象 |
# | 中级团队 | 四层架构 | 接口隔离、依赖注入 | 逐步引入模式 |
# | 高级团队 | 清洁架构 | DDD、CQRS、事件 | 保证业务价值 |
# 培训计划:
training_plan = {
'beginner': [
'基础分层概念',
'单一职责原则',
'简单依赖注入',
'基础测试策略'
],
'intermediate': [
'接口隔离原则',
'依赖倒置原则',
'仓储模式',
'单元测试最佳实践'
],
'advanced': [
'领域驱动设计',
'六边形架构',
'事件溯源',
'契约测试'
]
}
# 代码评审重点:
code_review_checklist = {
'beginner': [
'是否符合分层边界',
'是否有明显紧耦合',
'是否可测试',
'命名是否清晰'
],
'intermediate': [
'是否依赖抽象',
'是否遵循SOLID原则',
'测试覆盖率',
'异常处理'
],
'advanced': [
'领域模型是否丰富',
'是否恰当使用模式',
'性能考虑',
'可扩展性'
]
}
# 架构设计后缺乏持续治理
# 导致架构逐渐腐化
# 症状:
# 1. 层间边界逐渐模糊
# 2. 出现绕过分层的"快捷方式"
# 3. 新代码不再遵循架构规范
# 4. 技术债务积累
# 例子:直接数据库查询出现在Controller中
@router.get("/stats")
defget_stats():
# 绕过Service层,直接查询数据库
conn = get_db_connection()
cursor = conn.cursor()
cursor.execute("SELECT COUNT(*) FROM orders")
count = cursor.fetchone()[0]
return {"order_count": count}
# 架构治理的四个支柱:
# 支柱1:架构决策记录(ADR)
classArchitectureDecisionRecord:
"""架构决策记录"""
def__init__(self, title, context, decision, consequences):
self.title = title
self.context = context
self.decision = decision
self.consequences = consequences
self.timestamp = datetime.now()
defto_markdown(self):
"""生成Markdown文档"""
returnf"""
# {self.title}
**日期**: {self.timestamp.strftime('%Y-%m-%d')}
**状态**: 提议/接受/已弃用/已取代
## 背景
{self.context}
## 决策
{self.decision}
## 后果
{self.consequences}
"""
# 示例ADR:
adr_layering = ArchitectureDecisionRecord(
title="采用四层架构",
context="项目规模增长,需要更清晰的职责分离",
decision="采用接口层、应用层、领域层、基础设施层的四层架构",
consequences="提高可维护性,增加初始开发成本"
)
# 支柱2:架构守护(Architecture Guard)
# 使用工具自动检查架构规则
# .archunit.py - 架构规则定义
rules = [
# 规则1:Controller只能导入Service接口
LayerRule()
.layer("controllers")
.may_only_import(
"services.interfaces",
"domain.models",
"shared.exceptions"
),
# 规则2:Service只能导入Repository接口和领域模型
LayerRule()
.layer("services")
.may_only_import(
"repositories.interfaces",
"domain.models",
"domain.services"
),
# 规则3:禁止循环依赖
NoCircularDependenciesRule(),
# 规则4:领域模型不能导入基础设施
DomainModelsRule()
.may_not_import("infrastructure.*")
]
# 支柱3:定期架构复审
classArchitectureReview:
"""架构复审"""
def__init__(self, frequency='monthly'):
self.frequency = frequency
self.metrics = {
'layer_violations': 0,
'cyclic_dependencies': 0,
'god_classes': 0,
'test_coverage': 0.0
}
defconduct_review(self):
"""执行复审"""
# 收集指标
self._collect_metrics()
# 分析问题
issues = self._analyze_issues()
# 制定改进计划
improvement_plan = self._create_improvement_plan(issues)
return {
'metrics': self.metrics,
'issues': issues,
'improvement_plan': improvement_plan
}
def_collect_metrics(self):
"""收集架构指标"""
# 使用静态分析工具
pass
def_analyze_issues(self):
"""分析架构问题"""
return [
{
'type': 'layer_violation',
'description': 'Controller直接导入Repository',
'location': 'controllers/order_controller.py',
'severity': 'high'
}
]
def_create_improvement_plan(self, issues):
"""创建改进计划"""
return [
{
'action': '重构order_controller',
'owner': '张三',
'deadline': '2024-01-31',
'priority': 'P1'
}
]
# 支柱4:架构度量与可视化
classArchitectureMetrics:
"""架构度量"""
defcollect(self):
"""收集架构度量数据"""
return {
'coupling': self._calculate_coupling(),
'cohesion': self._calculate_cohesion(),
'complexity': self._calculate_complexity(),
'testability': self._calculate_testability()
}
defvisualize(self, metrics):
"""可视化架构度量"""
# 生成架构图
# 显示层间依赖
# 高亮违规点
return {
'dependency_graph': generate_dependency_graph(),
'layer_compliance': calculate_layer_compliance(),
'hot_spots': identify_hot_spots()
}
经过对13个常见误区的分析,咱们总结出以下最佳实践清单:
- • 中型项目:四层架构(接口-应用-领域-基础设施)
学习搭子,分层架构是一门实践艺术。没有完美的架构,只有适合当前项目、团队和业务阶段的架构。
- 1. 保持简单:从最简单的可行方案开始,只在需要时增加复杂度
- 2. 持续学习:从每个项目中总结经验,不断改进架构设计
- 3. 务实优先:架构服务于业务,而不是业务服务于架构
希望这份最佳实践总结能帮你在实际项目中避免常见的"坑",设计出既优雅又实用的分层架构。
如果在实践中遇到具体问题,或者想深入讨论某个技术细节,随时告诉我。咱们一起在实践中成长!