NVIDIA 初创加速计划,免费加速您的创业启动 了解详情
写点什么

亚马逊实践领域驱动设计之道

  • 2020-05-06
  • 本文字数:5417 字

    阅读完需:约 18 分钟

亚马逊实践领域驱动设计之道

当我们在讨论领域驱动设计,我们在讨论什么?GitChat 的谢老师开场说,DDD 出现了十几年了,都快推不下去了,突然刮来一阵微服务的热浪,随之而来就是这两年国内的 DDD 社区的火热;但作为整天泡在客户一线业务的架构师,看到的情况却是,大部分用户反馈使用领域驱动在开发团队,非常的别扭,真正带团队能实现微服务架构,支撑业务敏捷发展的企业非常少;所以,开始正题之前,我们需要弄清楚,DDD 为何出现?为何随着微服务的发展而真正流行?

软件研发交付难题 - 如何与业务一起比翼双飞?

软件开发是一项复杂的团队运动,随着技术的发展,解决问题的复杂度不断增大,代码量也不断增加;软件技术发展的使命之一就是控制复杂度,这些复杂度,包括业务复杂度(需求,规模),技术复杂度(代码含义模糊,非功能需求-安全、性能、高并发和高可用等等),还有项目管理复杂度(团队,文化,制度,工具等等)。



举例来说,亚马逊电商从 1995 年创立之初只有书这样一个单品,到现在的综合在线商城,站点上线第一行代码开始,一直膨胀成一个非常大的单体电商应用,后台数据库随着功能和数据量膨胀,表之间关系越来越复杂,同时商品品类和全球扩张,后台商品入库和上架等功能,创造了一堆的脚本和定时任务。从技术来看,这样的单体应用,除了后台技术人员比较辛苦外,似乎也没什么不妥;但巨大的单体应用,阻碍了新的功能需求的快速上线和电商站点的可用性问题,业务变化到应用的变更交付周期拉长人天耗费巨大,系统运维成本不可想象。



软件研发发展历史上,有很多理论框架和设计模式指导大家如何管理大型应用需求开发交付,提升软件质量,其中大家熟知的面向对象的设计模式,TOGAF 企业架构,敏捷软件开发原则模式和实践,以及埃里克·埃文斯 的领域驱动设计都是这方面的优秀成果。



由于关系数据库长期统治对应用架构的影响,开发人员早已习惯重复开发 CRUD 的数据库管理系统,以数据库数据模型展开整个系统设计和落地,业务需求方和技术人员的沟通长期存在巨大鸿沟;以数据库为核心的架构,缺陷在于丢失了更重要的业务原语,而简化成技术层的 CRUD 操作,这样业务到技术实现就经历好几层的翻译,准确性可想而知;另外一个技术缺陷在于,很多逻辑紧耦合在数据关系上,牵一发而动全身。



企业复杂的内部应用集成和重构催生出一批 SOA 架构的理论和产品,而大规模互联网分布式应用的成功,奠定了分布式微服务体系架构在敏捷业务创新领域的广泛应用,而其中亚马逊 AWS 的诞生更是大规模微服务系统一个有力的样板工程。Eric 在领域驱动设计这本书里面,强调业务领域和技术利用统一语音渐进融合的架构设计战略建模及战术落地相关的思考和总结。DDD 的核心内容就是,理解和独立出领域模型为核心,驱动技术人员思考业务边界和领域之间的互动关系。从原来的数据库为中心的架构转型到服务解耦+组织解耦的业务驱动,有非常多的挑战!



领域驱动核心就是多了一个领域层,这个领域是业务相关原语,随着业务价值变化而变化,通常每个企业的核心业务域是千差万别的,所以,在技术实现的时候,反复要问我们团队,我们多少比例的代码是针对业务本身,而业务本身对业务消费者有多大的价值?作为业务的技术实现方,一定要有手段通过量化方法,衡量你的业务价值,从而能精细化迭代升级。



领域驱动设计的设想非常美好,但通常研发团队很难推广,为什么?以前是由于基础技术不成熟,而云计算的出现,降低了技术门槛,各领域的小公司纷纷颠覆式创新并迅速发展壮大;以互联网思维,产品思维驱动的互联网公司高速发展路径被人们广泛认知;纯粹回到微服务技术落地角度,基于广泛的云服务,我们可以快速原型和测试上线,比如 Eric 提到的事件驱动架构,CQRS(命令查询分离架构)等,利用成熟的云平台,用户不需要重复构建轮子,更直接实现业务逻辑。




