时间:2020-3-15来源:本站原创作者:佚名

盛赫

叮~,您有新的饿了么订单,正在阿里云上被接单。

这篇文章成型于交易系统重构一期之后,主要是反思其过程中做决策的思路,我没有使用「架构」这个词语,是因为它给人的感受充满权利和神秘感,谈论「架构」让人有一种正在进行责任重大的决策或者深度技术分析的感觉。

如毕玄在系统设计的套路这篇文章里所提:回顾了下自己做过的几个系统的设计,发现现在自己在做系统设计的时候确实是会按照一个套路去做,这个套路就是:系统设计的目的-系统设计的目标-围绕目标的核心设计-围绕核心设计形成的设计原则-各子系统,模块的详细设计在进行系统设计时,摸清楚目的,并形成可衡量的目标是第一步。"Soft"wareSoftware拆开来分别是software,即灵活的产品。--鲍勃大叔重构前的交易系统第一版的代码可以追溯到8年前,这期间也经历过拆解重构,7年我来到时,主要系统是这样:

这套系统驮着业务从百万级订单跑到了千万级订单,从压测表现来看,它可以再支撑业务多翻几倍的量,也就是说如果没有啥变化,它可以继续稳定运行着,但如果发生点变化呢,答案可能就不这么肯定了。

