您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > Python

我们如何处理大型 Python 单体架构

时间:2023-08-10 16:25:00  来源:  作者:InfoQ

作者 | David Seddon

译者 | 平川

策划 | Tina

本文最初发布于 EuroPyhon 官方博客。

大家好,我叫 David,是 Kraken Technologies 的一名 Python/ target=_blank class=infotextkey>Python 开发人员。我从事 Kraken 开发,那是一个 Python 应用程序。据最新统计,它有 27,637 个模块。是的,你没看错:将近 28k 个独立的 Python 文件,这还不包括测试。我和世界各地的其他 400 名开发人员一起做这件事,不断地合并代码。任何人只要在 Github 上得到一个同事的批准,就可以做出变更,开始部署这个运行着 17 家不同的能源和公用事业公司、拥有数百万客户的软件。

现在,你可能觉得这会很混乱。说实话,我也会这么说。但事实证明,大量的开发人员可以在一个大型的 Python 单体上有效地开展工作,至少在我们工作的领域是如此。这是可能的,原因有很多,很多是文化上的,而不是技术上的。但在这篇博文中,我想介绍一下代码的组织如何帮助我们实现这一目标。

代码库分层

如果你在某个代码库上做过一段时间的开发,那么你肯定感受过那令人不快的复杂性。应用程序的逻辑链错综复杂,想要独立地考虑应用程序的各个部分变得越来越困难。我们的代码库开始时也是这样,所以我们决定采用所谓的“分层架构”,对代码库层与层之间哪些部分可见做了限制。

分层是一种众所周知的软件架构模式。在这种模式中,组件在概念上被组织成一个栈。栈中的组件不能依赖于上层的任何组件。

分层架构,向下依赖

如上图所示,C 可以依赖 B 和 A,但不能依赖 D。

分层架构的概念很广泛:它可以用于不同类型的组件。例如,你可以将几个可独立部署的服务分层;或者,你的组件可以只是一组源代码文件。

依赖的构成也很广泛。一般来说,如果一个组件对另一个组件有直接的了解(即使纯粹是在概念层面),那么它就依赖于另一个组件。间接交互(例如,通过配置)通常不视为依赖。

Python 中的分层

在 Python 代码库中,最好将层视为 Python 模块,将依赖视为 import 语句。

以下面的代码库为例:

myproject __init__.py payments/ __init__.py api.py vendor.py products.py shopping_cart.py

顶层模块和子包是层的良好候选。假设我们按下面这样的顺序分层:

shopping_cart payments products

那么,在这个架构中,shopping_cart 不能导入 payments 中的任何模块。不过,它可以导入 products 的模块。

层可以嵌套。因此,payments 可以像下面这样分层:

api vendor

至于分成几层以及各层之间的顺序,并没有一种唯一正确的方法,这是一种设计行为。但是像这样的分层可以减少代码库的混乱,使其更容易理解和修改。

Kraken 是如何分层的

在我写这篇文章时,有 17 家不同的能源和公用事业公司批准了 Kraken 的使用。我们为这些企业客户中的每一个运行一个单独的实例。现在,Kraken 的主要特点之一是不同的实例“相同又不同”。换句话说,它们之间有很多共享的行为,但每个实例都有满足特定客户需求的定制代码。在地区层面上也是如此:在英国运营的所有客户之间存在一些共性(它们与同一能源行业相融合),但与 Octopus Energy Japan 不同。

随着 Kraken 发展成为一个多客户平台,我们改进了它的分层结构。总的来说,现在的情况是这样的:

kraken/ __init__.py clients/ __init__.py oede/ oegb/ oejp/ ... territories/ __init__.py deu/ gbr/ jpn/ ... core/

客户位于顶层。每个客户对应该层中的一个子包(例如,oede 对应 Octopus Energy Germany)。客户的下面是地区,实现特定于国家的行为,同样,每个地区对应一个子包。最下层是核心层,其中包含所有客户都使用的代码。还有一个额外的规则,即客户子包必须是独立的(即不能从其他客户包导入),对于地区同样如此。

