跳转到正文
Carrey Notes logo Carrey Notes
返回

我觉得一个好的系统应该是什么样子

编辑此页

写在前面

我不是做基础设施出身的人,也不太想把这篇文章写成一篇架构方法论。更多时候,我只是站在开发者的位置参与系统建设:有些项目工期很紧,大家都在赶上线;有些项目节奏没那么夸张,但要长期维护、长期迭代,后面的问题反而更磨人。

这几年我越来越明显地感觉到一件事:一个系统能跑,和一个系统好维护,中间差得很远。

工期紧本身不可怕。真正麻烦的是,团队每次紧起来都只能靠堆人、堆加班、堆临时方案去顶。上线靠人盯,配置靠人记,问题靠熟人定位,交付靠几个人硬扛。短期看好像也能过关,但系统一旦进入长期维护,债就会慢慢显出来。

还有一种场景我印象很深:项目已经乱了、延期了,这时候再往里面塞人,结果往往不是更快,而是更乱。新人需要熟悉业务、代码和各种隐含规则,老人又要停下来解释上下文,沟通和集成成本一下子涨上来。最后大家都很忙,但系统没有因此变得更可控。

所以我现在看一个业务系统,会更关注一个问题:它到底是在减少团队对“人肉记忆、临时协调、个人英雄主义”的依赖,还是一直在把这些东西当作默认方案。

这篇文章想写的不是“什么架构最先进”,而是我自己更认同的一套判断:一个不大不小的业务系统,如果要长期运行、多人协作、持续迭代,至少应该把一些关键能力做成系统能力,而不是长期压在具体的人身上。

先说清楚:我这里说的是什么系统

我这里说的系统,不是特别大的互联网基础设施,也不是一个只跑几个月就结束的活动项目。它更像是公司主营业务相关的系统:团队规模不算小,需求会持续来,线上要长期运行,业务规则会不断变化,参与的人也可能会换。

它可能是单体逐步拆出来的,也可能一开始就是多服务;可能面向外部用户,有登录、账号、安全和权限问题;也可能是内部核心业务系统。它不一定有很高的 QPS,也不一定服务数特别多,但它已经开始出现一些更现实的压力:

我觉得这类系统最容易被低估。它还没大到必须上各种复杂平台,但也已经不适合只靠几个人的经验维持秩序。很多工程问题,正是在这个阶段开始发酵的。

所以本文里的“好系统”,不是指用了多少架构名词,而是指:当系统进入长期变化以后,它还能不能让交付、运行和演进保持在一个相对可控的状态。

好系统的主线:把隐性能力变成显性能力

如果只让我用一句话概括,我会说:

好的业务系统,会尽量把关键能力从“某个人知道”变成“系统本身可追溯、可复现、可协作”。

这句话听起来有点抽象,但放到项目里其实很具体。

上线不是“某个人知道点哪个按钮”,而是有明确流水线、环境配置和回滚路径。

排查问题不是“问一下老同事”,而是有日志、指标、链路、变更记录可以看。

需求推进不是“群里喊一声”,而是有任务状态、负责人、依赖和风险暴露出来。

业务规则不是“代码里翻一下”,而是至少有一份大家共同认可的说明。

代码质量不是“靠某个高手把关”,而是有评审、自动检查和团队共识。

我现在会把一个好系统的底层目标收敛成三个词:交付、运行、演进。

交付,指的是功能能稳定、可预测地上线,而不是每次都靠临时爆肝。

运行,指的是线上出了事能尽快定位、尽快恢复,而不是全靠某个人的经验。

演进,指的是系统在需求变化、人员变化、依赖升级以后,仍然改得动,不会动不动牵一发动全身。

很多系统的问题不是今天跑不起来,而是半年以后没人敢改。代码还在,服务也还活着,但每次改动都要靠猜、靠问、靠小心翼翼地试。这时候系统表面上没崩,实际上已经开始变重了。

