为什么好的软件架构很重要? – Maciej


近年来,我在IT公司遇到过很多因软件架构不正确而导致的问题。

不正确是什么意思?

在大多数情况下,这是一个方向——相对于它应该解决的问题来说:

  1. 要么过于简单
  2. 要么极其复杂

这两种情况都会导致性能问题并阻止组织变得敏捷。


软件架构是什么意思?
在我开始谈论由不正确的架构引起的问题之前,我想先看看它的概念。对我来说,它是生产软件的一切——从领域及其需求的战略分析到将它们转化为技术解决方案:

  • 了解业务领域及其功能
  • 将其拆分为子域和边界定义
  • 关于基础设施级别的决策——我想在这里实现的方式、地点和内容。云端还是本地?我需要容器吗?K8s?API网关?负载均衡器?缓存?什么类型的数据库?我想如何处理监视、日志记录和遥测?我需要开发和阶段环境还是只需要生产环境?
  • 选择合适的部署策略——是单个(模块化单体)还是多个部署单元(微服务)?如果我们决定采用微服务,促使我们做出此决定的原因(分解因素)是什么?
  • 基于领域战略分析的模块/微服务架构定义——我需要一个活动记录吗?交易脚本?域模型?我应该在那里申请事件采购吗?CQRS?
  • 测试策略的定义——我想执行哪些测试?什么时候?多常?
  • 发布策略的定义——我要持续部署我的应用程序吗?

如果架构太简单,逆向难度要大得多,等到发现这一点时,再进行更改通常为时已晚——因为例如更换一个组件会导致巨大的成本。
最重要的是,如果我们依赖其他系统并且我们的应用程序没有正确部署,这些问题只会堆积起来。在这种情况下,唯一的办法就是逐步更换系统中的元素(这里可能也需要外部顾问的帮助)。

架构怎么会太复杂?想象一下,您作为软件架构师加入了一家公司。你被录用是因为没有人有设计网络系统的经验。在过去的几年里,你听说过 k8s、容器、微服务、Redis、NoSQL、Kafka、领域驱动设计等等。现在是您和您的其他架构师和开发人员团队掌握了决策权。你做什么工作?
如果您专注于战略领域分析,那就太好了。迈向良好系统的第一步。你会见了不同的人——未来的客户、利益相关者、运营部门等等。举办研讨会,收集和分析业务需求。这几周很艰难,但最终,我们做到了,您想尽快开始构建系统。因此,您与您的团队一起决定:

  • 使用微服务
  • 容器化应用程序
  • 在k8s集群中运行
  • 添加 Redis
  • 添加卡夫卡
  • 使用 NoSQL
  • 在每个微服务中应用 DDD

现在有几个问题:

  • 当某些事情没有按预期工作时,您有很多地方需要检查
  • 一切都是从头开始添加的——不是基于需求而是愿意使用和过早优化。事实上,你不知道你是否需要它,所以很多时候,系统太复杂而无法维护,暴露了知识的缺乏
  • 任何加入你团队的人都有很高的进入门槛
  • 与另一个可能的解决方案相比,基础设施的成本可能会增加 70%(但现在改变它已经太晚了)

你所取得的成就当然是系统的良好模块化——如果正确地拆分到微服务的话。不幸的是,您在不需要时引入了极端的复杂性。这迟早会再次导致该主题出现 2 个问题:

  • 性能——您的应用程序开始随机失败(由于您不完全了解的不同组件中的错误),并且由于复杂性,您的团队执行速度较慢
  • 更改、修复和新功能很少发布,因为您必须手动进行部分部署和测试

我们可以做什么?
没有单一的、完美的方法可以使一切正常工作。但是,您可以采取一些步骤来最大程度地降低出现所述问题的风险:

  • 对业务领域进行战略分析——组织研讨会,收集和分析业务需求(使用以下一种方法或组合使用以下方法——事件风暴、领域故事讲述、影响映射或故事风暴)
  • 基于以上,将你的业务域划分为多个子域。定义这是核心(复杂的业务逻辑,使您的公司在市场上独一无二的东西)、支持性的(不那么复杂、内部或外包,没有什么真正独特的)或通用的(您可以购买市场上存在的东西)并满足您的需求)。然后决定在哪里应用事务脚本、活动记录或领域模型
  • 根据业务分析和提出的问题,计算你的应用程序将要处理的流量——读写操作的数量、数据库事务和要存储的数据量等。包括峰值计算——我更喜欢 3x 标准估计,有些人做 5 倍或更多
  • 基于以上计算,准备最简单的基础架构来处理它——不用担心,如果你的应用程序像病毒一样传播开来,那么你将有机会使用很多不同的框架、库或流行的组件。从简单开始(KISS)
  • 决定是要使用单个部署单元(例如模块化单体)还是多个部署单元(例如微服务)。如果您决定选择第二个选项,请找出原因——是否有任何区域的容错性低于其他区域?是否有需要加强安全性的区域?你认为有一个领域会更频繁地改变吗?从第一天起,是否有任何区域会被大量使用?您在不同时区有多个团队吗?
  • 通过架构决策日志记录您的决策——它应该尽可能靠近代码,例如以 .adoc 或 .doc 的形式。存储库中的 md 文件
  • 为您的架构编写测试,例如使用https://github.com/BenMorris/NetArchTest for .NET
  • 将你的工作分成垂直的部分——尝试交付一个特性或它的可用部分,而不是先准备数据库,然后是应用层,然后是 API
  • 遵循基于主干的开发和 pair/mob 编程——你将省略对 PR 的需求,因为审查将在编码期间由第二个人处理。如果您认为自己还没有为此做好准备,请关注短命分支——例如,每个分支都必须在开始后的 24 小时内关闭。这样你就有了小的 PR,频繁的更改和简单的合并/变基
  • 尝试 TDD(测试驱动开发),这是交付软件的好方法
  • 尽可能多地自动化——在最好的情况下,不会有手动步骤(持续部署)。这意味着您将需要一个好的测试策略并每次都自动运行它们
  • 由于上述原因,您将能够每天发布多次。别担心——如果您无法在生产环境中实现这一目标,请随时做好准备(持续交付)——在这种情况下,您可以在舞台环境中进行持续部署。如果由于某些情况而无法做到这一点,请尝试每周或冲刺发布一次
  • 仅向部分用户发布新版本,然后逐渐增加数量,直到达到 100%。


可扩展和可维护的软件架构极其重要,因为它对软件系统的性能和敏捷性有重大影响。正确设计的体系结构可以使系统更具可扩展性、可维护性和更易于修改,从长远来看可以节省时间和资源。