COLA开发流程总结

COLA开发流程总结

COLA发起者的博客
COLA是一套用于帮助你实践DDD落地的项目架构,在开发COLA之前,我们先再熟悉一下基于COLA创建的项目的结构:

image.png

demo-client:

  • api:存放的是对外暴露的接口
  • dto.domainmodel:用来做数据传输的轻量级领域对象。
  • to.domainevent: 用来做数据传输的领域事件。

demo-app:

  • service:接口实现的facade,没有业务逻辑,可以包含对不同终端的adapter。
  • eventhandler:处理领域事件,包括本域的和外域的。
  • executor:用来处理命令(Command)和查询(Query),对复杂业务,可以包含Phase和Step
  • interceptor: COLA提供的对所有请求的AOP处理机制。
  • validator:用来对传入的命令进行参数校验。

demo-domain:

  • domain:领域实体。
  • domainservice: 领域服务,用来提供更粗粒度的领域能力。
  • gateway:对外依赖的网关接口,包括存储、RPC、Search等,可以认为是对infrastructure的依赖反转。

demo-infrastructure:

  • config:配置信息相关
  • message:消息处理相关。
  • repository:存储相关,是gateway的特化,主要用来做本域的数据CRUD操作。
  • gateway:对外依赖的网关接口(demo-domain里的gateway)的实现。

除此之外,我们还要熟悉一下COLA中关于命名的规范:

命名规范

在COLA架构中,我们也能找到以前熟悉的VO,DTO等对象,只不过在COLA中他们的后缀名变了:

  • VO->CO,COLA中CO对象用于展示给前端。
  • DTO->Cmd,COLA中Cmd对象用于前端和后端的数据交互。
  • Entiry->DO,数据持久化对象。

此外,对于领域对象domain,比如UserDomain,我们在COLA中称之为UserE。

如何基于COLA架构实现一个CRUD

在COLA中,比如我们想创建一个User,一套完整的调用链大概如下图所示:

COLA调用链

以上是一个经过简化版的调用链,实际的调用链还要更复杂,调用过程中可能还包含了多个不同的扩展点(Extension)

查询

假设我们存在一个名叫组织的实体Organization,我们想实现一个根据主键查询的功能,按照COLA的规范,我们应该现在client中创建对应的接口,比如是OrganizationResource

client:

public interface OrganizationResource {
    /**
     * 根据id查找
     * @param id
     * @return
     */
    @GetMapping(value = "/org/{id}")
    DataResponse<OrganizationCO> get(@PathVariable(value = "id")String id);
}

application:

@RestController
public class OrganizationController implements OrganizationResource {
    /**
     * 根据id查找
     * @param id
     * @return
     */
    @Override
    public DataResponse<OrganizationCO> get(String id) {
        // 不再使用传统的service做业务查询,将查询的逻辑封装到了对应的领域对象中
        OrganizationE org = OrganizationE.of().id(id);
        return org != null ? DataResponse.of(org.convertToClient())
                : DataResponse.buildFailure(BasicCode.DB_QUERY_NO_RESULT);
    }
}    

domain:

public class OrganizationE {
    public static OrganizationE of() {
        return new OrganizationE();
    }
    
    public OrganizationE id(String id) {
        return getOrganizationGateway().getById(id);
    }
    /**
     * 从对应的gateway中获取实现
    **/
    private OrganizationGateway getOrganizationGateway() {
        if(this.organizationGateway == null) {
            this.organizationGateway = SpringContextUtil.getBean(OrganizationGateway.class);
        }
        return this.organizationGateway;
    }
}

repostitory:

@Component
public class OrganizationRepository extends RepositorySupport<OrganizationMapper, OrganizationDO> implements OrganizationGateway {
    public OrganizationE getById(String id) {
        OrganizationDO dataObject = super.getById(id);
        return BeanMapper.INSTANCE.copy(dataObject, OrganizationE.class);
    }
}
新增

client:

创建对应的command

注意:command类必须继承cola提供的Command,否则CommandBus无法发送这些消息给对应的Service处理