我会用几个很朴素的问题看系统是不是在变好:

  1. 我们多久能上线一次?
  2. 一次改动从写完到上线,要拖多久?
  3. 上线以后回滚、补丁、返工的比例高不高?
  4. 真出事故了,从发现到恢复要多久?

这些问题和业内常说的 DORA 指标很接近。但对我来说,它们不是为了做 KPI,而是为了让团队看清楚:所谓工程改造,到底有没有让系统更可控,还是只是换了一套更复杂的工具。

说到演进,我也会自然想到两本书。《数据密集型应用系统设计》反复强调可靠、可扩展、可维护这些长期主题;《领域驱动设计》关注的是业务复杂以后,系统怎么跟着业务一起演进。它们给我的启发不是“所有系统都要上复杂设计”,而是:如果一个系统注定要长期变化,那就不能只按“现在能跑”来设计。

平台化底座:把运行方式收进系统

很多开发对平台化的期待其实没有那么玄。大多数时候,我们只是希望:

没有统一底座的时候,很多事情单看都不大:端口怎么分、机器怎么选、哪个服务依赖哪个配置、哪台机器还在跑旧版本、发布顺序有没有要求。可是一旦服务和环境多起来,这些小事就会变成稳定的心智负担。

我现在比较倾向于:当服务和实例规模开始上来以后,能用 Kubernetes 这类统一运行底座,就尽量往这个方向靠。原因不是它“高级”,而是它把很多原来散落在人脑、脚本和文档里的运行约定,收进了一套声明式模型里。

你描述应用应该怎么跑、需要什么资源、怎么探活、怎么升级、怎么扩缩容,平台按这些规则去调度和执行。这样做的价值不是让架构图更好看,而是把运行过程变得更可描述、更可重复,也更容易交接。

当然,我不认为所有项目一开始都应该上 Kubernetes。如果团队规模小、服务少、发布频率不高,Jenkins 加注册配置中心,再配合一些规范,也完全可能够用。问题在于:够用不等于长期省心。

当系统变多、团队变多、环境变多以后,靠约定和零散配置维持一致性,会越来越吃人。今天某个脚本只有一个人懂,明天某个环境只有一个人知道差异,后天某次发布只有一个人敢操作。技术栈本身不一定落后,但运行方式已经变成了隐性知识。

Kubernetes 也不是没有代价。它不是装上以后就可以永远不管,版本升级、集群治理、资源模型、权限隔离、镜像和配置管理,都会变成长期工作。我的判断更像是:如果你的系统已经开始被手工运维、环境差异和发布不可控拖住,那平台化的成本可能比长期靠人扛更划算。

Git 化:让变更能被看见

我很认可 Git 化,但我理解的重点不是“所有东西都放 Git 里”这么简单。它真正解决的问题是:系统不要靠人的记忆维持运转。

一个系统里最危险的东西,往往不是复杂代码,而是那些没人说得清的变更:某个生产配置是谁改的,为什么改,改之前是什么,出了问题怎么退回去;某条流水线为什么加了一个特殊参数;某个环境为什么和其他环境不一样。

这些东西如果只存在于聊天记录、截图、临时文档和某个人脑子里,平时可能没感觉。一旦线上出问题,大家就会开始翻群、问人、猜最近谁动过什么。这个过程很消耗人,也很容易错过真正原因。

所以我更愿意把 Git 化理解成一句话:

把关键变更过程变成可追溯、可回滚、可复现的。

落地时,至少这些内容应该尽量进入版本管理:

这样做的价值在平时不一定显得很大,但出问题时会很明显。你不用先猜“最近发生了什么”,而是可以从提交历史、变更记录和配置差异里找到线索。人员流动时,也不会因为某个人离开,系统的一部分运行知识就跟着消失。

对我来说,Git 化不是仪式感,而是系统把记忆从人身上拿回来的过程。

项目管理:不是为了管人,是为了暴露状态

我以前对项目管理这件事没有那么强的感觉,后来发现很多交付问题并不是代码写不出来,而是状态一直不透明。