理论还需结合实际;可以说,微服务本身的理念和 DDD 不谋而合;那很多客户的困惑就在于如何拆分微服务,DDD 给大家的答案是通过定位核心域、子域和支撑域,明确领域边界,从而抽象出自治高内聚松耦合的服务。

客户普遍反馈的最大挑战:如何拆分业务定义边界?


疑问一:是否可以直接购买现成的业务领域模型?


直接购买现成的方案,是客户非常熟悉的快速实现业务诉求的方式之一;就比如公司 A 准备上一个电商平台,目前的现状是,后台是历史遗留的竖井式商业支撑系统,但业务短期的诉求是如何服务好广大的终端客户,渠道大多数为移动 APP 和 WeChat 入口;期望,新系统能很好支撑新业务上线,业务的灵活变更等等;看起来直接购买可以省时省力,关键是后续的持续开发迭代如何做?所以,目前我看到这几种方式:


  • 购买源码,自己团队消化,再进一步开发升级

  • 全部外包,找一个类似业务领域经验的公司,复用他们的领域模型、框架和团队能力

  • 基于 SaaS 化平台,标准模块+有限定制能力


最近看到还不错思路的某电商平台,好奇的同学可以进一步了解下:



再举一个例子就是涂鸦智能,他们提供了设备智能化的全套解决方案,可以快速帮助小家电、大家电等设备制造商,构建智能互联解决方案:



疑问二:类似 AWS 这样的云服务有提供现成的行业化的解决方案吗?


AWS 技术平台一直以来的口号就是 Go Build!赋能开发人员创造创新的自由。今天我们探讨 DDD 更多会涉及业务领域如何对齐技术实现的命题;上一个章节所述,AWS 的合作伙伴生态,有非常多的深耕各行业的解决方案,从我熟悉的领域来看,跟业务贴合非常紧密的云服务就是游戏行业解决方案,更多的内容可以参考官方资料(见文末资源链接);



疑问三:社区还有什么参考的 DDD 落地方法?


回到领域驱动设计,为了对齐业务术语和技术名词,实现领域模型驱动的开发,DDD 最核心的建议就是统一语言,至少在一个特定的界限上下文里面,消除业务领域“行话”的歧义,大家在同一个语境同一个理解上进行对话,比如我们讨论“下订单”,如果不是针对特定的上下文,每个人的理解都不一样,只有限定到比如咖啡店场景,大家才能无歧义沟通下去:



Eric 的十几年前的思考总结还缺乏具有实操意义的执行方法;所以,社区在实践中发明了事件风暴(Event Storming),在这样的 Workshop 中,参会者,利用不同颜色的便利贴和记号笔,统一语境:用户,命令,事件;不断挖掘特定业务场景的核心用户事件线索;并可以进一步进行战术建模,实现最小原型产品(MVP);



如果大家想体验一下事件风暴 Workshop 给团队带来的体验,以及在 AWS 快速原型实现 DDD 项目,我特别推荐台湾同事 Kim,他是无服务器领域的极客,又是台湾地区 DDD 社区联合创办人,他在 Github 上有个非常赞的事件风暴指南,欢迎大家跟他交流(Github 地址见文末的资源链接):


另外,实操层,DDD 中国社区大会每年也会有很多的客户现身说法,大家想听 DDD 企业实战的可以关注。AWS 专业服务团队是可以帮助客户现场咨询和落地,大家可以联系对应的 AWS 同事。


最后,我们从亚马逊的大规模微服务实践来探讨下,业务与技术一起比翼双飞的实践经验。



亚马逊的实践经验:大规模客户驱动的微服务产品研发落地公式


如果大家认可领域驱动设计的理念,那如何创造环境,开花结果才是完美的结局。今天跟大家分享的就是亚马逊的故事,一个诞生 AWS 这样大规模微服务云平台的故事;仅供大家参考,每家企业都有各自的独特性,这里的分享不是告诉大家一个银弹,而是抛砖引玉,给大家一个信心,业界有做的非常好的案例。



上面这个创新公式,跟 DDD 有什么关系呢?我们假设你也想客户至上,期望你的用户需求驱动你的业务敏捷创新,那我们思考 DDD 落地就不能局限在开发团队本身,而需要将开发团队放到整个公司组织的生态里来考虑。正如公式所示,业务和技术渐进统一的理想需要关注组织,架构,机制和文化四个方面,而机制和文化作为指数参数,是决定整个业务创新技术创新的加速度。