像这样把 Kraken 分层可以有效限制变更的“爆炸半径”。由于客户层位于顶部,所以没有任何东西直接依赖于它。因此,要修改与特定客户相关的内容会比较容易,而且不会意外影响其他客户的行为。同样,只涉及一个地区的更改也不会影响到另一个地区的任何东西。这使得我们能够快速独立地跨团队开展工作,特别是当我们正在进行的更改仅影响少量 Kraken 实例时。

利用 Import Linter 强制分层

当我们引入分层时,我们很快就发现,仅仅讨论分层是不够的。开发人员经常会不小心违反分层结构。我们需要以某种方式强制执行,为此,我们使用了 Import Linter。

Import Linter 是一个开源工具,可以检查你是否遵守了分层架构。首先,在 INI 文件中定义一个契约,用于描述分层,像下面这样:

[importlinter:contract:top-level]

name = Top level layerstype = layerslayers =kraken.clientskraken.territoriesKraken.core

我们也可以另外添加两个契约(‘independence’契约),强制保持不同客户和地区的独立性:

[importlinter:contract:client-independence]name = Client independencetype = independencelayers =kraken.clients.oedekraken.clients.oegbkraken.clients.oejp...

[importlinter:contract:territory-independence]name = Territory independencetype = independencelayers =kraken.territories.deukraken.territories.gbrkraken.territories.jpn...

然后,你可以在命令行上运行 lint-imports,它会告诉你是否有任何导入违反了契约。每次有 pull 请求时都会自动执行这个命令进行检查,所以如果有人引入了非法导入,就无法通过检查,也就无法完成合并。

契约不只这些。团队可以在应用程序中添加更深的分层:例如,kraken.territories.jpn 本身就是分层的。目前,我们有 40 多个契约。

减少技术债务

在引入分层架构时,我们没法从第一天开始就严格遵守。所以我们使用了 Import Linter 的一个特性,在检查契约之前忽略某些导入。

[importlinter:contract:my-layers-contract]name = My contracttype = layerslayers =kraken.clientskraken.territorieskraken.coreignore_imports =kraken.core.customers ->kraken.territories.gbr.customers.viewskraken.territories.jpn.payments -> kraken.utils.urls(and so on...)

然后,我们使用被忽略导入的数量作为跟踪技术债务的指标。这使我们能够了解改进情况,以及改进速度。

自 2022 年 5 月 1 日起被忽略导入的数量

上图是在过去一年左右的时间里,被忽略导入的数量变化情况。我定期向人们进行分享和展示,鼓励他们朝着完全遵守依赖原则的方向努力。我们在其他几个技术债务指标中也使用了这种燃尽方法。

缺点,缺点总是不可避免

局部复杂性

在采用分层架构之后的某个时刻,你可能会遇到需要打破分层的情况。实际情况会非常复杂,到处都是相互依赖,比如,你会发现自己想要调用一个更高层的函数。

幸运的是,办法总比问题多。我们可以利用控制反转,那在 Python 中很容易实现,所需的只是理念的转变。但它确实会增加“局部”的复杂性(如代码库的一小部分)。然而,为了使系统总体上更简单,付出这样的代价是值得的。

较高的层上代码过多

层越高,越容易更改。我们是有意为之的,让针对特定客户或地区的代码更容易更改。其他所有的层都要依赖于核心代码,对其进行修改的成本和风险也都更高。

因此,我们面临的设计压力部分是由我们选择的分层结构带来的,我们需要编写更多特定于客户和地区的代码,而不是在核心代码中引入更深的层次和更多可供全局使用的代码。因此,较高的层所拥有的代码超出了我们的预期。我们仍在研究如何解决这个问题。

我们还没有完成

还记得那些被忽略的导入吗?好吧,几年过去了,我们还是有一些!据最新统计,有 15 个。最后几项导入是最棘手、让人最纠结的。

回顾性地对代码库进行分层可能需要付出很大的努力。但这件事你做得越早,需要解决的问题就越少。

小 结

Kraken 的分层架构使我们这个非常庞大的代码库得以保持健康,并且相对比较容易使用,尤其是在这么个规模下。如果不对这成千上万的模块之间的关系施加约束,我们的代码库可能就会变成一大盘意大利面。但是,我们选择的这个大规模结构——并且随着业务的发展而发展——帮助我们在单个 Python 代码库上做了大量的工作。这似乎是不可能的,但我们确实做到了!