@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
public class OrganizationCreateCmd extends Command {
    /**
     * 名称
     */
    @NotBlank
    private String name;
    /**
     * 编号,如果没指定,会根据不同的名称生成不同的编号,比如liSi会生成1001,zhangSan会生成2001
     */
    private String code;
}

application:

@RestController
public class OrganizationController implements OrganizationResource {
    
    @Autowired
    private OrganizationService orgService;
    
    /**
     * 自定义创建cust1
     * @return
     */
    @PostMapping(value = "/org/cust1/create")
    Response createCust1(@RequestBody OrganizationCreateCmd cmd) {
        cmd.setBizScenario(BizScenario.valueOf(BizScenarioConstant.BIZ_ID.CUST1));
        return orgService.create(cmd);
    }

    /**
     * 自定义创建cust2
     * @return
     */
    @PostMapping(value = "/org/cust2/create")
    Response createCust2(@RequestBody OrganizationCreateCmd cmd) {
        cmd.setBizScenario(BizScenario.valueOf(BizScenarioConstant.BIZ_ID.CUST2));
        return orgService.create(cmd);
    }
}

service

@Service
public class OrganizationService {
    // 注入COLA提供的command bus
    @Autowired
    private CommandBusI cmdBus;

    /**
     * 创建组织
     * 有两个不同的扩展实现,分别会创建编号为1001和2001的组织信息
     * @param cmd
     * @return
     */
    public Response create(OrganizationCreateCmd cmd) {
        return cmdBus.send(cmd);
    }
}

extension(扩展点)

public interface OrganizationCreateExtPt extends ExtensionPointI {
    /**
     * 组织创建的扩展点
     * @param cmd
     * @return
     */
    OrganizationE extension(OrganizationCreateCmd cmd);
}

扩展点实现

@Extension(bizId = BizScenarioConstant.BIZ_ID.CUST1)
public class Cust1OrganizationCreateExt implements OrganizationCreateExtPt {
    /**
     * 组织创建的扩展点,根据不同的请求赋予不同的编号
     * @param cmd
     * @return
     */
    @Override
    public OrganizationE extension(OrganizationCreateCmd cmd) {
        // 如果是cust1 赋予1001
        return OrganizationE.of(cmd).setCode("1001");
    }
}
@Extension(bizId = BizScenarioConstant.BIZ_ID.CUST2)
public class Cust2OrganizationCreateExt implements OrganizationCreateExtPt {
    /**
     * 组织创建的扩展点,根据不同的请求赋予不同的编号
     * @param cmd
     * @return
     */
    @Override
    public OrganizationE extension(OrganizationCreateCmd cmd) {
        // 如果是cust2 赋予2001
        return OrganizationE.of(cmd).setCode("2001");
    }
}

扩展点执行器

@Command
public class OrganizationCreateCmdExe implements CommandExecutorI<Response, OrganizationCreateCmd> {
    /**
     * 参数校验器
     */
    @Autowired
    private OrganizationCreateValidator validator;

    /**
     * 扩展执行器
     */
    @Autowired
    private ExtensionExecutor executor;

    @Override
    public Response execute(OrganizationCreateCmd cmd) {
        // 执行校验扩展
        executor.executeVoid(OrganizationCreateValidatorExtPt.class,
                cmd.getBizScenario(), exe-> exe.validate(cmd));

        // 执行扩展逻辑
        OrganizationE org = executor.execute(OrganizationCreateExtPt.class,
                cmd.getBizScenario(), exe -> exe.extension(cmd));
        
        // 调用领域对象的create方法
        org.create();
        
        return Response.buildSuccess();
    }
}

domain

public class OrganizationE {
    public OrganizationE create() {
        if(!getOrganizationGateway().create(this)) {
            throw new DBSaveFailedException();
        }
        return this;
    }
}

repository

@Component
public class OrganizationRepository extends RepositorySupport<OrganizationMapper, OrganizationDO> implements OrganizationGateway {

    @Transactional
    public boolean create(OrganizationE organization) {
        OrganizationDO dataObject = BeanMapper.INSTANCE.copy(organization, OrganizationDO.class);
        return super.save(dataObject);
    }
}
  • 6
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值