DDD 入门指南:从贫血模型到领域驱动是系统设计的核心,它决定了系统的可扩展性、可靠性和可维护性。
本文介绍了DDD 入门指南:从贫血模型到领域驱动的设计原则和实践经验,帮助你提升架构设计能力。
假设我们正在开发一个担保业务系统,有一个"客户申请授信额度"的功能。按照传统的三层架构,代码大致是这样的:
// Controller 层
@RestController
@RequestMapping("/api/credit")
public class CreditController {
@Autowired
private CreditService creditService;
@PostMapping("/apply")
public Result<CreditApplyResponse> apply(@RequestBody CreditApplyRequest request) {
return Result.success(creditService.apply(request));
}
}
// Service 层
@Service
public class CreditService {
@Autowired
private CustomerMapper customerMapper;
@Autowired
private CreditRecordMapper creditRecordMapper;
@Autowired
private RiskEngineClient riskEngineClient;
@Transactional
public CreditApplyResponse apply(CreditApplyRequest request) {
// 1. 查询客户信息
CustomerDO customer = customerMapper.selectById(request.getCustomerId());
if (customer == null) {
throw new BusinessException("客户不存在");
}
// 2. 校验客户状态
if (!"ACTIVE".equals(customer.getStatus())) {
throw new BusinessException("客户状态异常,无法申请授信");
}
// 3. 校验是否已有有效授信
CreditRecordDO existingCredit = creditRecordMapper
.selectByCustomerId(request.getCustomerId());
if (existingCredit != null && "VALID".equals(existingCredit.getStatus())) {
throw new BusinessException("已存在有效授信,无需重复申请");
}
// 4. 调用风控引擎
RiskResult riskResult = riskEngineClient.evaluate(buildRiskRequest(customer));
if (!riskResult.isPassed()) {
CreditRecordDO failedRecord = new CreditRecordDO();
failedRecord.setCustomerId(request.getCustomerId());
failedRecord.setStatus("REJECTED");
failedRecord.setRejectReason(riskResult.getReason());
failedRecord.setCreateTime(new Date());
creditRecordMapper.insert(failedRecord);
return CreditApplyResponse.rejected(riskResult.getReason());
}
// 5. 计算授信额度
BigDecimal creditAmount = calculateCreditAmount(customer, riskResult);
// 6. 保存授信记录
CreditRecordDO record = new CreditRecordDO();
record.setCustomerId(request.getCustomerId());
record.setCreditAmount(creditAmount);
record.setStatus("VALID");
record.setEffectiveDate(new Date());
record.setExpireDate(calculateExpireDate());
record.setCreateTime(new Date());
creditRecordMapper.insert(record);
return CreditApplyResponse.success(creditAmount);
}
private BigDecimal calculateCreditAmount(CustomerDO customer, RiskResult riskResult) {
BigDecimal baseAmount = customer.getAnnualIncome()
.multiply(new BigDecimal("0.5"));
BigDecimal adjustedAmount = baseAmount
.multiply(riskResult.getCreditMultiplier());
return adjustedAmount.min(new BigDecimal("500000"));
}
}
// 数据对象(贫血模型)
@Data
@TableName("t_customer")
public class CustomerDO {
private Long id;
private String name;
private String idCard;
private String phone;
private String status;
private BigDecimal annualIncome;
private String companyName;
private Date createTime;
private Date updateTime;
}
@Data
@TableName("t_credit_record")
public class CreditRecordDO {
private Long id;
private Long customerId;
private BigDecimal creditAmount;
private String status;
private String rejectReason;
private Date effectiveDate;
private Date expireDate;
private Date createTime;
}
2026/6/11大约 26 分钟