如果你正在处理大型 Python 代码库(甚至是相对比较小的代码库),不妨试一下分层。这事越早做越简单。

原文链接:

https://blog.europython.eu/kraken-technologies-how-we-organize-our-very-large-pythonmonolith/



Tags: Python   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
Python 办公神器:教你使用 Python 批量制作 PPT
介绍本文将介绍如何使用openpyxl和pptx库来批量制作PPT奖状。本文假设你已经安装了python和这两个库。本文的场景是:一名基层人员,要给一次比赛活动获奖的500名选手制作奖状,并...【详细内容】
2024-03-26  Search: Python  点击:(16)  评论:(0)  加入收藏
使用 Python 连接 SQL Server 数据库并实时读取数据?
实时读取SQL Server数据库表并进行处理是一个常见的需求。在Python中,可以使用pyodbc库来连接SQL Server数据库,并使用pandas库来进行数据处理。下面是一个实战示例,演示如何实...【详细内容】
2023-12-28  Search: Python  点击:(91)  评论:(0)  加入收藏
作为 .NET 开发人员,我为什么开始使用 Python?
作者 | Alex Maher编译 | 小欧作为一名 .NET 开发人员,很长一段时间以来,我一直关注 C# 和 .NET 的出色工具和功能。但我最近开始使用 Python,感觉非常棒。这里申明一点,这篇文...【详细内容】
2023-12-25  Search: Python  点击:(142)  评论:(0)  加入收藏
5 个让日常编码更简单的 Python 库
如果曾经在 Python 中使用过 subprocess 库,那么我们很有可能对它感到失望,它不是最直观的库,可能还有些复杂,并且很难处理底层系统调用的输出。但是 sh 库结束了低效使用子进程...【详细内容】
2023-12-14  Search: Python  点击:(155)  评论:(0)  加入收藏
你知道怎样在 Python 中管理内存吗
memray 是一个Python库,它提供了一种可视化内存管理工具,可以帮助Python开发人员更好地理解和优化他们的代码中的内存使用情况。它是由彭博社开发的,可用于分析Python程序中的...【详细内容】
2023-12-11  Search: Python  点击:(185)  评论:(0)  加入收藏
Top 12 Python 开源框架,你都用过吗?
今天好学编程给大家带来了12个在GitHub等开源网站中最受欢迎的Python开源框架。如果你正在学习python,那么这12个开源框架,千万别错过,这些框架包括事件I/O,OLAP,Web开发,高性能网...【详细内容】
2023-12-07  Search: Python  点击:(290)  评论:(0)  加入收藏
五个堪称瑰宝级的 Python 库,建议收藏!
Python是一种广泛使用的高级编程语言,拥有丰富的生态系统和庞大的开发社区。在这个生态系统中,有许多优秀的Python库,它们为开发者提供了丰富的功能和工具,极大地简化了开发过程...【详细内容】
2023-12-06  Search: Python  点击:(169)  评论:(0)  加入收藏
掌握九个好用的 Python 库
当谈到Python编程的强大之处时,不得不提到其丰富的库和模块。这些库可以帮助我们简化开发过程并提供丰富的功能,从而使我们的代码更加高效和强大。在本文中,笔者将向大家介绍九...【详细内容】
2023-12-06  Search: Python  点击:(183)  评论:(0)  加入收藏
你知道 Python 其实自带了小型数据库吗
dbmDBM(DataBase Manager)是一种文件系统,专门用于键值对的存储,最初是在 Unix 平台实现,现在其它平台也可以用。对于 KV 模型,DBM 提供了一个轻量级、高效的存储解决方案。总的来...【详细内容】
2023-11-29  Search: Python  点击:(197)  评论:(0)  加入收藏
解密 Python 如何调用 Rust 编译生成的动态链接库
楔子Rust 让 Python 更加伟大,随着 Rust 的流行,反而让 Python 的生产力提高了不少。因为有越来越多的 Python 工具,都选择了 Rust 进行开发,并且性能也优于同类型的其它工具。...【详细内容】
2023-11-29  Search: Python  点击:(188)  评论:(0)  加入收藏
▌简易百科推荐
Python 可视化:Plotly 库使用基础
当使用 Plotly 进行数据可视化时,我们可以通过以下示例展示多种绘图方法,每个示例都会有详细的注释和说明。1.创建折线图import plotly.graph_objects as go# 示例1: 创建简单...【详细内容】
2024-04-01  Python技术    Tags:Python   点击:(8)  评论:(0)  加入收藏
Python 办公神器:教你使用 Python 批量制作 PPT
介绍本文将介绍如何使用openpyxl和pptx库来批量制作PPT奖状。本文假设你已经安装了python和这两个库。本文的场景是:一名基层人员,要给一次比赛活动获奖的500名选手制作奖状,并...【详细内容】
2024-03-26  Python技术  微信公众号  Tags:Python   点击:(16)  评论:(0)  加入收藏
Python实现工厂模式、抽象工厂,单例模式
工厂模式是一种常见的设计模式,它可以帮助我们创建对象的过程更加灵活和可扩展。在Python中,我们可以使用函数和类来实现工厂模式。一、Python中实现工厂模式工厂模式是一种常...【详细内容】
2024-03-07  Python都知道  微信公众号  Tags:Python   点击:(31)  评论:(0)  加入收藏
不可不学的Python技巧:字典推导式使用全攻略
Python的字典推导式是一种优雅而强大的工具,用于创建字典(dict)。这种方法不仅代码更加简洁,而且执行效率高。无论你是Python新手还是有经验的开发者,掌握字典推导式都将是你技能...【详细内容】
2024-02-22  子午Python  微信公众号  Tags:Python技巧   点击:(32)  评论:(0)  加入收藏
如何进行Python代码的代码重构和优化?
Python是一种高级编程语言,它具有简洁、易于理解和易于维护的特点。然而,代码重构和优化对于保持代码质量和性能至关重要。什么是代码重构?代码重构是指在不改变代码外部行为的...【详细内容】
2024-02-22  编程技术汇    Tags:Python代码   点击:(33)  评论:(0)  加入收藏
Python开发者必备的八个PyCharm插件
在编写代码的过程中,括号几乎无处不在,以至于有时我们会拼命辨别哪个闭合括号与哪个开头的括号相匹配。这款插件能帮助解决这个众所周知的问题。前言在PyCharm中浏览插件列表...【详细内容】
2024-01-26  Python学研大本营  微信公众号  Tags:PyCharm插件   点击:(85)  评论:(0)  加入收藏
Python的Graphlib库,再也不用手敲图结构了
Python中的graphlib库是一个功能强大且易于使用的工具。graphlib提供了许多功能,可以帮助您创建、操作和分析图形对象。本文将介绍graphlib库的主要用法,并提供一些示例代码和...【详细内容】
2024-01-26  科学随想录  微信公众号  Tags:Graphlib库   点击:(86)  评论:(0)  加入收藏
Python分布式爬虫打造搜索引擎
简单分布式爬虫结构主从模式是指由一台主机作为控制节点负责所有运行网络爬虫的主机进行管理,爬虫只需要从控制节点那里接收任务,并把新生成任务提交给控制节点就可以了,在这个...【详细内容】
2024-01-25  大雷家吃饭    Tags:Python   点击:(58)  评论:(0)  加入收藏
使用Python进行数据分析,需要哪些步骤?
Python是一门动态的、面向对象的脚本语言,同时也是一门简约,通俗易懂的编程语言。Python入门简单,代码可读性强,一段好的Python代码,阅读起来像是在读一篇外语文章。Python这种特...【详细内容】
2024-01-15  程序员不二    Tags:Python   点击:(162)  评论:(0)  加入收藏
Python语言的特点及应用场景, 同其它语言对比优势
Python语言作为一种高级编程语言,具有许多独特的特点和优势,这使得它在众多编程语言中脱颖而出。在本文中,我们将探讨Python语言的特点、应用场景以及与其他语言的对比优势。一...【详细内容】
2024-01-09    今日头条  Tags:Python语言   点击:(253)  评论:(0)  加入收藏
站内最新
站内热门
站内头条