业务代码与技术代码(业务代码和技术代码的对比)
cac55 2024-09-20 12:56 25 浏览 0 评论
当程序员大多都有一个共同的经历:当你在改一段复杂的代码时,你一边吐槽是哪个小可爱写的这段像一坨*一样的代码时,一边打开了提交记录,赫然发现竟然是自己3个月前写的!
明明看起来很简单的业务,但写出来的软件代码为什么会这么复杂呢?这是所有程序员都可能会思考的问题。
“领域驱动设计”号称是一种能够应对软件复杂性的解决方案,它的核心思路是从业务视角出发,去设计软件,并试图把技术复杂性和业务复杂性分离开来。但领域驱动设计是20年前就提出来的,那时候的软件面临的技术挑战和技术复杂性和现在不可同日而语,有些规则可能已经不那么适用。
那软件为什么复杂呢?前段时间看张逸前辈的《解构领域驱动设计》,里面对这块有非常详尽的解释,我觉得他总结得挺好的,这里精炼一下分享给大家:
简单来说,软件复杂是分为两个维度的。从理解维度上来说,软件的规模越大,结构越混乱,软件也就越复杂。从预测能力维度来说,软件可能会因为不能很好地适应未来的变化而导致改动成本太大而复杂。
我们可以用一些开发上的概念对应这几个维度,比如规模对应了代码行数和微服务数量;结构对应的是代码的分层设计、服务的调用关系;过度设计指的是为了把软件设计得过分通用,而导致代码设计复杂、可读性降低;设计不足就是很多写死的代码,导致业务变化时会有“改不动”的现象。
那么领域驱动设计的解决方案是什么呢?——通过分解领域,分而治之来「控制规模」;通过合理的架构来「清晰代码结构」;通过抽象合适的领域模型,高内聚低耦合来「应对变化」。
其中,在清晰结构这一部分,我们应该尽量把“业务复杂度”和“技术复杂度”区分开来。比如一个订单业务,业务上关注的是订单的校验,计算订单金额,提交订单和整个订单后续状态的流转。而技术上关注的是保证订单能够正确的完成,保障数据的正确性,一致性,稳定性,更具体一点,比如如何防止重复提交,如何防止超卖,如何应对高并发,下游服务或者数据库挂了怎么办等等一系列技术问题。
那么我们以“提交订单”这个业务为例,来看看整个过程中会有哪些代码,哪些算是业务代码,哪些算是技术代码,它们应该如何被组织。
我们先来看看一个简化版的提交订单用例图,真实情况可能会比这个更复杂得多。
这个用例图看起来并不算很复杂,一共只有6步操作步骤,我们来一步一步解析。
分解步骤
1 提交订单
在提交订单这个环节,业务上并不会考虑太多。但从技术上,处于安全性考虑,我们可能需要校验一些参数的合法性,比如提交的商品id不能为空列表,提交的商品数量必须大于0等。
这些代码通常写在我们应用的最外层,是一进来就需要校验的。一些语言(比如Java)可能会有更优雅的解决方案,比如使用Validation注解。
所以「这里的参数校验是纯技术代码」。
2 校验并占用库存
其实从业务上来讲,这一步应该只是叫“校验库存”,也就是校验这个商品是否还有库存,如果库存不足的话,应该及时中断流程,提示用户库存不足。
但处于技术上考虑,这里可能并不只是单纯的校验就可以的。我们还需要“占用”库存,防止超卖现象。比如在秒杀场景,某个商品有100个库存,但同时有1万人抢,大家几乎在同一时间抢购,如果在校验库存这个地方做限制,那很有可能有远超100人都校验通过,流程往后走,一直到用户付款后才发现库存不足了,给用户带来不好的体验,这在业务上是不允许的。
我把这一步合在了一起,叫“校验并占用库存”,但实际设计的时候可能是两个接口,也可能是一个接口。
所以「这里的校验是业务代码,但占用是技术代码」。但占用也是为了业务上的体验更好,业务上数据正确,所以有些团队会把占用也认为是业务代码。
3 查询商品价格
从业务视角看,其实只关心的是这个订单的总价。计算逻辑也很简单,就是订单上每种商品的价格 * 数量之和。
但技术上要考虑安全性,所以这个金额不可能是从前端页面传过来的,尽管此时前端页面已经拿到了每种商品的金额数据展示给用户。
出于保险起见,订单系统会去商品系统查询数据。
那么问题来了,假如查不到某个商品(下游挂了或者数据不正确),或者这个商品已下架/已违规怎么办?
此时如果是因为下游挂了或者数据不正确,而查不到商品,这里算是一种技术问题,应该终止流程并提示用户。而如果商品下架/违规,这里算是一个业务问题。当然也应该终止流程,并提示用户相应的文案。
但无论是技术问题还是业务问题,如果这里不能正常查询商品的价格,出于数据一致性的考虑,「都应该回滚在第二步占用的库存」。
那么问题来了,回滚失败怎么办?
这里就涉及到一个问题了,「我们值不值得为了这种“极小概率场景”去做一套方案」?比如占用超时释放?
出于成本考虑,我想大多数团队不会做得很严谨,事实上也不可能完美解决这个问题,毕竟可能根本没有完美的方案。真要是发生了这种情况,可能多数人的选择还是打个ERROR日志,然后触发告警,手动看一看。
4 计算订单总价
好了,终于来到纯业务的领域了。计算订单总价,看起来好像很简单,乘起来再加起来就行了。
然后业务同学告诉你,这块现在是直接计算没问题,但我们后面可能要搞满减活动,它是分档次的。满100减10,满200减25,满500减80……
而且会员有折上折,vip 1 打9.8折,vip 2打9.7折……
在大促期间,我们可能还会有优惠券活动,用户可以使用各种各样的优惠券……
最恐怖的是,可能产品同学提需求的时候并不会跟你说这些,而是后面再提n个需求让你改。
好吧,这就是业务代码。它可能是随时会发生变化的。
在计算完后,应该把这个订单的信息保存到DB,生成一个单据。但业务不关心这个,这是技术代码。
5 确认扣减库存
其实提交订单在业务上看就是一瞬间的事情,提交订单,然后扣减库存。但技术上因为会分为上面的步骤,所以要有占用,回滚,确认扣减这几个步骤。也是处于数据一致性考虑。
所以个人觉得“确认扣减库存”,更像是一个技术代码。
6 生成支付单据
这个我觉得是业务代码了。但同样会有上面的一系列技术问题,比如生成失败怎么办,如何设计幂等,防止重复提交等等。
领域代码
假设我们是按领域来划分的系统。那我们就有订单领域,库存领域,商品领域,支付领域。对于电商场景来说,它们可能都是我们系统中的核心领域(支付领域也许不是,这个看公司策略)。
在用户提交订单这个业务,订单领域要做的是生成一个“订单”模型,完成订单的计算,生成订单单据。其中完成订单的计算这一步骤是纯业务逻辑,也是最复杂的,它应该放在领域模型内部。但其实也不尽然,当规则复杂和易变到一定程度,我们可能会使用「规则引擎」,那订单模型的职责就变成了“应用从规则引擎读取到的规则来计算金额”了。
在库存领域,核心的领域代码应该是库存被占用。
在商品领域,这个步骤不涉及领域状态的变更,更多的只是商品信息的查询。在领域驱动设计提倡的CQRS(读写分离)的架构下,商品领域只是提供一个查询接口,所以不会涉及领域模型的相关代码。
在支付领域,也是生成一个“支付单”,此处逻辑较简单。
技术代码
你可以很明显的能够感知到,如果光靠领域代码,基本上是不可能顺利地正确完成“订单提交”这个业务操作的。
比如库存占用,就需要上锁才能保证不超占。更别说还有回滚和确认。比如参数的校验、幂等的设计,也是不属于业务代码的。
我们再来看领域驱动设计倡导的两个领域之间“基于事件通信”,在这个业务里面也是不能完全使用事件来通信的。订单领域就是需要实时调用库存领域的接口来保证强一致性。
反思
所以我们再回过头来反思,领域驱动设计可以解决这个问题吗?业务代码和技术代码真的能分开吗?
很明显,在订单领域,单纯的一个订单模型已经不能够内聚所有的逻辑了。那么加一个订单领域服务呢?其实理论上是可以的。大概代码组织是这样:
public String submitOrder(SubmitOrderCommand command) {
stockAdapter.checkAndOccupyStock(command.getCommodityInfos());
try {
Commodities = commodityAdapter.Getcommodities(command.getCommodityInfos());
Order order = OrderFactory.generateOrder(command);
order.computeTotalAmount();
orderRepository.save(order);
stockAdapter.confirmOccupyn(command.getCommodityInfos());
} catch(Throwable t) {
logger.Error("提交订单失败。", t)
stockAdapter.rollbackOccupy(command.getCommodityInfos());
}
paymentAdapter.submitPayment(order.getPaymentInfo())
}
可以看到,上述代码涵盖了第2步到第6步的所有步骤(第1步没放进来是因为参数校验通常在更外层就做了)。但很明显我们仍然「不可避免地把技术代码和业务代码糅杂在了一起」。比如保存数据库、确认占用等。但我们也尽力把技术代码挪到了adapter和repository的实现里面,在领域层只是调用了一下接口。相较于传统的面条式各种service调用代码,使用领域服务和领域对象就清晰得多了。
再回过头来看过度设计和设计不足的问题。这其实考验的是一个程序员对业务的理解程度和思考程度。如果可以显然预料到未来会发生明显的变化(比如文中提到的计算规则的变化),那确实应该在设计之初更灵活地设计好。而如果对未来的变化把握并不清晰,或者确定,那满足当前业务需求就可以了,如果架构合理,代码清晰,改起来成本倒也没那么大。这里提倡的是开发者尽量多与领域专家(比如业务人员或者产品经理)沟通,这样才能更好地把握代码未来的走向。
求个支持
我是Yasin,一个坚持技术原创的博主,我的微信公众号是:「编了个程」
都看到这儿了,如果觉得我的文章写得还行,不妨支持一下。
文章会首发到公众号,阅读体验最佳,欢迎大家关注。
你的每一个转发、关注、点赞、评论都是对我最大的支持!
还有学习资源、和一线互联网公司内推哦
相关推荐
- 无力吐槽的自动续费(你被自动续费困扰过吗?)
-
今天因为工作需要,需要在百度文库上下载一篇文章。没办法,确实需要也有必要,只能老老实实的按要求买了个VIP。过去在百度文库上有过类似经历,当时为了写论文买了一个月的VIP,后面也没有太注意,直到第二个...
- 百度文库推出“文源计划”创作者可一键认领文档
-
11月7日,百度文库发布了旨在保护创作者权益的“文源计划”。所谓“文源计划”,即为每一篇文档找到源头,让创作者享受更多的权益。据百度文库总经理李小婉介绍,文源计划分为三部分,分别是版权认证、版权扶持和...
- 有开放大学学号的同学,百度文库高校版可以用了。
-
还在网上找百度文库的下载方式,只要从身边的朋友在读开放大学的,那他(她)的学号就可以登陆到国家开放大学图书馆,还使用百度文库高校版来下载。与百度文库稍有不同,但足够使用了。现转国图链接如下:htt...
- 搜索资源方法推荐(搜索资源的方法)
-
今天msgbox就要教大家如何又快又准的搜到各类资源,第一点,排除干扰百度搜索出来啊经常前排展示它的产品以及百度文库,如何去除呢?很简单,后面输入空格减号百度文库,比如你搜高等数学百度文库很多,只要后...
- 一行代码搞定百度文库VIP功能(2021百度文库vip账号密码共享)
-
百度文库作为大家常用查资料找文档的平台,大多数文档我们都可以直接在百度文库找到,然而百度文库也有让人头痛的时候。好不容易找到一篇合适的文档,当你准备复制的时候他却提示你需要开通VIP才能复制~~~下载...
- 百度文库文档批量上传工具用户说明书
-
百度文库文档批量上传工具用户说明书1、软件主要功能1、批量上传文档到百度文库,支持上传到收费、VIP专享、优享以及共享。2、支持自动分类和自动获取标签3、支持多用户切换,一个账户传满可以切换到...
- 百度文库现在都看不到文档是否上传成功,要凉了吗?
-
打开知识店铺,百度文库文档里显示都是下载这一按键,上传的文档也看不到是否成功?咋情况,要取消了吗?没通过审核的也不让你删除,是几个意思,想通吃吗?现在百度上传文档也很费劲,有时弄了半天的资料上传审核过...
- 微信推广引流108式:利用百度文库长期分享软文引流
-
百度文库相对于百度知道、百度百科来说,操作上没那么多条条框框,规则上也相对好把握些。做一条百度知道所花费的精力一般都会比做一条百度文库的要多些,老马个人操作下来觉得百度文库更好把握。但见仁见智吧,今天...
- 职场“避雷”指南 百度文库推出标准化劳动合同范本
-
轰轰烈烈的毕业季结束了,众多应届生在经过了“职场海选”后,已正式成为职场生力军的一员。这一阶段,除了熟悉业务,签订劳动合同、了解职场福利也迅速被提上日程。而随着国人法律意识的增强,百度文库内《劳动合同...
- 《百度文库》:素材精选宝库(百度文库官网首页)
-
《百度文库》:独特功能助力选择高质量素材在当今信息爆炸的时代,如何高效地获取并利用有价值的素材成为了许多人面临的挑战。而《百度文库》作为百度公司推出的一款在线文档分享平台,凭借其丰富的资源、强大的功能...
- 深度整合和开放AI能力 百度文库和网盘推出内容操作系统「沧舟OS」
-
【TechWeb】4月25日消息,Create2025百度AI开发者大会上,百度文库和百度网盘推出全球首个内容操作系统——沧舟OS。基于沧舟OS,百度文库APP全新上线「GenFlow超能搭子」...
- 女子发现大二作业被百度文库要求付费下载,律师:平台侵权,应赔偿
-
近日,28岁的黎女士在百度百科搜索家乡的小地名时,发现了自己在大二完成的课题作业。她继续搜索,发现多个平台收录了该文,比如豆丁网和文档之家等,有的还设置了付费或积分下载。2月15日,九派新闻记者以用户...
- 2016杀入百度文库的新捷径,只有少数人才知道的喔
-
百度的产品在SEO优化中的分量真不用多说,其实很多人都像我一样一直在找捷径。但是我经常发现很多人都是在用死方法。比如发贴吧发帖而不知道去申请一个吧主,知道自问自答而不知道去申请一个合作资格。口碑和贴吧...
- 百度文库付费文档搜索方法(百度文库付费文档搜索方法有哪些)
-
一直以来,百度文库中无论是个人中心还是个人主页,都没有像淘宝一样的店内搜索功能,连最近新开的知识店铺也没有设计店内搜索功能,这无论是对上传用户还是下载用户都不方便,上传用户想要搜索自己的文档无法办到...
- 供读者免费使用!泰达图书馆机构版百度文库新年上新啦
-
在泰达图书馆读者使用百度文库数字资源不需要VIP,免-费-用!惊不惊喜?快来了解一下吧……新年伊始,为满足区域企业、高校、科研院所以及居民群众在教学、科研及学习过程中,对各类文献资源的需求,泰达图书馆...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- 如何绘制折线图 (52)
- javaabstract (48)
- 新浪微博头像 (53)
- grub4dos (66)
- s扫描器 (51)
- httpfile dll (48)
- ps实例教程 (55)
- taskmgr (51)
- s spline (61)
- vnc远程控制 (47)
- 数据丢失 (47)
- wbem (57)
- flac文件 (72)
- 网页制作基础教程 (53)
- 镜像文件刻录 (61)
- ug5 0软件免费下载 (78)
- debian下载 (53)
- ubuntu10 04 (60)
- web qq登录 (59)
- 笔记本变成无线路由 (52)
- flash player 11 4 (50)
- 右键菜单清理 (78)
- cuteftp 注册码 (57)
- ospf协议 (53)
- ms17 010 下载 (60)