在我入职的这两年里,系统承载的业务迭增变化:从单一的餐饮外卖到与新零售及品牌餐饮三方并行,又从到家模式衍生至到店,随之而来的是业务持续不断的差异化定制,还有并行上线的要求。另一面,随着公司组织架构变化,有的项目需要三地协同推进才能完成,沟通协作成本翻倍提升。几方面结合起来,导致开发没有精力对大部分系统的演进都进行完善的规划。几个月前,业务提了一个简单的需求:对交易的评价做自动审核并进行相应的处罚。当时评价核心“域模型”是这样的:设计自身的优劣这里暂不进行讨论,只是举例说明为了满足这个诉求,会涉及多个评价子模块要改动,开发评估下来的工作量远远超出了预期,业务方对此不满意,类似的冲突在其他系统里也经常出现。但实际上,团队里没人偷懒,和之前一样努力工作,只是不管投入了多少个人时间,救了多少次火,加了多少次班,产出始终上不去,因为开发大部分时间都在系统的修修补补上,而不是真正完成实际的新功能,一直在拆东墙补西墙,周而往复。为什么会导致这样的结果,我想应该是因为大部分系统已经演变到很难响应需求的变更了,业务认为的小小变更,对开发来说都是系统的一次大手术,但系统本不应该往这个方向发展的,它和hardware有着巨大的区别就在于:变更对软件来说应该是简单灵活的。所以我们思考设计的核心目标:“采用好的软件架构来节省项目构建和维护的人力成本,让每一次变更都短小简单,易于实施,并且避免缺陷,用最小的成本,最大程度地满足功能性和灵活性的要求”。Sourcecodeisthedesign提到软件设计,大家脑袋里可能会想到一幅幅结构清晰的架构图,认为关于软件架构的所有奥秘都隐藏在图里了,但经历过一些项目后发现,这往往是不够的。JackReeves在99年发表了一篇论文《源代码即设计》,他在文中提出一个观点:高层结构的设计不是完整的软件设计,它只是细节设计的一个结构框架。在严格地验证高层设计方面,我们的能力是非常有限的。详细设计最终会对高层设计造成的影响至少和其他的因素一样多(或者应该允许这种影响)。对设计的各个方面进行改进,是一个应该贯穿整个设计周期的过程。在踩过一些坑之后,这种强调详细设计重要性的观点在我看来很实在接地气,简单来说:“自顶向下的设计通常是不靠谱的,编码即是设计过程的一部分”,个人认为:系统设计应该是从下到上,随着抽象层次的提升,不断演化而得到良好的高层设计。编程范式从下向上,那就应该从编码开始审视,饿了么交易系统最开始是由Python编写,Python足够灵活,可以非常快速的产出mvp的系统版本,这也和当时的公司发展状态相关:产品迭代迅速,新项目的压力很大。最近这次重构,顺应集团趋势,我们使用Java来进行编写,不过在这之前有一个小插曲:7年底,因为预估到当前系统框架在单量到达下一个量级时会遇到瓶颈,所以针对一些新业务逐渐开始使用Go语言编写,但在这个过程里,经常会听到一些言论:用Go来写业务不舒服。为什么会不舒服?大致是因为没有框架,没有泛型,没有trycatch,确实,在解决业务问题的这个大的上下文中,Go语言不是最优的选择,但语法简单,可以极大程度的避免普通程序员出错的概率。那么Python呢,任何事物都有双刃剑,虽然Python具有强表达力,但是灵活性也把很多人惯坏了,代码写的糙,动态语言写太多坑也多,容易出错,在大项目上的工程管理和维护上有一定劣势,所以rails作者提到:“灵活性被过分高估——约束才是解放”也有一定道理。为避免引起语言战,这里不过多讨论,只是想引出:我从C++写到Go,又从Python写到Java,在这个过程里体会到--编程范式也许是学习任何一门编程语言时要理解的最重要的术语,简单来说它是程序员看待程序应该具有的观点,但却容易被忽视。交易老系统的代码,不管是针对什么业务逻辑,几乎都是OPP一杆到底,类似的代码在系统里随处可见。我们好像完全遗忘了OOP,这项古老的技艺被淡化了,我这里不是说一定要OOP就是完美的,准确来说我是“面向问题”范式的拥趸者,比如,Java从骨子里就是要OOP,但是业务流程不一定需要OOP。一些交易业务就是第一步怎么样,第二步怎么样,采取OPP的范式就是好的解法。这时,弄很复杂的类设计有时并不必要,反而还会带来麻烦。此外,同一个问题还可以拆解为不同的层次,不同的层次可以使用各自适合的方式。比如高层的可以OOP,具体到某个执行逻辑里可以用FP,比如:针对订单的金额计算,我们用Go写了一版FP的底层计算服务,性能高、语法简单以及出错少等是语言附带的优点,核心还是因为该类问题自身适合。然而,当面向整个交易领域时,针对繁复多样的业务场景,合理运用OOP的设计思想已经被证明确实可以支撑起复杂庞大的软件设计,所以我们作出第一个决策:采用以OOP为主的“混合”范式。原则和模式Thedifferencebetweenabadprogrammerandagoodoneiswhetherheconsidershiscodeorhisdatastructuresmoreimportant.Badprogrammersworryaboutthecode.Goodprogrammersworryaboutdatastructuresandtheirrelationships.--LinusTorvalds不管是采用哪种编程范式、编程语言,构造出来的基础模块就像盖楼的砖头,如果砖头质量不好,最终大楼也不会牢固,引用里的一大段话,relationships才是我最想强调的:我理解它是指类之间的交互关系,“关系”的好坏通常等价于软件设计的优劣,设计不好的软件结构大都有些共同特征:僵化性:难以对软件进行改动,一般会引发连锁改动,比如下单时增加一个新的营销类型,订单中心和相关上下游都要感知到并去做改动。脆弱性:简单的改动会引发其他意想不到的问题,甚至概念完全不相关。牢固性:设计中有对其他系统有用的部分,但是拆出来的风险和成本很高,比如订单中心针对外卖场景的支付能力并不能支持会员卡等虚拟商品的支付需求。不必要的复杂性:这个通常是指过度设计。晦涩性:随时间演化,模块难以理解,代码越来越难读懂,比如购物车阶段的核心代码已经长成了一个近千行的大函数。...采取合适的范式后,我们需要向上抽一个层次,来







































北京哪个医院可彻底治愈白癜风
澳门治疗白癜风最好的医院

转载请注明原文网址:http://www.imeimeishou.com/tbyx/9588.html
------分隔线----------------------------