范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

后微服务时代,领域驱动设计在携程国际火车票的实践

  一、前言
  领域驱动设计(Domain-Driven Design,简称 DDD)是一种软件开发设计思想,其旨在以领域为核心,让软件系统在实现时准确地基于对真实业务过程的建模,专注于业务问题域的需要。
  DDD将软件系统设计分为了2个部分:战略设计和战术设计,战略设计用于提炼问题域并塑造应用程序的架构,战术设计用于帮助创建用于复杂有界上下文的有效模型。基于此,DDD强调专注于核心领域,通过协作对公共语言和知识进行提炼,并且持续致力于领域的知识提炼,让模型持续发展。
  本文基于DDD思想,在携程国际火车票中台预订系统项目进行实践。二、实践背景
  本文以国际火车票中台预订系统项目的创单流程为例,其服务结构下图所示:
  伪代码如下所示:@Override protected CreateOrderResponse execute(CreateOrderRequest request) {     // 1、参数校验     if (!validate(request)) {         throw new BusinessException(P2pBookingResultCode.PARAM);     }     if (orderMapper.select(request.getOrderId()) != null) {         throw new BusinessException(P2pBookingResultCode.ORDER_EXISTS);     }          // 2、初始化订单     OrderDao orderDao = new OrderDao();     orderDao.setOrderId(request.getOrderId());     orderDao.setOrderStatus(100);     orderMapper.insert(orderDao);     // 初始化乘客信息     PassengerDao passengerDao = new PassengerDao();     ...     passengerMapper.insert(passengerDao);          // 3、转换汇率     ExchangeRate exchangeRate = exchangeService.getExchangeRate(originCurrency, targetCurrency);          // 4、购买保险     if (isBuyInsurance(request)) {         // 调用保险服务         InsuranceInfo insuranceInfo = insuranceService.buyInsurance(request);         // 保存保险信息         InsuranceDao insuranceDao = new InsuranceDao();         ...         insuranceMapper.insert(insuranceDao);     }          // 5、供应商创单     SupplierOrder supplierOrder = supplierService.createOrder(request, exchangeRate);     // 保存供应商订单信息     SupplierOrderDao supplierOrderDao = new SupplierOrderDao();     ...     supplierOrderMapper.insert(SupplierOrderDao);          // 6、保存订单信息     orderDao = new orderDao();     orderDao.setOrderId(request.getOrderId);     orderDao.setOrderStatus(OrderStatusEnum.WAIT_FOR_PAY.getCode());     ...     orderMapper.update(orderDao);          // 7、发送超时支付取消消息     messageProducer.push(MessageQueueConstants.TOPIC_TIMEOUT_CANCEL, "orderId", String.valueOf(orderDao.getOrderId()), appSettingProp.getTimeoutMinutes(), TimeUnit.MINUTES);          // 8、返回结果     return mappingResponse(orderDao, orderInsuranceEntity, exchangeRateResponse); }
  2.1 控制层臃肿
  在传统的互联网软件架构中,通常都会采用MVC三层架构,其是一种古老且经典的软件设计模式,基于分层架构的思想,将整个程序分为了Model、View和Controller三层:Model(模型层):最底下一层,是核心的数据,也就是程序需要操作的数据或信息;View(视图层):最上面一层,直接面向最终用户的视图,它是提供给用户的操作界面,是程序的外壳;Controller(控制层):中间的一层,就是整个程序的逻辑控制核心,它负责根据视图层输入的指令选取数据层的数据,然后对其进行相应操作产生最终结果;
  MVC三层架构模式,将软件架构分为了三层,就可以让软件实现模块化,使三层相互独立,修改外观或者变更数据都不需要修改其他层,方便了维护和升级。但是这种软件架构中模型层只关注数据,控制层只关注行为,随着迭代的不断演化,业务逻辑越来越复杂,便会导致整个控制层的代码量越来越多,而模型层和视图层的变更却很少,最终导致整个控制层变得十分臃肿,从而失去了分层的意义。
  2.2 过度耦合
  在业务初期,程序的功能都非常简单,此时系统结构逻辑是清晰的,但是随着程序的不断迭代,一方面会导致业务逻辑越来越复杂,系统逐渐冗余,模块之间彼此关联,软件架构设计模式逐渐向"大泥球"模式(BBoM,Big Ball of Mud)发展;另一方面系统会调用越来越多的第三方服务,从而导致数据格式不兼容,业务逻辑无法复用。
  在出票系统中,除了订单相关的功能外,还包括了保险、汇率、供应商订单等多个服务接口,同时包括保险、供应商订单、乘客等多个模块的功能及存储均耦合在出票流程的控制层中,使得我们在维护代码时,修改一个模块的功能可能会影响到其他功能模块。
  另一方面,如汇率服务这种第三方接口也会存在结构不稳定的情况,当其API签名发生变化或者服务不可靠需要寻找其他可替代的服务时,整个核心逻辑都会随之更改,迁移成本也是巨大的。
  2.3 失血模型
  失血模型是指领域对象里只有get和set方法的POJO,所有业务逻辑都不包含在内而是放在控制层中,该模型对象的缺点就是不够面向对象,对象只是数据的载体,几乎只做传输介质之用,它是没有生命、没有行为的。
  与失血模型相对应的就是充血模型,充血模型就是会包含此领域相关的业务逻辑等,同时也可以包含持久化操作,它的优点对象自洽程度很高,表达能力很强,可复用性很高,更加符合面向对象的思想。
  对于创单流程中的对象几乎都是使用的失血模型,虽然可以完成功能的实现,但是在系统逐渐迭代,业务逻辑逐渐复杂后,采用失血模型会导致业务逻辑。状态散落在大量的方法中,使得代码的意图渐渐不够明确,代码的复用性下降。三、DDD设计
  通过上文的背景介绍,我们基于DDD思想对携程国际火车票中台预订系统做出了一定的重构,使系统实现高内聚、低耦合。
  3.1 系统设计
  Evic Evans将软件系统的设计分为2个部分:战略设计和战术设计。战略设计提出了域、子域、限界上下文等概念,主要用于指导我们如何拆分一个复杂的系统,战术设计提出了实体、值对象、聚合、工厂、仓储。领域事件等概念,主要用于指导我们对于拆分出来的单个域如何进行落地,以及落地过程中需要遵循的原则。
  3.1.1 战略设计
  通用语言
  对于国际火车票中台预定系统,我们定义了预定的通用语言:通过用户搜索条件调用供应商下单;记录供应商相关数据用于财务统计;根据用户选定币种做汇率转换;根据用户选择购买保险;
  领域
  在通过软件实现一个业务系统时,建立一个领域模型是非常重要和必要的。因为领域模型是整个软件的核心,其是对某个边界的领域的一个抽象,反映了领域内用户业务需求的本质,开发者便可以仅关注领域边界内所需关注的部分。同时领域对象与技术实现无关,仅反映业务,领域模型贯穿软件分析、设计,以及开发的整个过程。领域专家、设计人员、开发人员通过领域模型进行交流,彼此共享知识与信息。因为大家面向的都是同一个模型,所以可以防止需求走样,可以让软件设计开发人员做出来的软件真正满足需求。
  基于此,我们将预定系统划分为了对客订单和对供应商订单两个子域,对客订单负责处理客户需要,对供应商订单负责记录供应商侧的相关数据用于财务统计。
  限界上下文
  划分限界上下文主要是想传达一种领域设计的思考方式,通过建模来划分清楚业务领域的边界,划分关系如下所示:
  在上图左侧的PS代表合作关系(Partner Ship),右侧的ACL表示防腐层(Anticorruption Layer),即右侧几个上下文均是外部领域,需要通过防腐层来转换交互,以隔离业务。
  3.1.2 战术设计
  上文提到的失血模型,绝大多数来自于数据库的Dao对象,因为Dao对象仅仅是数据库结构的映射,没有包含业务逻辑,这样就会导致业务逻辑、校验逻辑散落在各个service层,不易维护。为了解决这个问题,DDD将领域模型与数据模型做了区分,前者用于内聚自身行为,后者用于业务数据的持久化,仓储就是用来链接这两层的对象,数据模型又可以分为实体和值对象。
  实体
  实体(Entity)是指领域中可以由唯一标识进行区分的,且具有生命周期的对象,例如上文中的订单就是一个实体,其可以通过订单号进行唯一标识,且订单在整个预定系统中状态会发生改变。
  值对象
  值对象(Value Object)是指没有唯一标识的对象,也就是我们不需要关心对象是哪个,只需要关心对象是什么,例如上文中的行程上下文,故我们不能提供其set方法,行程如果需要改变应该整个对象更新掉。
  聚合根
  聚合(Aggregate)是指通过定义对象之间清晰的所属关系和边界来实现领域模型的内聚,并避免了错综复杂的难以维护的对象关系网的形成。聚合是一组相关对象的集合,每个聚合有一个根和边界,聚合根(Aggregate Root)是这个聚合的根节点,其必须是一个实体,边界定义了聚合内部有哪些实体或值对象。聚合内部的对象可以相互引用,对外通过聚合根进行交互。
  仓储
  仓储(repository)就是对领域的存储和访问进行统一管理的对象,聚合根被创建出来后进行持久化都需要跟数据库打交道,这样我们就需要一个类似数据库访问层的东西来管理领域对象。
  3.2 架构设计
  DDD有多种分层架构模式,包括四层架构模式、五层架构模式、六层架构模式等,其核心均是定义一层领域层对领域对象及其关系进行建模,从传统的MVC三层架构中将领域抽出,但是依然是高层组件依赖低层组件,不同层次之间的耦合无法消除,故本文采用的是一种改进的分层架构模型:六边形架构,其结构如下所示:
  六边形架构采用依赖倒置原则优化了传统的分层架构,低层组件应该依赖于高层组件提供的接口,即无论高层还是低层都依赖于抽象,这样使得整个架构变平。六边形中每条不同的边代表了不同类型的端口,端口要么处理输入,要么处理输出,这样就将外界与系统内部进行了隔离,对于每种外部类型,都需要一个适配器与之对应。
  六边形架构的最大特点就是将技术与业务进行分离,六边形内部核心就是领域模型及不同领域的逻辑编排,领域模型外部的基础设施层就是为领域模型提供技术实现以及外部系统的适配,因为技术选型在项目之初就已经选定完成并且随着项目迭代也很少会发生更改,所以业务人员可以将更多的精力放在领域模型的更新上面。
  如上文介绍的三方接口结构不稳定情况,也可以通过适配器转化为内部模型,防止修改成本过高。同时,对于外部请求,无论是通过rpc,REST、HTTP还是通过MQ等方式,均可通过适配器对输入进行转化,控制权由此交给内部区域进行处理。同时,上文战术设计中的仓储(repository)的实现也可以看作是持久化适配器,该适配器用于访问先前存储的聚合实例或者保存新的聚合实例,我们可以通过不同方式实现仓储适配器,如MySQL、Redis等。四、DDD实现
  通过上文分析,本文以国际火车票中台预订系统项目作为DDD实践落地。
  4.1 项目架构
  根据DDD六边形架构原理,系统架构如上图所示,总共分为了4层:gateway:项目入口,其中包括rpc、mq等不同入口;infrastructure:基础设施层,一方面用作防腐,提供不同入口、出口的适配,另一方面实现领域层的接口提供技术实现;application:应用层,用于逻辑编排、管理、调度,突出核心逻辑,尽可能轻薄;domain:领域层,定义领域模型,对领域模型进行建模;
  4.2 领域对象
  前文提到DDD要解决的一个重要问题就是对象的失血问题,即对象不能仅作为数据的载体而没有行为,如上文代码中的参数校验应该是其自身的行为而非外部进行校验,通过适配器转换为内部对象就可以完成自身参数校验的行为,代码如下所示:public class CreateOrderRequest extends CommonRequest {      private List outSolutionOfferPairList;     private List returnSolutionOfferPairList;     private String transactionNo;     ...     private Contact contact;     private List passengerInfoList;     private boolean isSplitOrder;     private boolean randomAssigned;     private List extraInfos;      @Override     public void requestCheck() {         if (StringUtils.isEmpty(splitPlanId) && CollectionUtil.isEmpty(outSolutionOfferPairList)) {             throw new BusinessException(ResponseCodeEnum.PARAM_ERROR);         }         ...     } }
  4.3 战术设计实现
  本文以订单聚合根为例具体说明战术设计的实现。
  聚合根
  聚合根中包含了实体和值对象,同时聚合根与仅有getter、setter的业务对象不同,其将业务逻辑也封装在内,提高了内聚性,同时将仓储封装在内,为聚合根提供持久化操作。public class P2pOrder {      private P2pOrderRepository repository;      @Getter     private long orderId;     @Getter     private OrderMasterModel orderMasterModel;     @Getter     private List orderItemModels;      public P2pOrder(P2pOrderRepository repository, long orderId) {         this.repository = repository;         this.orderId = orderId;         orderInfoModel = new OrderInfoModel();         orderItemModels = new ArrayList<>();     }          public boolean find() {         return repository.find(this);     }      public void createOrder(CreateOrderRequest request) {         if (find()) {             throw new BusinessException(ResponseCodeEnum.ORDER_EXISTED);         }         this.orderMasterModel.createOrderMaster(request);         repository.createP2pOrder(this);         // 发送超时支付取消消息         pushDelayMessage(this);     } }
  实体
  实体是指会存在状态变更的类,比如order,其可以提供订单的变更状态等。@Getter public class OrderMasterModel {      private OrderStatusEnum orderStatus;     private LocalDateTime ticketTime;     private LocalDateTime expirationTime;     private String lang;     ...      public void init(CreateOrderRequest request) {         this.channelName = request.getChannelMetaInfo().getChannel();         this.orderStatus = OrderStatusEnum.SEAT_BOOKING;         ...     }      public void ticketing() {         if (this.orderStatus != OrderStatusEnum.WAIT_FOR_PAY) {             throw new BusinessException(ResponseCodeEnum.ORDER_STATUS_ERROR);         }         this.orderStatus = OrderStatusEnum.TICKETING;     } }
  值对象
  而值对象是指仅作为描述没有唯一标识的类,比如行程信息,行程信息变更应该是整个行程信息进行变更而不是提供方法进行修改,故本文针对值对象的构造方法进行私有化处理,并仅提供静态方法用于重新创建对象。@Getter public class OrderSegmentModel {     private long orderSegmentId;     private short sequence;     private TravelTypeEnum direction;     private String  segmentType;     private String departureLocationCode;     private String departureLocationName;     private String arriveLocationCode;     private String arriveLocationName;     ...              private OrderSegmentModel() {}      public static OrderSegmentModel init(OrderSegment orderSegment, short sequence) {         OrderSegmentModel model = new OrderSegmentModel();         model.orderSegmentId = Long.valueOf(orderFareId + "0" + orderSegment.getSegmentId());          model.sequence = sequence;         if (Objects.nonNull(orderSegment.getDepartureLocation())) {             model.departureLocationCode = orderSegment.getDepartureLocation().getLocationCode();             model.departureLocationName = ConvertUtil.getLocationName(orderSegment.getDepartureLocation());         }         if (Objects.nonNull(orderSegment.getArrivalLocation())) {             model.arriveLocationCode = orderSegment.getArrivalLocation().getLocationCode();             model.arriveLocationName = ConvertUtil.getLocationName(orderSegment.getArrivalLocation());         }          model.departureTime = DateUtil.parseStringToDateTime(orderSegment.getDepartureDateTime(), DateUtil.YYYY_MM_DDHHmm);         model.arriveTime = DateUtil.parseStringToDateTime(orderSegment.getArrivalDateTime(), DateUtil.YYYY_MM_DDHHmm);         ...         return model;     }
  仓储
  仓储封装于聚合根内部,不用于外部调用,故通过工厂方法将仓储注入聚合根中。@Slf4j @Component public class OrderFactory {      @Autowired     private OrderIdGenerator orderIdGenerator;     @Autowired     private P2pOrderRepository repository;      public P2pOrder create(CreateOrderRequest request) {         long orderId = orderIdGenerator.generateOrderId();         if (orderId < 1) {             log.error("fail to gen order id");             throw new BusinessException(ResponseCodeEnum.FAIL_GEN_ORDER_ID);         }         return new P2pOrder(repository, orderId);     } }
  仓储用于链接领域层与数据层,使领域对象与DAO隔离,使我们软件更加健壮。@Slf4j @Component public class P2pOrderRepositoryImpl implements P2pOrderRepository {      @Autowired     private OrderMapper orderMapper;      @Override     public boolean createP2pOrder(P2pOrder p2pOrder) {         OrderMasterEntity orderMasterEntity = new OrderMasterEntity;         orderMasterEntity.setOrderId(p2pOrder.getOrderId());          orderMasterEntity.setOrderStatus( p2pOrder.getOrderMasterModel().getOrderStatus().getCode());         ...         return orderMapper.insert(orderMasterEntity) > 0;     } }
  防腐层
  防腐层,又称为适配层,在对外部上下文的访问中,就需要引入防腐层对外部上下文进行一次转义,这样就可以将外部上下文转化为内部模型,防止因为外部更改导致改动影响过大。仓储也是防腐层的一种,因为其隔离了数据库的DAO对象,转化为了内部的实体和值对象。在本系统中,也需要对外部的汇率服务、保险服务等引入防腐层的概念。
  4.4 服务结构
  通过DDD思想进行建模,并采用DDD的六边形架构,重构后的服务结构如下:
  五、总结
  本文基于携程国际火车票出票系统对领域驱动设计进行实践,通过对出票系统中多个领域的划分使业务逻辑更加清晰,使得代码易于维护和迭代;并通过领域驱动设计的六边形架构将业务与技术进行了隔离,突出业务重点,使代码易于阅读;加入防腐层使外部上下文与内部模型进行隔离,防止外部对象侵蚀;将迭代需求转化为各个领域模型的更新,以领域来驱动后续功能开发,使其变得可控,避免了软件架构设计模式变成"大泥球"模式。
  鉴于作者经验有限,对领域驱动的理解难免会有不足之处,欢迎大家共同探讨,共同提高。
  参考文献
  [1] Scott Millett 等著, 蒲成 译; 领域驱动设计模式、原理与实践(Patterns, Principles, and Practices of Domain-Driven Design); 清华大学出版社, 2016
  [2] Evic Evans 著, 赵俐 等译; 领域驱动设计:软件核心复杂性应对之道; 人民邮电出版社, 2010
  [3] 领域驱动设计在互联网业务开发中的实践
  [4] 阿里技术专家详解DDD系列 第二讲 - 应用架构
  [5] 基于 DDD 思想的酒店报价重构实践
  [6] DDD(领域驱动设计)总结
  [7] 谈谈MVC模式
  [8] 阿里技术专家详解DDD系列 第三讲 - Repository模式
  [9] 领域驱动设计详解:是什么、为什么、怎么做?
  [10] 领域建模在有赞客户领域的实践
  [11] DDD分层架构的三种模式
  【作者简介】Ma Ning,携程国际火车票后端开发工程师,关注系统架构、微服务、高可用等技术领域。

5万元以下能买哪些车?推荐6款高性价比纯电微型车今年,随着新能源汽车爆发式增长,以及用车需求增大,纯电微型车市场的潜力彻底被激发。也有越来越多的城市上班族选择购买增购一台纯电微型车用于通勤代步,很显然,得益于纯电动微型车车身小巧OV要爆发了,三款新机即将发布,售价预计仅1599元起OPPO和vivo很多网友都简称OV,因为OPPO和vivo是同一个老板,据说都是步步高出来的品牌,很多地方OPPO和vivo的实体店都连在一起,当然两家厂商也相互独立相互竞争,O联想小新Pro142021升级为2。8K90Hz高刷屏,9月28日预售本文转自IT之家作者信鸽今日官方宣布,联想小新Pro142021款笔记本将升级至2。8K90Hz高刷屏,相比此前产品的2240140060Hz屏幕规格全面提升,同时亮度更高。升级后元宇宙概念风不断袭来,Picofacebook微美全息小米等产品上新如果说当下最火的概念是什么?元宇宙一定榜上有名。从元宇宙第一股Roblox上市首日股价即上涨54,到扎克伯格公开表示将用5年时间把Facebook打造成元宇宙公司,再到国内字节跳动区块链未来的发展板块分布区块链技术目前已被很多国家作为重要的基础设施应用到多个领域中,医疗教育科研等。随着区块链市场的不断发展,其中分出的板块也越来越多,NFTDeFi元宇宙分布式存储成为主要的发展趋势。难怪网购总比别人贵,原来是大数据杀熟了!4步快速解决不知大家是否知道?你的网购跟别人的网购有可能是不一样的!为什么这样说呢?在手机上点外卖购物,又或是打车,同样的商品或服务可能就比别人的要贵很多。或许你还不知道,但这样的情况比比皆是红豆角拼团碰瓷中国电信,又是一次有预谋割韭菜的骗局?现在网络上到处都是拼团的消息,各种各样的拼团的形式,这种什么拼多赚多的活动,大家真的要小心警惕,大概率上又是一次割韭菜的骗局。之前有个拼拼有礼拼团现在已经被证实是个骗局,而且已经崩影像旗舰vivoX70Pro开售,首销享两年质保今日(9月17日),vivoX70Pro与vivoX70Pro在线上线下同步正式开售。其中,vivo年度影像旗舰X70Pro从发布到预售阶段,预售量打破了vivo4000价位段全网中国芯片产业的突破!新一代国产先进光刻机来了,有两个重大意义众所周知,我国在光刻机领域一直处于弱势地位,国内芯片行业的先进光刻机一直依靠进口。科技日报在2018年曾经评选出35项制约我国工业发展的卡脖子技术,芯片和光刻机名列前二。如今3年过你见过最小人的同事干过什么事?那年,我在县委宣传部新闻股工作,领导安排我和一位女同事,一起接待3名一家省杂志社的记者。我们共同约好的事,她后来却把我给卖了。她算小人吗?那家省级杂志社的3名记者,是自己开车一路沿揭秘小米智能眼镜在AR眼镜出现之前,能显示单色信息的智能眼镜会是一个成功的过渡产品吗?采写靖宇据说今年苹果秋季发布会上最令人失望的不是iPhone13系列升级程度太小,而是没有OneMoreThi
机器人妻子上市遭抢购,是在解决刚需,还是在挑战伦理?作者李云飞来源原创一位久经商场的创业老司机,关注我,每天分享点财富干货,让你的人生少走弯路。随着人工智能的发展,目前我国的人工智能总体技术已经与世界先进水平同步。预计到2030年,缺货就是耻辱?挺让人生气的。小米公司Redmi产品总监和小米孙波你们作为公众人物,这么说话真的合适吗?小米孙波给小米王腾发来缺货就是耻辱字样的图片,小米王腾回复两个吐口水的表情。我就想说你俩挺会数字货币为什么叫挖矿为什么叫挖矿在比特币的P2P网络中,有一类节点,它们时刻不停地进行计算,试图把新的交易打包成新的区块并附加到区块链上,这类节点就是矿工。因为每打包一个新的区块,打包该区块的矿工就可中国版权协会发布区块链产品探索版权管理保护科技化中新网北京6月2日电(记者吴涛)在版权维权过程中,版权存证维权存在成本高周期长效率低等痛点。不过,随着互联网技术的发展,版权管理和保护迎来新机遇。发布会现场。中新网记者吴涛摄1日,虚拟数字货币未来的发展趋势嗨喽各位的观众老爷们,欢迎收看这一期的老猫吹币,我是比特老猫。最近各国都开始了数字货币的开采挖矿,而且许多国家也开启了数字货币交易也允许了用数字货币支付。那数字货币的未来发展趋势会网传某万元手机品牌严重滞销!仅售出1万部!网友哪个牌子?近日,某财经媒体报道的一则消息引爆舆论,消息称,某一线品牌推出的售价近万元的手机备货30万部,但仅售出1万多部,由此积压的资金就有几十亿元。由于大量滞销,已经让该手机企业吃不消了。备货30万只卖出1万,某一线手机品牌万元机滞销?近日有一篇知名自媒体的文章在网络上引起了不少的讨论,在这篇名为没有华为,国产手机还是干不过苹果的文章中透露了一个劲爆消息某一线品牌售价近万元的手机备货了30万部,却只售出了1万多部有哪些2000到2500左右的手机性价比高的,打王者吃鸡不卡,跪求各位大佬推荐()?感谢您的阅读!有哪些2000到2500左右的手机性价比高的,打王者吃鸡不卡的手机推荐我相信很多人对于吃鸡或者是王者荣耀还是非常的青睐的,特别是它们确实在我们的日常生活中能够起到一定阿里拓展社交版块!闲鱼创始人亲手打造小绒猪线上社交已经成为当代年轻人的重要社交方式之一,在兴趣垂类的赛道上有哔哩哔哩豆瓣等社区,两性交往上有陌陌Soul等软件,并且市值与流量都不低。由于网络社交版块发展潜力巨大,所以阿里也鸿蒙出道,操作系统的中国时代来了!下一个20年,属于中国文华商韬略斯钦几十年来,中国人对国产操作系统的殷切期盼,终于有了一个真实的载体。6月2日晚8点,华为正式发布了鸿蒙操作系统HarmonyOS2。0正式版。没有遮遮掩掩,也没有权衡利鸿蒙系统发布,华为的野心终露!不造车是因为要做票大的?6月2日,华为正式发布了鸿蒙操作系统。华为官方的微博名也由华为EMUI改为了HarmonyOS,连华为字样都去掉了,可以看作是一个新的时代正式开启了。鸿蒙系统的涵盖范围极广,不仅会