7Fresh是京东第一个线上线下融合落地的零售创新业务模式,店内有大量设备的集成,设备供应商达50多家,针对线下业务的特点,团队独立规划和设计POS收银系统、店内生产系统、加工系统、货架陈列系统、魔镜系统、餐饮系统、自助收银系统等共60多个系统,对接电子价签、电子秤、包装机、无人购物车、门店客流检测等几十种设备。

第一期上线40多个系统,后续又高效上线了其他新增20个系统,短时间内完成了别人口中不可能完成的神话。今天我就带您一同回顾7Fresh系统从0到1的快速构建之路!

01 系统构建历程
7Fresh与京东商城一样拥有一整套的交易系统、一键结算系统,但和线上不一样的是,我们还有很多线下系统,店内的生产、加工、库存管理、餐饮等等。

整个项目从产品调研、架构设计,到第一期上线经过了2个半月的开发。第一期就有40多个系统同时上线,基本能把所有的业务系统运行跑通,之后又增加了很多餐饮类,地推类和线下有关的新需求,现在也依然在落地新的需求中。

02 快速开发的主要原因
1、用DDD进行战略设计
•分治
•界限上下文内的技术无关的通用语言
•薄薄的技术集成层隔离业务变化
2、虚拟组织保障设计落地
•早期组成虚拟的架构师组织,后期产品也加入
•不断摸索方法论和原则
3、其他因素
•多团队协同包括成都、武汉、技术拓展等部门
•框架和组件积累,之前积累的pop-spring-boot和popdesign及脚手架
•业务团队的大量参与,与业务开展同步进行

03 我们对DDD的理解
1、首先是战略部分,这也是我们认为实施比较好的部分:
(1)划分和集成界限上下文。
这个虽然不是技术上的问题,但是最关键的还是对业务的理解,跟部门业务专家一起工作很重要,另外是参考了京东现有的情报,做了很多的改进。怎么把系统进行解耦,这个领域边界界定以后,首先上下文最重要的是界定通用语言,就是在一个上下文里边有一套完整明确的概念:一个店就相当于一个仓,WMS开始设计的时候概念方式是管理统一SKU。而我们线下店有做蛋糕、做餐饮这些场景,加工的原材料也应该在系统里,WMS如果强绑定销售商品的SKu的话,那我们线下店就没法管理了。

所以,经验就是不能把一个概念应用超出上下文界定的领域,这样做的好处就是,通过这种方式隔离一些变化,适应更多的场景,实现解耦。

(2)面向服务集成而不要面向数据集成。

如果这样的话就能解耦了吗?

随着一些新需求的推进,还是发现里边有些耦合存在。总结的经验就是:下游的系统应该对需求做抽象,提出自己的标准,这样才能实现解耦。做DDD领域设计的时候,不应该受到具体架构风格、模式的影响,不管是微服务的还是单体加模块化的风格,最终的效果应该都是一样的,界限分明。

(3)技术无关地考虑领域模型,比如使用类图,定义和功能场景甚至状态图和对象快照。

2、使用DDD进行战略设计相对容易落地,收益明显。在使用DDD进行战术设计却遇到了重重困难。

战术部分在落实到代码层面遇到了困难。看过业内关于DDD的分享,发现其实大家能把战术层面把DDD落地的,其实都做的不理想。以下是我们对战术层面上的理解:
(1)代码即设计

代码即设计,在代码中尽量表现出想要的设计意图和领域意图,但是像性能这类的属性很难表现出来,能够实现但却不能表现意图。而领域设计是比较能在代码层面表现出来的。

难点一:聚合根识别困难

难点二:贫血模式。基本我们的框架和思路,很机械式的编码和设计,很难实现上述的目标;

难点三:按DDD的理论,聚合根之间不赞成使用数据库事务,成本很高。
 (2)用包来体现实体概念

左图中间的部分就是领域模型,这也是现在比较通用的方式,领域模型包括领域对象、领域服务,领域对象总是要被存储的,这就需要依赖于仓库,仓库在领域下应该是个接口,我们认为领域应该依赖于技术实现,存储的实现应该在另外一个包下,通过依赖倒置的方式,把领域模型包含的东西和基础设施层分隔。
(3)订单状态变更的例子

现在有很多不同类型不同场景产生的订单,它们之间的状态变更是不同的,从未支付到已支付再到在拣货,当中有很多状态是不一样的。如下:

从设计层面可以划分不同的状态设计,但是最后状态无非是当前状态,编码实现上就目前来看,写在service层到处都是判断……,来一个新业务就要改一次新判断,但是我们现在从构思想,简单来说先把它放在order对象里,因为这只跟order的数据有关系。


从集成的角度来说,如果支付系统接收到支付完成的消息,我们把消息payevent变成一个事件,传给了orderservice-changestate,orderservice里边非常简单,把order从仓库里边加载出来,然后调动方法即可。

大部分业务里的规则还是在orderchangestate方法里。这么做的好处就是,它能够表达出我想要的设计意图,如果分散在其中的话,可能只与设计文档不一致。

第二个就是说,把领域规则识别出来放在对象中会带来额外的好处是,领域规则往往跟外部是没有关系的,很容易做纯粹的自动化的单元测试。

(4)数据一致性和领域事件
一个微服务内部的多个聚合根,可以使用数据库事务保证数据一致性,虽然不完美,但还算实用。用领域事件去做最终一致性成本太高。

