更简单的架构如何让我成为更好的高级开发者

0 阅读5分钟

How Simpler Architectures Made Me a Better Senior Developer

设计更简单且有效的架构的技巧

我过去认为图中的框框越多,设计就越好。在多年参与大型企业系统开发后,我学到了相反的教训;

大多数系统不是因为工具不足而失败,而是因为它们拥有太多工具而失败

以下是五种重塑了我对系统设计思考方式的架构实践。

仅在必要时拆分系统

我们曾从一开始就使用微服务构建了一个支付系统。想法是构建一个从一开始就具有可扩展性的系统

即使流量较低,每个支付请求也会触发多个网络调用。任何服务的故障都会导致整个支付失败。

除此之外,调试是个头疼的问题。它需要跨日志搜索和团队间协调。

此外,即使是简单的更改也需要在依赖的服务中进行部署。

让我们简化这个架构:

通过去除物理分隔同时保持逻辑边界,我们显著减少了故障模式。部署现在更简单了。调试现在更快了。

当扩展需求出现时,我们可以将使用最频繁的一个服务提取出来,变成它自己的微服务。

避免过度抽象

我们继承了一个难以维护的订单管理系统。我们的第一反应是通过添加抽象层来清理它;引入了通用服务、共享存储库和基类来“标准化”行为。结果比以前更糟了。

理解订单流程需要跨越界面和基类。业务规则分散在各个层级,使得即使是简单的修改也变得昂贵;抽象消除了重复,但也消除了意义。我们改变了方法。

我们不再使用通用层,而是将工作流明确化。订单创建、定价和履行都存在于具体的代码中。仍然存在一些重复,但这是有意为之且显而易见的。改动变得局部化,失败也更容易追踪。

简单的系统会明确地崩溃。复杂的系统会神秘地崩溃。

宁选简单而非花哨的架构

在结账系统中,我们为整个流程采用了事件驱动架构。每一步都发出并消费事件。在白板上看起来很优雅。在生产环境中却痛苦不堪。

稍作停顿。你在这套架构中看到任何明显的问题吗?

大多数讨论都围绕事件排序、重试和消费者延迟展开。没有哪个服务明确拥有订单的最终结果。失败导致订单处于部分状态,需要人工干预。

该架构以牺牲清晰度为代价,优化了灵活性。

我们将完全事件驱动的流程替换为简单、同步的结账服务。

一个服务负责整个结账生命周期。它验证购物车、处理支付,并返回最终的成或败。事件仍然被使用,但仅用于分析、通知等副作用。核心业务流程保持线性且易于理解。

失败现在变得即时且可见。一个订单要么完成,要么明显失败,绝不会处于模糊的状态

你不需要它(YAGNI)

产品范围很窄,用户提交了反馈。管理员审核了它。但架构比这复杂得多。

在纸面上,设计预期能够增长。实际上,它优化了一个从未到来的未来。这也造成了诸多复杂性:

  • 一个服务内的多个架构层
  • 反馈提交的事件驱动流程
  • 反馈、状态和审计日志的分离表
  • 保护未完成或未使用功能的特性标志

所有这些复杂性都存在于一个服务中。它并没有解决一个真正的问题。它只是反映了关于未来的假设。

简化的架构看起来大致是这样的:

通过移除未使用的抽象、表格和基础设施,系统变得一目了然。

过多的配置并不总是好的

个内部系统将灵活性推向了极端。几乎每种行为都由配置驱动;

特性标志、环境变量和多个配置文件影响了核心逻辑。大多数生产事故并非由代码缺陷引起,而是由错误的配置导致。

理论上,这看起来很灵活,但它有许多隐藏的复杂性:

  • 运行时加载了多个配置源
  • 控制关键执行路径的功能标志
  • 跨代码库的特定环境行为

要了解系统如何运行,你首先必须了解它是如何部署的。

现在,让我们看看简化的架构:

  • 直接在代码中定义清晰的默认值
  • 特性标志仅用于临时发布
  • 配置仅限于真实环境差异

随着可移动部分的减少,部署变得更安全。系统行为变得可预测。代码解释了自身。

简洁的架构并不意味着设计薄弱。它意味着去除不必要的复杂性,以便系统在发展过程中保持可理解性。

强大的系统始于简单。它们随着时间的推移逐渐获得复杂性。

本文到此结束,感谢阅读。

原文地址:How Simpler Architectures Made Me a Better Senior Developer