需求在群里飘来飘去,最后到底谁负责并不清楚;每个人都很忙,但没人说得清整体进度;风险靠口头同步,传几轮以后信息就变形;临近交付才发现关键依赖没对齐,于是开始互相催、互相解释、互相觉得对方不靠谱。

这种情况下,团队很容易把问题归因到“沟通不够”或者“责任心不够”。但很多时候,真正缺的是一张大家共同承认的状态图。

我不觉得项目管理一定要复杂。一个看板、一套状态流转规则、明确负责人、明确截止时间和依赖关系,已经能解决很多问题。关键是团队要有一个共同认可的事实来源:现在在做什么,卡在哪里,谁需要谁,风险什么时候暴露出来。

有了这个东西,沟通会从“我解释一下我最近在忙什么”,变成“我们一起处理这个卡点”。压力大的时候,也更容易做取舍:是砍范围,是加资源,是调整顺序,还是承认当前方案不现实。

所以我看项目管理,不是看工具多漂亮,而是看它有没有把协作状态从口头承诺变成可见信息。看不见的项目,最后一定会靠人催;靠人催久了,团队关系也会被消耗。

文档化:把业务上下文留在系统里

很多团队不喜欢写文档,我能理解。文档经常过期,也经常写完没人看。如果只是为了显得规范,确实没什么意思。

但长期项目里,文档真正的价值不是“好看”,而是减少上下文丢失。

新人上手只能靠带、靠问;业务规则全靠口口相传;同一个概念每个人叫法不一样;某段历史逻辑没人敢动,因为谁也不确定当初为什么这么写。到这个阶段,团队经常会误以为自己缺的是更强的人,其实更缺的是共享上下文。

我心里比较实用的文档标准是:它不需要覆盖所有细节,但要能解释系统为什么是现在这样。

至少这些内容应该讲得清楚:

尤其是业务系统,很多复杂性并不在代码技巧里,而在业务规则和历史包袱里。如果这些东西不沉淀,后面每一次改动都要重新考古。系统越老,这个成本越高。

我不认为文档能解决所有问题,但它至少能让系统的上下文不完全依赖人。对长期演进来说,这已经很重要了。

代码评审:把质量变成团队能力

代码评审也容易被做歪。做得不好,它会变成挑格式、挑写法、表达个人偏好的地方;做得太重,又会让大家害怕提交。

我更认可的评审目标有三个:

第一,把风险前移。很多问题如果等到测试、上线甚至线上事故才暴露,修起来代价会高很多。评审不是为了证明谁厉害,而是尽早发现会影响维护和运行的风险。

第二,让团队形成一致的工程标准。命名、异常处理、日志、事务边界、接口兼容、必要指标,这些东西如果每个人都按自己的习惯写,系统很快就会变成风格拼盘。风格拼盘不只是难看,真正的问题是后面的人很难判断“这里到底有没有约定”。

第三,让知识扩散。长期系统最怕某一块只有一个人懂。评审至少能让更多人知道某个改动为什么这么做、影响哪些地方、有没有更简单的方案。

我会更倾向于从很务实的方式开始:

好的评审机制不会让项目越写越怕改,而是让团队越来越知道什么样的代码更容易接得住后续变化。

最后:好系统不是没有问题,而是问题能被系统接住

我现在不会用“用了什么技术栈”来判断一个系统好不好。技术当然重要,但更关键的是:系统出了问题以后,团队有没有抓手;需求变化以后,系统还能不能改;人换了以后,知识会不会断;项目紧起来以后,是不是只能靠大家硬扛。

一个好的中型业务系统,不一定看起来很先进,但它应该尽量做到:

这些东西单独看都不炫,但它们会决定系统在长期变化里是越来越稳,还是越来越依赖少数人救火。

对我来说,好的系统不是完全不出问题。真正重要的是:问题出现以后,不是只靠某个人想起来、某个人站出来、某个人熬夜顶住,而是系统本身已经准备好了一些机制,把问题接住、暴露出来、定位下去,并且让下一次变得更容易处理。


编辑此页
分享这篇文章: