DDD领域驱动设计(DP、Entity介绍;DDD实现流程;DDD聚合Aggregate;限界上下文(Bounded Context))

DDD(Domain Driven Design)

DP(Domain Primitive)

define:

一切模型、方法、架构的基础,是指在特定领域、拥有精准定义、可以自我验证、拥有行为的对象,可以认为是领域的最小组成部分

三条原则:

  1. 让隐性的概念显性化
  2. 让隐性的上下文显性化
  3. 封装多对象行为

Entity

  • DP: 抽象并封装自检和一些隐性属性的计算逻辑,且这些逻辑是无状态的

  • Entity: 抽象并封装单对象有状态的逻辑

  • Domain Service: 抽象并封装多对象的有状态逻辑

  • Repository: 抽象并封装外部数据访问逻辑

流程

  1. 首先对需要处理的业务问题进行总览
  2. 然后领域对象(Entity)进行划分,明确每个领域对象的包含的信息和职责边界,并进行跨对象、多对象的逻辑组织(Domain Serivice)
  3. 接着在上层应用中根据业务描述去编排Entity和Domain Service
  4. 最后进行一些下水道工作,对下层数据进行访问、RPC调用等一些具体实现

聚合(DDD-Aggregate)

define:

  • 边界

使用:

  • 运行时->domain service
  • 持久化->repository

eg.

//标识符接口
public interface Identifier extends Serializable{}
//聚合根接口,实现此接口即为该边界内的聚合根
public interface AggregateRoot<T extends Identifier > extends Entity<T>{}
//实体类接口,实现此接口即为该边界内与聚合根关联的实体,此实体标识符为类型T
public interface Entity<T extends Identifier>{}

//以下为示例					
						————————————————————————————————————————————————————
domain service----------->|												  |
    					|	账号(根对象)----------->钱包----------->余额	     |
    repository----------->|												  |
					 	————————————————————————————————————————————————————					
//定义电话号码为聚合根对外接口
public class PhoneNumber implements Identifier{}
//定义聚合根实体类微信账户
public class WechatAccount implements AggregateRoot<PhoneNumber>{
    //防止通过new构造对象,以使用工厂创建符合标准的对象
    private WechatAccount(){}
    private PhoneNumber id;
    private NickName nickName;
    private Wallet wallet;
    // ...
    public void withdraw(Asset asset){
        Wallet.pay(asset);
    }
    public void deposit(Asset asset){
        wallet.receive(asset);
    }
}
//定义聚合根关联类微信钱包
public class Wallet implements Entity<WalletNumber>{
    //防止通过new构造对象,以使用工厂创建符合标准的对象
    private Wallet(){}
    private WalletNumber id;
    private Balance balance;
    private Statement statement;
    // ...
    public void pay(Asset asset) throws BalanceException{
        balance.decrease(asset.getBanlance);
        statement.add(asset);
    }
    public void receive(Asset asset) throws BalanceException{
        balance.increase(asset.getBanlance);
        statement.add(asset);
    }
}
//定义聚合根关联类微信钱包的关联类余额
public class Balance implements Entity<BalanceNumber>{
    //防止通过new构造对象,以使用工厂创建符合标准的对象
    private Balance(){}
    private BalanceNumber id;
    // ...
}

//定义Repository接口,其传递对象为聚合根
public interface Repository<T extends AggregateRoot<ID>, ID extends Identifier>{
    void save(T t);
    T find(ID id);
}
//定义AccountRepository接口,其传递对象为聚合根WechatAccount及其标识符PhoneNumber
public interface AccountRepository extends Repository<WechatAccount, PhoneNumber>{
    void save(WechatAccount wechatAccount);
    WechatAccount find(PhoneNumber id);
}
public class AccountRepositoryImpl implements AccountRepository{
    private WechatAccountDAO wechatAccountDAO;
    private WalletDAO walletDAO;
    private BalanceDAO balanceDAO;
    private StatementDAO statementDAO;
    @Override
    public void save(WechatAccount wechatAccount){
        var wechatAccountPO = WechatAccountConverter.convert(wechatAccount);
        wechatAccountDAO.save(wechatAccountPO);
        //以下逻辑仍可优化
        //即change tracking问题
        var wallet = WalletFactory.obtain(wechatAccount);
        var walletPO = WalletConverter.convert(wallet);
        walletDAO.save(walletPO);
        
        var balance = BalanceFactory.obtain(wallet);
        var balancePO = BalanceConverter.convert(balance);
        balanceDAO.save(balancePO);
        
        var statement = StatementFactory.obtain(wallet);
        var statementPO = StatementConverter.convert(wallet);
        statementDAO.save(statementPO);
        // ...
    }
    public WechatAccount find(PhoneNumber id){
        // ...
    }
}

//定义具体对外的服务接口TransferService
public interface TransferService{
    void transfer(WechatAccount payer, WechatAccount payee, Asset asset);
}
//实现接口TransferService,操作entity
public class TransferServiceImpl implements TransferService{
    public AccountRepository repository;
    @Override
    public void transfer(WechatAccount payer, WechatAccount payee, Asset asset){
        payer.withdraw(asset);
        payee.deposit(asset);
        repository.save(payer);
        repository.save(payee);
    }
}

限界上下文(Bounded Context)

define:

上下文(Context)是业务目标,

限界(Bounded)则是保护和隔离上下文的边界,

使用BC目的是避免业务目标的不单一而带来的混乱与概念的不一致

特性:

  1. 最小完备(自身的职责 不需要与其他上下文相耦合)
  2. 自我履行(判断 职责是术语本单元 还是别的上下文所在单元 划分边界)
  3. 稳定空间(通过隐藏细节和开放抽象接口来封装变化)
  4. 独立进化(约束接口的规范与版本)

你可能感兴趣的:(架构,后端,java)