浅谈业务系统设计哲学
作者:易振强
1. 背景
设计和开发业务系统是一个很“神奇”的工作,我已经在软件行业工作多年,遇见过各种类型的业务研发工程师,干我们这行的人都知道,软件开发入门门槛没像外行人所认为的那样高,当然,这个行业也绝对不乏“高手”。再回到之前说的,为啥我会认为设计和开发业务系统是一个很“神奇”的工作?因为“开发工程师”这职位应该是软件行业人数最多的群体,我们如今在PC或者手机上用到的各式各样的软件都离不开他们,在这一职位上,我们能结识各式各样的人,所谓历经人生百态。
可能有很大一部分工程师认为开发业务系统很简单,所以对这一日常工作内容不那么感冒,他们常常用自己“六七分”实力来做设计、写代码,所以也容易导致工作七八年,写过“一麻袋”的业务系统,但自身能力提升较慢,最后自我埋汰到:“写了这么多年业务系统代码,都把自己都写废了”。
我们当然不希望自己是这样的结局。
2. 业务系统的设计哲学
2.1 可维护性是根本
系统也需要人来“保养”
代码可读性很关键
打造可扩展系统
把这个放第一条,有些人会感到意外,如何理解这里的“可维护性”?简单来说就是我们的业务系统——
1.能否在当前组织模式下满足业务的发展而进行快速迭代;
2.能否为了承接增长的流量而横向快速扩容;
3.能否支持团队内多人协作维护;
4.能否支持快速对线上问题进行定位和止损;
5.运维成本能否可控。
可维护性和系统的架构设计和编码实现高度相关,这里很有必要说下设计的实现部分——编码,编码是开发阶段很重要的一环,其实很多一线研发工程师的能力,在写代码时就能“高下立判”。
那么业务系统编码阶段最重要的是什么?这个问题很多人会有不同的答案,但我这边的答案只有一个:
即——在正确实现功能的前提下让代码具备较高的可读性。我在进行CR时,会非常看重这一点。代码可读性并不等同于你的代码一定要写的很短或很精炼(但是短代码或格式规整的代码确实能降低阅读者负担,让阅读者赏心悦目),而是说一定得说明这段代码为什么这么做(加注释也好,代码能自说明也好),特别是某些“特殊逻辑”!
之所以在这里特别强调这一点,是因为业务系统总在随着业务不断在迭代,“铁打的代码流水的猿”,只要业务活得够久,你永远不知道下一个维护这套系统的人是谁、是哪个团队,而系统的可维护性、可扩展性、稳定性、重构等,强依赖的是后续继承者能看懂你写的代码,千万不能造成:我很懂业务,但我看不懂你代码为什么这样写,尴尬的是我又不敢改。
特别怕一些“天赋异禀”的开发者,用“很巧妙”的思路将业务系统实现的只有他自己能懂,而其他人“望而生畏”,导致后续遭人诟病,所以我们需要记住,只有学习成本低,系统才能谈可维护性。
2.2 稳定性是底线
充分拆解背后的非功能性诉求
核心资源和非核心资源需要隔离
尽可能做到自动降级
实现异常出口
任何业务系统不能只满足基本的业务功能需求,很多非功能性需求产品和业务方同学不一定会直接展现在PRD上,需要我们研发工程师或架构师来“拿捏”,常见的非功能性需求比如系统稳定性、吞吐量、性能、响应时间、时效性、数据安全性、数据一致性等。这其中,系统稳定性是最常见的非功能性需求,也是很多大型互联网公司业务方能直接感知到产研的一面,一旦系统故障被用户投诉,业务方第一直觉就是技术那边出了问题。
系统稳定性建设的抓手很多(参见:稳定性全系列文章),一线研发同学在设计和实现时,一定得有自己的原则和意识,比如核心接口和非核心接口的资源隔离(例如线程池、部署隔离等);弱依赖做到真正的弱依赖,出问题不能影响核心链路(设置合理的超时时间,能做到自动降级或熔断最好);关键资源一定得受保护(比如借助SDS、Sentinel、Hystrix等)和监控;异常情况得可看、可感知(配置合适并且有效的告警策略和大盘)。
系统稳定性犹如工程师的底子,不能随便拿出来到处说,但需要花精力花功夫不断去维护和巩固,一旦没做好,鬼知道别人背后咋说你。
2.3 多参考业界的成功模式
GoF的23种设计模式
面向对象的X大设计原则
学习业界的成功或失败案例
合理利用设计模式,遵循面向对象的设计原则,有了这些大家熟知的模式,会降低整个业务系统的学习成本,无形中也优化了系统的内部结构,提升了系统的可扩展性。
研发工程师或架构师得有自己的独立思考能力和创造力,但创新这东西我们不能强求,很多成功的设计或方案,都是在前人的成功或失败经验加上自己的一些因地制宜的“变化”而“长”出来的,我们在做业务系统架构设计时应该多看看行业标杆如何做,他们这样做的效果是什么?目前他们遇到的问题是什么?他们的方案有哪部分是不适合我们的?
有了这些,哪怕是“管中窥豹”,根据以往经验,我们也能看出个所以然来。
2.4 选择恰当的设计方案
中间件的设计方式不一定适合业务系统
方案选型要考虑团队的技能水位
方案要符合项目当前的发展阶段
重点评估方案的维护成本
从多套方案中选择最合适的方案
一个系统的架构是客观存在的,在业务系统进行架构设计时,一定要结合业务形态、非功能性诉求、当前组织架构、团队技能水位、现有基础设施、运维资源等。
业务形态
要考虑如下问题:服务的可靠性和准确性是否会影响用户的生命财产安全?服务的用户人群是什么?服务是否有早晚高峰期?服务是否要存储大量数据?服务流量如何?
非功能性诉求
即非功能性需求,架构设计时一定要充分挖掘隐藏在业务背后的一些需求,比如给心跳起搏机开发软件系统,其他的可以不提,但一定要绝对的安全和可靠。
当前组织结构
我们当然应该避免多个团队去维护一个系统,所以系统拆分力度一定要和组织结构相当或细于组织,这本质上和"康威定律"也有些关系。
团队技能水位
这是一个很残酷的现实,团队应该去维护和发展符合自己能力的系统,如果某个框架或某项技术是该系统架构设计的关键,而这个框架或技术是团队短时间内无法有效承载的,那这就不是合适的架构设计。我们不能把屠龙刀才能砍的架构设计,去丢给手里只有菜刀的程序猿来实现。
现有基础设施
底层设施决定上层建筑,我们需要有效的利用周边的基础设施,如果没有MQ的使用经验,但我们的架构设计却强依赖MQ,除非你希望借这个业务系统的实现来“培养”一些MQ专家出来,那么我们架构设计时最好将MQ换成另一个“现成”技术套件。
运维资源
这也是一个残酷的现实,我们很多架构设计需要考虑运维团队,甚至很多架构师在设计系统时,会主动去和运维同学沟通,参考他们的建议,这样做没错,有好的运维团队支持,你的系统成功了一半。
业务系统和中间件系统的设计和实现思路有差别,中间件系统可以“无止境”的去打磨系统的性能和扩展性,很多技术大牛在给中间件添砖加瓦时怎么巧妙怎么来,所以有时候中间件代码的可读性并不高(当然,不排除某些中间件产品在这方面做的很好),往往中间件系统关注的点和业务系统的关注点大相径庭,尽量不要以中间件的思路去写业务系统,否则容易走极端。业务系统的设计和开发一定得带着理解业务的思路去做。避免过度设计或过于前瞻性设计(如果真有必要,这些可以放到二期、三期去做),不然会给系统实现增加负担,得不偿失。如果拿捏不准,可以先给出多套设计方案,然后再仔细分析,权衡利弊来做选择。
这里有个遗留问题,就是怎样的系统架构设计才是合格的设计?我认为,只有能抓住现阶段业务成败关键点的设计才是合格的架构设计方案(就好比只有准确抓住社会主义初级阶段社会的主要矛盾,才对党和国家工作重点的转移、推动社会生产力的发展和社会全面进步,具有重大的理论意义和实践意义)。所以,这也从侧面验证了,架构设计可以“扣”细节,只要这些细节会影响系统建设的成败,那么架构设计就应该包含它。
3. 总结
好的设计方案一定要被大多数人所接受和理解的,那些只有少数一两个人能看懂的方案,要不另辟蹊径(风险高),要不其实是过度设计(性价比低),当然,我们说的是一般情况,在某些业务领域,确实是存在一些“最佳方案”。
更多精彩文章,请扫码或长按下方二维码阅读原文
版权声明: 本文为 InfoQ 作者【滴滴普惠出行】的原创文章。
原文链接:【http://xie.infoq.cn/article/a4d7ca6384daabc1eb71f238e】。文章转载请联系作者。
评论