美文网首页
DDD核心元素简介

DDD核心元素简介

作者: 吃番茄的土拨鼠 | 来源:发表于2020-03-31 11:17 被阅读0次

分包示例


工程分包实现

以界限上线文为指导核心,总体分为两类 :业务界限上线文,系统界限上下文

系统界限上下文

用于放置: aop切面,通过工具包(utils),共用三方组件(mq,redis,id生成器)

业务界限上下文

按照领域划分,每个领域有一个独立的界限上线文

controller:控制器

又叫北向网关,只能将功能委托applicaton或者 reposity实现,自身只承担数据转换适配

application: 应用服务

对domain server 进行编排,控制事务,发送消息,不实现业务逻辑。需要将功能委托domain或者reposity实现

assembler

用作 DTO和do对象转换,组织网关层的数据对象(DTO,VO)入侵domain层

实例

1:验证展现层的输入
2 :将展现层对象转出领域理解的对象
3 :从reposiory获取领域对象
4: 委托领域对象执行业务处理
5:委托基础设施服务,如发送应用消息或者web调用

domain 领域

  service:领域服务

  1. 一个现实领域动作,但是并不能归属于某个领域对象,它本身可以实现业务逻辑。但是不能窃取领域对象自身的业务逻辑
  2. 领域服务负责动作编排,可以调用多个聚合根,可以调用其它领域对象

如何判断一系列交互是否属于领域
1.这种情况总是出现吗?
2.这些步骤无法分开吗?
如果这些步骤必须一起出现,就不存在’任务编排‘。他们本质上是一个整体,只是因为单一职责和分治原则需要分解,做到各个对象各司其职

  entity 实体

核心业务对象,有唯一标识,有自身的数据和动作。内部的数据完全由自身掌控,不可透传给其它对象。对象的状态完全通过动作来进行驱动

  value 值对象

通过属性而不是ID来标识和区分,是不可变对象

  factory 对象工厂

复杂对象创建

  reposity 仓储

  • 负责持久化数据数据对象

  • 从持久化介质构建领域对象,如果对象负责委托factory进行创建

  • 对于简单数据请求直接返回数据对象(PO)

repoisotry如何注入到domain中? 通过Factory 构建domain对象时设置

聚合根、实体、值对象对象之间如何建立关联

聚合根: 它本身不是具体的存在,它只是标识了一些作为跟对象的实体。就是说如果一个实体维护了一个领域边界,它内部包含了一些实体或者值对象,这个实体是外界访问内部信息的的唯一入口。
聚合要保持不变性

对象本身有一套对自身状态进行校验的检查条件,以确保该对象的本质不发生改变,这称之为不变式

  • 聚合根到聚合根:通过ID关联;
  • 聚合根到其内部的实体,直接对象引用;
  • 聚合根到值对象,直接对象引用;
  • 在一个领域内部,事务可以跨多个聚合根
  • 外部对象可以通过聚合根导航到内部对象的引用,但是他们只能临时引用,不能保持引用

界限上下文交互

  • 网关的对象不能渗透到领域层。如 Request 要使用内部属性或者封装成BO对象domain向内部传递
  • 领域对象不能渗出界限上下文。如 Oder 这个领域对象不能直接返回给 Payment 所属的界限上下文,而是要封装成Respose这样的契约消息