通常公司架构从创业开始,开始的小团队,规模不断扩大,组织变得越来越复杂,流程也越来越复杂,而应用本身也会随着业务发展,膨胀成一个“胖子”,研发再也无法快速响应业务需求,在保持可用性,运维方面,团队会付出极大的人力和时间成本;因此,避免组织僵化,支撑业务长期敏捷小步快跑式创新,适应市场长期不变的用户需求升级;架构上,我们总结了三点:


  • 自服务:降低技术门槛,提供广泛的工具给到团队,提升研发效率

  • 微服务:服务自治,团队自治自主,避免紧耦合;快速交付和验证;

  • 重复构建:微服务架构会出现多个团队同时做类似的产品,但由于单个服务团队的资源约束(2 个披萨),和快速迭代,很快就可以判断哪个产品胜出,试错成本较低。


什么是微服务架构?它的优势是什么?如下图所示,“单一责任原则”和 DDD 里面倡导的界限上下文一个意思,另外,微服务提升了扩展性、可用性和容错,服务拆分更加靠近业务领域,同时需要组织架构配套保障;所以,微服务的初衷可以支撑大规模复杂业务的继续更新迭代。技术复杂度而言,微服务初期要比单体复杂很多。



很多客户都反馈,就算是微服务实现的技术层,团队的想法太多,一直在选型各类框架,但实施后的效果,尤其对业务的支撑效果,并没有想象的那么好,我们什么地方做的不对吗?那亚马逊微服务的基石是什么?如下,是 2002 年前后,我们的创始人的 API 化宣言,只有 6 条就统一了“语言”和思路。打破了以前一直以数据库为核心的紧耦合开发协作方式,奠定了微服务的基础。列一个你们在微服务架构中坚持的原则?



很多团队在讨论微服务的时候,仅仅围绕技术方面,但根据康威定律,要玩好微服务,组织架构解耦也非常重要:



什么样的组织和团队才是适合的呢?团队解耦的方法很多,就如同微服务解耦的方法也很多一样,我们是怎么做的呢?保持和创业团队类似的小团队,完全自主自治,对最终交付的产品负责,由于团队规模保持在 2 个披萨(4-7 个人左右),所以,一个小团队负责的产品职责就自然会尽量单一聚焦,团队也不会轻易扩大自己的核心业务域。小团队更强调 DevOps,小步快跑,快速迭代,最快的速度上线,收集产品反馈,再持续迭代;该团队的使命一直伴随着该产品的价值而波动,直到被未来更有价值的产品服务取代。小团队,更容易使团队成员有主人翁精神;小团队同时保持简单的层级关系,可以使得团队获取管理层支持和资源的时候,沟通更加直接,后面我们会探讨小团队的核心业务领域如何确定,如何获得资源支持。



这里面还有一个非常重要的实践,就是招聘,要保证小团队的战斗力,招聘的标准是非常重要的,这个标准决定了你是否可以不断扩张团队,而同时客户以提升团队能力,一个很简单的指标就是新加入的人一定要比团的 50%的人的能力要强,因为我们相信,人的经验是无法压缩的,不断招募高于团队平均水平以上的新鲜血液可以保障团队战斗力不断提升。



和 DDD 所设想的类似,全栈小团队的设计,就是为了让团队的整个软件的研发交付围绕着业务价值在迭代,而当今时代,云服务是软件研发交付价值链里面非常重要的一个基础平台。接下来以亚马逊电商为例,我们看看团队和产品的对应关系,重点是,每个团队(都是 2 个披萨),如果一个业务域需要更多的资源投入,那就不断成立新的小团队,横向扩展,即使整个团队的规模不断扩大,但每个团队还可以如创业初期那样,独立自主进行价值交付,团队越多,交付的价值就越大。



上面我提到了微服务架构,微服务产品团队,那跟 DDD 遇到同样的问题,创新的源泉来自客户需求也就是业务,如何围绕业务,阐明价值,并获得管理层资源支持呢?这里就不得不说说“机制”,亚马逊实践出一个非常有意思的一个机制叫“逆向工作法”,为了做到客户至上的创新机制,逆向工作法要求团队在投入资源之前,从客户场景和痛点出发,假象未来某一个时间点,你的产品发布了,你要跟你的客户讲些什么?客户会有哪些问题?这就是逆向工作法的交付物,我们称之为“新闻稿”和“常见问题”;在沟通业务域问题的时候,我们倾向于提议者写不超 6 页纸的格式化 Word 文档,会议中,给到所有人 30 分钟时间认真阅读之后,再进行讨论,提问和判断下一步是否要投入。




神奇的逆向工作法,就是想象有一天你成功发布了你的产品服务,你要如何跟你的客户说?这个就类似我们的创业计划书,不过更加简化和实用;我们再看看最后一个因素“文化”,有人说,大公司都讲文化,确实,文化是行动纲领,当我们没有更好的信条之前,大家都要遵循 14 条领导力原则,如果感兴趣可以继续通过文末的资源链接扩展阅读。



