面向领域编程ddd一

这里有ddd说明,可以先看面向领域编程DDD二它,然后再往后看

public class PaymentController{
    private PayService payService;
    public Result pay(String merchantAccount,BigDecimal amount){
        Long userId = (Long) session.getAttribute("userId");
       return payService.pay(userId, merchantAccount, amount);
    }
}

public class PayServiceImpl extends PayService{
    private AccountDao accountDao;//操作数据库
    private KafkaTemplate<String, String> kafkaTemplate;//操作kafka
    private RiskCheckService riskCheckService;//风控微服务接口
    public Result pay(Long userId,String merchantAccount,BigDecimal amount){
        // 1. 从数据库读取数据
        AccountDO clientDO = accountDAO.selectByUserId(userId);
        AccountDO merchantDO =
        accountDAO.selectByAccountNumber(merchantAccount);
        // 2. 业务参数校验
        if (amount>(clientDO.getAvailable()) {
        	throw new NoMoneyException();
        }
        // 3. 调用风控微服务
        RiskCode riskCode = riskCheckService.checkPayment(...);
        // 4. 检查交易合法性
        if("0000"!= riskCode){
            throw new InvalideOperException();
        }
        // 5. 计算新值,并且更新字段
        BigDecimal newSource = clientDO.getAvailable().subtract(amount);
        BigDecimal newTarget = merchantDO.getAvailable().add(amount);
        clientDO.setAvailable(newSource);
        merchantDO.setAvailable(newTarget);
        // 6. 更新到数据库
        accountDAO.update(clientDO);
        accountDAO.update(merchantDO);
        // 7. 发送审计消息
        String message = sourceUserId + "," + targetAccountNumber + "," + targetAmount;
        kafkaTemplate.send(TOPIC_AUDIT_LOG, message);
        return Result.SUCCESS;
    }
}`

上面的代码是一个简单的mvc代码这样的代码 就会有一个问题 第一版本可以会很成功但是 如果在这基础上编写二期三期。。那么这里就会变的很庞大 也不敢删维护起来很麻烦 测试也不好测比如专门测试风控微服务 这样就会要把其他的逻辑都测一遍 如果单独开一个接口也会有很多问题比如两个方法的数据不一样 上面的代码还是一个很简单的代码 要是现实的业务代码会更加复杂 短期项目这样写也是没问题主要就是长期的项目 然后就有人提出的ddd的架构模式 ddd称为面向领域编程

ddd设计模式 仓库模式

public interface AccountRepository {
    .......
}
public class AccountRepositoryImpl implements AccountRepository {
    @Autowired
    private AccountDao accountDAO;
    @Autowired
    private AccountBuilder accountBuilder;
    @Override
    public Account find(Long id) {
    	AccountDO accountDO = accountDAO.selectById(id);
    	return accountBuilder.toAccount(accountDO);
    }
    @Override
    public Account find(Long accountNumber) {
    	AccountDO accountDO = accountDAO.selectByAccountNumber(accountNumber);
    	return accountBuilder.toAccount(accountDO);
    }
    @Override
    public Account save(Account account) {
	    AccountDO accountDO = accountBuilder.fromAccount(account);
        if (accountDO.getId() == null) {
        	accountDAO.insert(accountDO);
        } else {
        	accountDAO.update(accountDO);
        }
    return accountBuilder.toAccount(accountDO);
}
public class Account{
    private Long id;
    private Long accountNumber;
    private BigDecimal available;
    
    public void withdraw(BigDecimal money){
        //转入操作
        available = available + money;
    }
    public void deposit(BigDecimal money){
        //转出操作
        if(available < money){
            throws new InsufficientMoneyException();
        }
        available = available - money;
    }
}

之前都是定义一个跟数据库的字段名相同的一个类作为实体类 现在不提供get set方法写一个仓库 在仓库里把实体类拼接起来

防腐层 隔离外部服务

public interface BusiSafeService{
    .......
}
public class BusiSafeServiceImpl implements BusiSafeService{
    @Autowired
    private RiskChkService riskChkService;
    
    public Result checkBusi(Long userId,Long mechantAccount,BigDecimal money){
        //参数封装
        RiskCode riskCode = riskCheckService.checkPayment(...);
        if("0000".equals(reskCode.getCode()){
            return Result.SUCCESS;
        }
        return Result.REJECT;
    }
}

隔离外部服务就是封装一个返回类型 如果你换了返回类型实现接口重写方法即可不会影响业务

防腐层 隔离第三方组件

public class AuditMessage{
    private Long UserId;
    private Long clientAccount;
    private Long merchantAccount;
    private BigDecimal money;
    private Date data;
    .....
} 
public interface AuditMessageProducer{
    ....
}
public class AuditMessageProducerImpl implements AuditMessageProducer{
    private KafkaTemplate<String,String> kafkaTemplate;
    public SendResult send(AuditMessage message){
        String messageBody = message.getBody();
        kafkaTemplate.send("some topic",messageBody);
        return SendResult.SUCCESS;
    }
}

就是如果你换了中间件 继承接口实现它的方法 不用更改业务代码

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值