代码示例

 public class OrderController {

        private OrderAppService orderAppService;
        private OrderRepository orderRepository;

        public OrderResp placeOrder(OrderDto orderDto) {
            OrderDo orderDo = BeanUtils.trans(orderDto, OrderDo.class);
            Long orderId = orderAppService.placeOrder(orderDo);
            return new OrderResp(orderId);
        }

        public OrderResp cancel(String orderNo) {
            orderAppService.cancelOrder(orderNo);
            return new OrderResp();
        }

        public OrderResp cancelPayment(Long orderId, Long paymentId) {
            orderAppService.cancelPayment(orderId, paymentId);
            return new OrderResp();
        }


        //直接从repo获取
        public OrderDto getOrderDetailByNo(String orderNo) {
            Order order = orderRepository.findByNo(orderNo);
            return BeanUtils.trans(order, OrderDto.class);
        }

    }

    public class OrderAppService {

        private OrderService orderService;

        private OrderRepository orderRepository;

        private OrderEventBus orderEventBus;


        public Long placeOrder(OrderDo orderDo) {
            Order order = orderService.placeOrder(orderDo);
            orderEventBus.send(new OrderEvent(EventType.PLACE.getCode(), order));
            return order.getId();
        }


        public void cancelOrder(String orderNo) {
            orderService.cancelOrder(orderNo);
            orderEventBus.send(new OrderEvent(EventType.CANCEL.getCode(), orderNo));
        }

        public void cancelPayment(Long orderId, Long paymentId) {
            Order order = orderService.cancelPayment(orderId, paymentId);
            orderEventBus.send(new OrderEvent(EventType.UPDATE.getCode(), order));
        }
    }

    public class OrderService {
        private OrderRepository orderRepository;
        private OrderFactory orderFactory;

        @Transactional(rollbackFor = RuntimeException.class)
        public Order placeOrder(OrderDo orderDo) {
            Order order = orderFactory.buildFromDo(orderDo);
            order.place();
            return order;
        }

        @Transactional(rollbackFor = RuntimeException.class)
        public void cancelOrder(String orderNo) {
            Order order = orderRepository.findByNo(orderNo);
            if (order == null) {
                throw new RuntimeException("订单不存在");
            }
            order.cancel();
        }


        @Transactional(rollbackFor = RuntimeException.class)
        public Order cancelPayment(Long orderId, Long paymentId) {
            Order order = orderRepository.find(orderId);
            if (order == null) {
                throw new RuntimeException("订单不存在");
            }
            order.cancelPayment(paymentId);
            return order;
        }

    }

    @Data
    public class Order {

        private OrderRepository orderRepository;

        public void place() {
            if (this.money <= 0 || this.payments == null) {
                throw new RuntimeException("无效订单");
            }
            if (orderRepository.findByNo(this.orderNo) != null) {
                throw new RuntimeException("重复下单");
            }
            Long orderId = orderRepository.addOrder(this);

            OrderDetail orderDetail = new OrderDetail();
            orderDetail.orderId = orderId;
            orderDetail.money = this.money;
            orderDetail.status = OrderStatus.INIT.getCode();
            orderRepository.addOrderDetail(orderDetail);
        }

        public void cancel() {
            if (this.status != OrderStatus.PAY.getCode()) {
                throw new RuntimeException("订单不能撤销");
            }
            this.status = OrderStatus.CANCELED.getCode();
            orderRepository.update(this);

            OrderDetail orderDetail = new OrderDetail();
            orderDetail.orderId = this.id;
            orderDetail.money = this.money;
            orderDetail.status = OrderStatus.CANCELED.getCode();
            orderRepository.addOrderDetail(orderDetail);


        }

        public void cancelPayment(Long paymentId) {
            Payment payment = payments.stream().filter(x -> x.id.equals(paymentId)).findAny().get();
            payment.cancel();
            this.money = payments.stream().filter(x -> x.status != 1).mapToLong(x -> x.money).sum();

            orderRepository.update(this);
            orderRepository.updatePayment(payment);
        }


        private Long id;
        private String orderNo;
        private Long money;
        private Integer status;
        private List<Payment> payments;


    }

    @Getter
    @AllArgsConstructor
    public enum OrderStatus {
        INIT(1, "未支付"),
        PAYING(2, "支付中"),
        PAY(3, "已支付"),
        CANCELED(4, "已撤销");

        private int code;
        private String desc;
    }

    @Data
    public class OrderDetail {
        private Long id;
        private Long orderId;
        private Long money;
        private Integer status;

    }

    @Data
    public class Payment {

        public void cancel() {
            this.status = 1;
        }

        private Long id;
        private Long money;
        private Integer status;

    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class OrderResp {
        private Long id;
    }


    public class OrderDto {
        private Long id;
        private Long money;
        private List<PaymentDto> paymentDtos;
    }

    public class PaymentDto {
        private Long id;
        private Long money;
        private Integer status;
    }

    public class OrderDo {
        private Long id;
        private Long money;
        private List<PaymentDo> paymentDos;
    }

    public class PaymentDo {
        private Long id;
        private Long money;
        private Integer status;
    }

    public class OrderRepository {
        OrderMapper orderMapper;
        PaymentMapper paymentMapper;
        OrderDetailMapper orderDetailMapper;
        OrderFactory orderFactory;


        private Order find(Long id) {
            OrderPo order = orderMapper.find(id);
            List<PaymentPo> payments = paymentMapper.listByOrderId(id);
            return orderFactory.buildFromPo(order, payments);
        }

        private Order findByNo(String orderNo) {
            OrderPo orderPo = orderMapper.find(orderNo);
            List<PaymentPo> payments = paymentMapper.listByOrderId(orderPo.id);
            return orderFactory.buildFromPo(orderPo, payments);
        }


        void update(Order order) {
            orderMapper.update(null);
        }

        void updatePayment(Payment payment) {
            paymentMapper.updatePayemnt(null);
        }

        Long addOrder(Order order) {
            return orderMapper.insert(null);
        }

        Long addOrderDetail(OrderDetail orderDetail) {
            return orderDetailMapper.insert(orderDetail);
        }
    }

    public class OrderFactory {

        private OrderRepository orderRepository;

        public Order buildFromDo(OrderDo orderDo) {
            Order order = BeanUtils.trans(orderDo, Order.class);
            order.setOrderRepository(orderRepository);
            return order;
        }

        public Order buildFromPo(OrderPo orderPo, List<PaymentPo> paymentPos) {
            Order order = BeanUtils.trans(orderPo, Order.class);
            order.setOrderRepository(orderRepository);
            order.payments = paymentPos.stream().map(x -> {
                Payment payment = BeanUtils.trans(null, Payment.class);
                return payment;
            }).collect(Collectors.toList());
            return order;
        }
    }

    @Getter
    @AllArgsConstructor
    public enum EventType {
        PLACE(1, "下单"),
        CANCEL(2, "撤销"),
        UPDATE(3, "修改订单");
        private int code;
        private String desc;

    }


    @Data
    @AllArgsConstructor
    public class OrderEvent {
        private int type;
        private Object data;
    }

    public class OrderEventBus {

        public void send(OrderEvent event) {

        }
    }

    public interface PaymentMapper {

        List<PaymentPo> listByOrderId(Long orderId);

        int updatePayemnt(PaymentPo payment);

    }

    public interface OrderDetailMapper {

        OrderPo find(Long id);

        Long insert(OrderDetail orderDetail);
    }


    public interface OrderMapper {

        OrderPo find(Long id);

        OrderPo find(String no);

        int update(OrderPo order);

        Long insert(OrderPo order);
    }


    @Data
    public class OrderPo {
        public Long id;
        public long money;
    }

    @Data
    public class PaymentPo {
        public Long id;
        public int status;
        public Long money;
    }

相关文章

  • DDD核心元素简介

    分包示例 以界限上线文为指导核心,总体分为两类 :业务界限上线文,系统界限上下文 系统界限上下文 用于放置: ao...

  • DDD领域驱动设计浅见

    目录 DDD简介DDD是啥DDD能给微服务带来什么不用DDD的常见设计方式DDD整洁架构常见三层架构设计整洁架构D...

  • 领域驱动设计DDD入门(一)

    领域驱动设计简介 领域驱动设计(Domain-Driven Design)简称DDD。 目录 DDD是什么? DD...

  • DDD核心观点

    领域驱动设计并不牵涉到技术层面的实现细节。 ”对一个大型系统,领域模型的完全统一将是不可行的或者不划算的。“ --...

  • DDD概念概览 [0]

    软件的核心,是为其用户解决领域相关问题的能力。 何为DDD DDD是Domain Driven Design的简称...

  • DDD架构

    大型微服务架构下如何解决系统老化问题 DDD架构 如何走出系统老化的循环 DDD核心思想

  • 记浅析开源电商框架《flamingo-commerce》

    简介 框架旨在构建电商系统的完整解决实现,通过DDD领域驱动设计,将抽象出来的具体领域模型实现,在核心域的基础上采...

  • DDD中的模型

    “模型”这个词语在DDD中反复出现,是DDD的核心概念。可是我们从Eric在他的著作(Domain-driven ...

  • 领域驱动设计的DDD简介和工程实践

    领域驱动设计DDD简介 软件负责性与开发周期关系 DDD经典分层 用户界面/展示层:负责向用户展现信息,并且会解析...

  • 结合领域驱动设计的SOA分布式软件架构,你还在为这些烦恼?

    一、SOA与DDD的定义 SOA与DDD都是常用的系统架构,但两者之间所针对的核心是不同的。 SOA(面向服务架构...

网友评论

      本文标题:DDD核心元素简介

      本文链接:https://www.haomeiwen.com/subject/irfwuhtx.html