Files
DDDMicroFrontend/doc/杂项.md
2025-09-16 22:08:45 +08:00

98 lines
3.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

### 横切关注点
- 特征:横向,影响多个模块,那些无法放入任何一个业务模块,而是会"横着"贯穿多个甚至所有模块的技术性需求。
- 案例:日志记录、身份认证、授权、事务管理、异常处理、缓存、性能监控
## 业务关注点
- 特征:通常局限于一个业务模块内
- 案例:计算订单总额、验证用户邮箱格式、处理库存扣减
### 对象职责的设计理念对比:
#### 贫血模型
- 特征:对象仅仅是数据的容器(一堆属性的集合),没有任何业务逻辑。所有操作这些数据的逻辑都放在外部的“服务”或“工具”类中。
- 比喻:像一个没有灵魂的空壳,或者一个数据结构。它只负责装数据,至于数据怎么用、怎么变,它不管。
```typescript
// 1. 贫血的Order实体只有数据没有行为
class Order {
public id: string;
public items: OrderItem[];
public total: number; // 总额需要外部来计算和设置
public status: string;
}
// 2. 所有业务逻辑都在外部的“服务”里
class OrderService {
calculateTotal(order: Order): void {
let total = 0;
for (const item of order.items) {
total += item.price * item.quantity;
}
order.total = total; // 从外部修改对象的数据
}
markAsPaid(order: Order): void {
if (order.total <= 0) {
throw new Error('订单金额无效');
}
order.status = 'paid'; // 从外部修改对象的状态
}
}
// 使用方式
const order = new Order();
order.items = [...];
const orderService = new OrderService();
orderService.calculateTotal(order); // 服务来算总额
orderService.markAsPaid(order); // 服务来改状态
```
#### 充血模型
- 特征:对象不仅包含数据,还包含与这些数据紧密相关的业务逻辑。它是有行为和责任的。
- 比喻:像一个有智慧的专家。它不仅拥有数据,还知道如何操作和处理自己的数据。
```typescript
// 充血的Order实体数据 + 行为
class Order {
public id: string;
private _items: OrderItem[];
private _total: number; // 总额是内部计算的结果
public status: string;
constructor(items: OrderItem[]) {
this._items = items;
this._total = this.calculateTotal(); // 构造时自己计算总额
this.status = 'created';
}
// 业务逻辑封装在实体内部
private calculateTotal(): number {
return this._items.reduce((sum, item) => sum + (item.price * item.quantity), 0);
}
// 一个公开的业务方法
public markAsPaid(): void {
// 它自己 knows 自己的业务规则
if (this._total <= 0) {
throw new Error('订单金额无效,无法支付');
}
this.status = 'paid';
}
// 提供访问内部数据的方法(如果需要)
get total(): number {
return this._total;
}
get items(): ReadonlyArray<OrderItem> {
return [...this._items]; // 返回副本,保护内部数据
}
}
// 使用方式:对象是聪明的,告诉它做什么就行,而不是一步步操作它
const order = new Order([...]);
order.markAsPaid(); // 对象自己处理状态变更
```