两个上下文之间用MQ做最终一致性

本文转载自:http://www.dalbll.com/Group/Topic/ArchitecturedDesign/5011

京东7Fresh新零售架构设计分析的更多相关文章

  1. 新零售SaaS架构:中央库存系统架构设计

    近年来,越来越多的零售企业大力发展全渠道业务.在销售额增长上,通过线上的小程序.直播.平台渠道等方式,拓展流量变现渠道.在会员增长方面,通过多样的互动方式,全渠道触达消费者,扩大会员规模.而全渠道的库 ...

  2. 新零售下的 AI智能货柜

    公司有个智能货柜,通过微信扫码开门,拿货,自动扣款,挺智能的.还不错.研究一下原理,网上查了一下. 文章简介: 目前新零售风刮的蛮大,笔者进入该领域近一年,负责过无人便利店.智能货柜.智慧商超等产品, ...

  3. Saas系统架构的思考,多租户Saas架构设计分析

    ToB Saas系统最近几年都很火.很多创业公司都在尝试创建企业级别的应用 cRM, HR,销售, Desk Saas系统.很多Saas创业公司也拿了大额风投.毕竟Saas相对传统软件的优势非常明显. ...

  4. Web API应用架构设计分析(2)

    在上篇随笔<Web API应用架构设计分析(1)>,我对Web API的各种应用架构进行了概括性的分析和设计,Web API 是一种应用接口框架,它能够构建HTTP服务以支撑更广泛的客户端 ...

  5. 新项目架构从零开始(三)------基于简单ESB的服务架构

    这几个月一直在修改架构,所以迟迟没有更新博客. 新的架构是一个基于简单esb的服务架构,主要构成是esb服务注册,wcf服务,MVC项目构成. 首先,我门来看一看解决方案, 1.Common 在Com ...

  6. 【公众号系列】SAP的新零售

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[公众号系列]SAP的新零售   写在前面 还是 ...

  7. 阿里前CEO卫哲:马云好玩,人工智能泡沫巨大,新零售重在社区

    阿里前CEO卫哲:马云好玩,人工智能泡沫巨大,新零售重在社区 投资中国网 08-21 08:34 投中网(https://www.chinaventure.com.cn) 编者按:当下的技术时代,是跨 ...

  8. 良品铺子:“新零售”先锋的IT必经之路

    良品铺子:“新零售”先锋的IT必经之路 云计算 大数据 CIO班 CIO 互联网+ 物联网 电子政务 2017-12-29 09:25:34  来源:互联网抢沙发 摘要:2017年被称为“新零售”元年 ...

  9. 微软YY公开课[《微软中国云计算Azure平台体验与新企业架构设计》 周六晚9点

    YY频道是 52545291//@_勤_: YY账号真的是一次一账号啊! 全然记不得之前注冊的//@老徐FrankXuLei: 最火爆的微软免费公开课.第一次顶峰126人.第二次96人.第三次我们又来 ...

随机推荐

  1. 闲谈:乌云上那些 web-based 的 QQ 漏洞

    0×00 起始 昨日凌晨,看到爱尖刀团队发布了一条“腾讯客户端XSS,已第一时间提交至TSRC”的微博,心想,腾讯又出此类漏洞了.今日,由于有一位名叫“阿布”的同学将该漏洞发布到了乌云,引来不少争吵甚 ...

  2. jQuery的attr()与prop()的区别

    jQuery的attr()与prop()都是用于获取与设置属性的,但它们又各有不同. attr()一般是用于设置默认值,prop()一般是用于设置属性值,即对于像“diabled”,"che ...

  3. 安卓app开发-03-项目的基本开发步骤

    android项目的基本开发步骤 这里分享一下开发 安卓 app 的流程,当然有些感觉不必要,其实不然,前期工作也是极为重要的额,就像开发的时候如果目标不对的话,到后期后很迷的,所以一定要提前做好规划 ...

  4. Docker Toolbox更换镜像源并下载centos7

  5. python----------闭包 、装饰器

    闭包: 就是内层函数对外层函数(非全局变量的)非全局变量的引用 def func(): name = '老人家' def func1(): print(name)#局部变量对全局变量的引用 因为并没有 ...

  6. 猴子选大王【PHP】

    目录 猴子选大王 指针解决 数组压栈 猴子选大王 一群猴子排成一圈,按1,2,...,n依次编号.然后从第1只开始数,数到第m只,把它踢出圈,从它后面再开始数,再数到第m只,在把它踢出去...,如此不 ...

  7. ASP.NET Core 返回文件、用户下载文件,从网站下载文件,动态下载文件

    ASP.NET Core 中,可以在静态目录添加文件,直接访问就可以下载.但是这种方法可能不安全,也不够灵活. 我们可以在 Controller 控制器中 添加 一个 Action,通过此Action ...

  8. August 17th 2017 Week 33rd Thursday

    Fate is responsible for shuffling, but the game of cards is our own! 命运负责洗牌,但是玩牌的是我们自己! Today, I upd ...

  9. December 27th 2016 Week 53rd Tuesday

    A journey of one thousand miles begins with one step. 千里之行始于足下. No matter how slowly you walk, as lo ...

  10. 在android工程中添加图片资源(转加)

    在Android工程中,每添加一个资源,就会在gen目录下的R.java中自动生成一个新的静态整型变量来指向这个资源.程序文件中调用资源的时候,先在R.java中找到变量名,然后根据变量值查找资源. ...