这些感悟并非来自于具体的技术实现,而是关于我在架构设计和实施过程中所体会到的一些软性经验和领悟。我希望通过这些分享,能够激发大家对于架构设计和技术实践的思考,帮助大家更好地理解和应用架构原则和方法。
一、“提出问题”难于“解决问题”
在我看来,我最近的一个重要感悟是:提出问题要比解决问题更具挑战性。作为一个工程师,我通常习惯于解决问题,因为这是我们的工作之一。但是,我意识到我很少主动提出问题,尤其是从用户的角度出发去提出问题或需求。我发现,这种不主动提出问题的倾向可能导致团队内部的沟通障碍,特别是与产品经理等其他团队成员的交流。
有时候我们会抱怨产品经理不懂技术,提出的需求不够专业。但是,我开始思考,作为工程师,我是否应该更加积极地从用户的角度出发,去了解用户真正的困惑,并提出合理的需求来解决它们。或者,我是否可以亲身体验用户的场景,然后提出全新的问题并解决它们。
我认为,我们不仅仅应该是解决问题的人,还应该是提出问题的人,主动去思考如何能够让业务更加先进。尽管设计架构、编写代码解决问题是一项很棒的工作,但是当我尝试主动提出问题和改进用户需求时,我发现这其实是一项更加困难的任务。我觉得这种思维转变,对于我个人的职业发展和团队的成功都是非常重要的。
二、决定“不要什么”比“要做什么”更难
在我看来,我最近的第二个重要感悟是:决定“不要什么”比“要做什么”更具挑战性。或许这是因为人性的本质是贪婪的,所以在项目或架构设计中,我们常常倾向于尽可能包含更多功能和需求,特别是对于非功能性需求更是如此。
当我们审查一个架构设计说明书时,往往会看到对高可用性、高性能、高扩展性、高可维护性等需求的强调,几乎所有的架构设计都会列出这些非功能性需求。这些需求似乎成了一个共识的列表,认为所有的架构都必须满足这些需求。当然,功能性需求更是不胜枚举,产品经理会不断地添加。
然而,回过头来仔细思考,什么是架构?实际上,在很多层面上,架构是一种权衡和平衡的结果。作为一个架构师,你应该是那个能够明确说出“不要”的人。在现实中,很多东西是无法兼得的。比如,是尽早发布产品,还是等到所有功能都完善再发布;又比如,在一致性和性能之间需要取舍,我们是选择强一致性,还是牺牲一致性以换取更高的性能等。CAP 原则就是这样一个关于权衡的准则。
因此,作为架构师,我强烈建议大家在架构设计的初期就确定一些原则。例如,数据一致性优先级最高,或者尽早发布基础功能版本优于延迟发布完善功能产品等。当面临冲突时,我们可以利用这些原则进行取舍和决策。
三、非功能性需求决定架构
在我看来,我最近的第三个重要感悟是:非功能性需求决定架构。在很多人眼中,做架构的第一步是收集各种功能性需求,因为最终的产品是为用户服务的。
然而,事实并非如此。一个优秀的架构实际上是由非功能性需求所驱动,而不是由功能性需求所驱动。你会发现,对于一个功能,可以有很多种不同的架构方案来实现,但是你为什么选择某个方案,其实是由非功能性需求来决定的。
大家都非常清楚什么是非功能性需求,包括性能、伸缩性、可扩展性、可维护性等,甚至还包括团队的结构、技术水平、发布周期要求等等。通过这些需求来筛选可用的方案,最终找到一个合适的架构。
因此,非功能性需求在架构设计中扮演着至关重要的角色,可以说是决定性因素之一。设计完架构后,如果缺少某个功能性需求,我们很容易意识到并且可以进行补充,它不会对架构产生根本性的影响。但如果我们忽略了某个非功能性需求,那么在未来可能会导致严重的问题,甚至需要重写架构。例如,如果架构中的数据一致性问题无法解决,或者在设计阶段没有充分考虑性能问题,那么所有的功能性实现都会变得毫无意义。这基本上就是重构,甚至可以说不应该叫重构,而是应该叫重新创建或者重写,因为你需要彻底重新设计整个架构。
实际上在架构领域,大家对这点也是有共识的。比如下图中这个 Micro-Kernel 的架构模式来自《面向模式的软件架构》的第一卷,它一大特点就是有比较好的可扩展性,同时通过 Plugin 之间的隔离,能够提高系统的可用性。
“简单"并不容易
在我看来,我最近的第四个重要感悟是:“简单”并不容易。许多架构师都会强调保持简单,但很多时候我们会混淆简单和容易。简单是指简洁、清晰,而容易是指易于实现、理解或操作。我们应该努力保持简洁,而不是追求轻松的实现。
正如乔布斯所说,简单有时比复杂更难,因为它需要对问题、事物的深入研究,才能找到真正简洁的解决方案。简单实际上是一种巧妙的设计和思考。
举例来说,布隆过滤器就是一个简单而高效的重复数据过滤算法,它巧妙地解决了一个问题。如果想要使某件事情变得简单,就需要进行大量深入的工作。例如,简化架构很大程度上取决于我们对技术、开发过程以及不同业务场景的深入理解,而不仅仅是架构本身的设计容易与否。
因此,保持简单并不容易,它需要我们深入理解问题的本质,并找到最优雅、最有效的解决方案。
举个例子,我们来回顾一下软件生命周期中各个阶段的成本消耗占比。
可以看到,在整个软件生命周期中,成本消耗最高的并不是设计、编码这些阶段,而是维护阶段。也就是说,如果你让维护变得简单,这会是最有性价比的。
五、永远不要停止编码
在我看来,我最近的第五个重要感悟是:永远不要停止编码。这一点非常重要,特别是对于一个架构师来说,要牢记自己始终是一名程序员。作为架构师,我们可能设计了一个高层次的架构,但实际上,代码才是软件的最终实现形式。每个程序员在架构落地的过程中的实现,都可能影响最终的架构呈现。
此外,如果你停止编码,最大的影响不是技术上的滞后或代码编写速度变慢,而是你可能会逐渐失去对编程的敬畏之心,忘记作为程序员的体验,特别是编码过程中的那些挑战与痛苦。你可能会陷入一些不切实际的幻想,做出一些不切实际的设计,这才是最大的问题。
我们都熟悉 Java 的创始人 James Gosling,在亚马逊担任杰出工程师的职位,相当于高级副总裁,但他依然坚持编码。他每年编写的代码量是惊人的,常常超过 10 万行。这个事实告诉我们,无论职位有多高,作为一个技术人员,始终保持对编码的热爱和投入是至关重要的。
六、风险优先
在我看来,我最近的第六个重要感悟是:风险优先。
让我们先思考一个问题:为什么要进行架构设计?在我看来,架构设计的主要目的是转化、降低、甚至避免整个开发过程中的风险。作为架构师,我们的一个主要责任就是在项目的早期阶段识别出系统可能存在的风险,并通过我们的设计来转化、消除这些风险。
我们经常提到的原型方法或者架构切片的快速迭代方式,实际上也是在早期尽量测试风险,评估我们的架构是否能够解决相关问题,特别是那些非功能性需求的实现风险。这些风险往往不像功能性需求那样容易在项目初期被发现,但是修正它们的成本通常比修正功能性需求要大得多,甚至可能导致整个项目的失败。
比如敏捷开发,很多人认为敏捷开发只是更快地开发出一个产品,然后快速地将其交付到市场上,但这只是敏捷的一部分。另一个很重要的方面是,如果一个项目注定要失败,那么就要尽早地让它失败,绝对不能将风险留到最后。这也是敏捷方法的一种体现。
在这里,我想推荐一本书《Just Enough Software Architecture(恰如其分的软件架构)》。这是一本非常流行的架构书籍,强调了架构设计的目的是为了化解软件实现中的风险。如果项目中的所有风险都可以通过未来的重构来解决,那么你根本就不需要进行架构设计,直接等待重构即可。这也是我非常赞同的观点:风险优先。
从“问题”开始,而不是“技术”
我最近的第七个重要感悟是:从“问题”开始,而不是“技术”。
作为技术人员,我们往往会很乐意学习新技术,并且一旦掌握了这些技术,就会有强烈的欲望去应用它们。有时候我们甚至会感觉自己被某个技术所“上身”,迫不及待地想要将其应用到工作中,而忽略了当前手头上的问题是否适合用这个技术来解决。或许你也有类似的经历。
冷静下来想想,我们每个人都明白,应该从实际需求、用户问题出发,而不是一味地从技术角度考虑。然而,在实际工作中,我们常常不自觉地忽略了这一点。就像拿着一把锤子,看到什么都想当作钉子来敲。
然而,这种做法可能会带来很大的害处。让我来分享一个故事,来自我之前工作过的一个团队。
在那个团队中,有一位工程师维护着一个简单的服务,使用 MySQL 作为数据存储。后来,他对当时新出的 DynamoDB 产生了兴趣,并学习了相关知识。结果发生了以下情况:他决定使用 DynamoDB 替换 MySQL,但这却成为了一个噩梦的开始。很快就发现 DynamoDB 并不能很好地支持事务特性,而且性能极差的客户端类库导致了性能问题,效率大大降低。
于是,他又尝试使用最终一致性技术,采用消息队列来实现。但随之而来的是,实现相同功能的复杂性大大增加,维护成本也由一个人变成了整个团队。
这个故事告诉我们,我们对技术的热情有时会让事情变得更加复杂,甚至会带来额外的烦恼。我们应该始终从问题出发,而不是被技术所驱动。
八、过度繁忙使你落后
我最近的第八个重要感悟是:过度繁忙使你落后。
对于IT人员来说,忙碌已经成为了一种习惯,加班似乎也成了公司高效的标志,“996”甚至变成了一种常态。但是我们有时候需要反思一下,有多久没有在业余时间看与技术相关的书了?我曾经在公司里问过这个问题,百分之百的人都告诉我,下班后已经很晚了,回到家基本上没有时间再看书,刷一下手机,就可以直接睡觉了。这是一个非常值得我们去思考的问题。
作为技术人员,如果你不更新你的知识,或者繁忙让你没有时间更新知识,那会有什么样的结果呢?让我分享一个有趣的现象,我遇到过不少程序员,有些是之前的同事,有些是朋友。他们换了一份新工作,一开始进入那家公司时会说,“这个公司我不是特别看好,我了解一下它的技术,就准备跳槽了。”可是过了两三年,我再问他们,“为什么还在这里,还没跳槽?”结果他们告诉我,“我觉得现在的招聘形势不太好,不太好找新的机会。”几年下来,他们对公司越来越“忠诚”了。实际上,在一个公司忙碌工作几年,没有留出时间学习,导致他们失去了跳槽的能力和勇气。当他们想要重新回到市场时,却发现自己已经落伍了,技术已经过时了,甚至已经被淘汰了。
在这个高速发展的时代,如果因为过度忙碌,导致你没有时间学习和更新自己的知识,那必然会让你落后。即使你不跳槽,呆在同一家公司里,公司的业务不断发展,数据量会越来越大,用户需求也会越来越复杂。如果你长期不更新知识,掌握的技能没有发生变化,你会觉得越来越难以应付,最终只能通过不断地加班来应对。
另外,还有一种可能是,你不更新知识,不深入思考,那么很大概率,你所创造的技术和业务丧失了领先性,没有领先优势,只能被动紧紧跟随竞争对手。而紧紧跟随就意味着你只能加班,这将导致更多的忙碌,更少的时间用来学习和提升自己的技能。这实际上是一个恶性循环,你花越多的时间去忙碌,就越没有时间去学习,去提高自己的工作技能,最终只能靠加班来追赶,结果就更加忙碌,更加没有时间学习,最终你将陷入一个无法自拔的恶性循环中。
当我在某个领域工作了一段时间后,比如三五年之后,我会逐渐变得对该领域的业务越来越熟悉,解决问题也会变得更加顺手。但与此同时,我也会意识到能够学习到的新知识和技能会逐渐减少。有些人可能会建议我离开这个舒适区,尝试去另一个领域,以激发学习新知识的动力。但我觉得并不需要这么做。
我认为,即使留在原来的领域,我也可以通过一些方法来持续学习和成长。我可以有意识地摆脱舒适感,挤出时间来重新学习,然后尝试以不同的方式解决问题。即使在相同的领域中,我也可以探索新的方法和技术,从而提升自己的能力。
通过持续学习和不断探索,我可以在工作中保持活力,并不断地提升自己的竞争力。这种积极的学习态度和探索精神对于我的职业发展是非常重要的,它能够让我保持在一个不断成长的状态中。