到这里,关于亚马逊创新公式就讲的差不多了,对照 DDD 理论和实践,这个公式给大家一个更好的框架来思考,微服务落地或者改造这件事,你如果要行动的话,可以从哪些方面出发,基于 20/80 原则,抓重点结合你自己的实际情况,对实施的代价要有清醒的认识,如果无法估算,就走一步看一步再走一步:)

归根结底是研发团队赋能

我们最后总结下,领域驱动设计还的结合事件风暴或者亚马逊的逆向工作法,才能更好地抽象业务领域,而这块的抽象更多是人员和沟通问题;核心业务问题和用户故事出来之后,尽量将核心域工作范围限制在一个 2 披萨团队可以独立完成的范围,不行就再拆;业务和技术一致的架构,本质上要求,微服务团队也需要解耦和自治自主;为了更好的帮助团队敏捷研发,需要提供一个无人值守的自服务平台,提供必要的工具和基础服务;



因此,我认为,核心我们要面临的问题是,“研发团队赋能”,如何让团队高效运作,实现最终的业务敏捷是我们这次探讨 DDD 还有亚马逊创新公式的出发点。


本文转载自技术锁话公众号。


原文链接:https://mp.weixin.qq.com/s/6YHVvwhaNJkCg6gqR3iq0Q


2020-05-06 10:25809

评论

发布
暂无评论
发现更多内容

说说个人影响力

张老蔫

28天写作

MySQL统计总数就用count(*),别花里胡哨的《死磕MySQL系列 十》

咔咔

MySQL conut

Spring 扩展之深入分析 Bean 的类型转换体系

chenssy

死磕 Java 死磕 Spring

Spring扩展之 深入分析 Aware 接口

chenssy

死磕 Java 死磕 Spring

毕业设计

毛先生

TypeScript 之 Class(上)

冴羽

JavaScript typescript 翻译 大前端

什么?还在用delete删除数据《死磕MySQL系列 九》

咔咔

MySQL delete

在K8s里部署Eureka集群

xiaoboey

Kubernetes Spring Cloud Eureka Gateway 服务发现

Spring 扩展之深入分析 PropertyPlaceholderConfigurer

chenssy

死磕 Java 死磕 Spring

Spring 扩展之深入分析 PropertyOverrideConfigurer

chenssy

死磕 Java 死磕 Spring

Spring 扩展之自定义类型转换器

chenssy

死磕 Java 死磕 Spring

大湾区的“科创土壤学”

脑极体

浅谈MySQL中的游标

麦洛

MySQL 游标

年后跑路第一战,从Java泛型学起!

麦洛

Java Java泛型

38 K8S之CNI插件与选型

穿过生命散发芬芳

k8s 28天写作 12月日更

字符串可以这样加索引,你知吗?《死磕MySQL系列 七》

咔咔

MySQL 字符串 加索引

Spring 扩展之深入分析 InitializingBean 和 init-method

chenssy

死磕 Java 死磕 Spring

Spring 扩展之之 PropertyPlaceholderConfigurer 的应用

chenssy

死磕 Java 死磕 Spring

毕业总结

毛先生

低代码实现探索(七)赋能产品架构如何做定制化

零道云-混合式低代码平台

为什么MySQL字符串不加引号索引失效?《死磕MySQL系列 十一》

咔咔

MySQL 索引失效

Spring 扩展之深入分析 BeanPostProcessor

chenssy

死磕 Java 死磕 Spring

面试官synchronized连环问,学会Monitor之后轻松拿下

李子捌

Java、 28天写作 12月日更

架构训练营作业一

supermenG

架构师训练营 4 期

无法复现的“慢”SQL《死磕MySQL系列 八》

咔咔

MySQL 慢SQL

打开order by的大门,一探究竟《死磕MySQL系列 十二》

咔咔

order by MySQL高级

架构实战营 第4期 模块一作业

架构实战营 模块一 「架构实战营」

Spring 扩展之深入分析 BeanFactoryPostProcessor

chenssy

死磕 Java 死磕 Spring

MySQL性能测试之insert&delete【FunTester框架】

FunTester

MySQL 性能测试 测试框架 FunTester delete

手把手教你实现网页端社交应用中的@人功能:技术原理、代码示例等

JackJiang

即时通讯 IM web socket

10 款你不知道的 Linux 环境下的替代工具!

JackTian

GitHub Linux 程序员 运维 命令行终端

亚马逊实践领域驱动设计之道_行业深度_技术琐话_InfoQ精选文章