简体   繁体   English

如何正确组织包/模块依赖树?

[英]How to properly organize a package/module dependency tree?

Good morning, 早上好,

I am currently writing a python library. 我目前正在编写python库。 At the moment, modules and classes are deployed in an unorganized way, with no reasoned design. 目前,模块和类是以无组织的方式部署的,没有合理的设计。 As I approach a more official release, I would like to reorganize classes and modules so that they have a better overall design. 当我接近正式发布时,我想重新组织类和模块,以便它们具有更好的总体设计。 I drew a diagram of the import dependencies, and I was planning to aggregate classes by layer level. 我绘制了导入依赖关系图,并计划按层级别聚合类。 Also, I was considering some modification to the classes so to reduce these dependencies. 另外,我正在考虑对类进行一些修改,以减少这些依赖性。

What is your strategy for a good overall design of a potentially complex and in-the-making python library? 对于潜在复杂且正在制作中的python库进行总体设计的最佳策略是什么? Do you have interesting suggestions ? 您有有趣的建议吗?

Thanks 谢谢

Update: 更新:

I was indeed looking for a rule of thumb. 我确实在寻找经验法则。 For example, suppose this case happens ( init .py removed for clarity) 例如,假设发生这种情况(为清楚起见删除了init .py)

foo/bar/a.py
foo/bar/b.py
foo/hello/c.py
foo/hello/d.py

now, if you happen to have d.py importing bar.b and a.py importing hello.c, I would consider this a bad setting. 现在,如果您碰巧有d.py导入bar.b和a.py导入hello.c,我认为这是一个糟糕的设置。 Another case would be 另一种情况是

foo/bar/a.py
foo/bar/baz/b.py
foo/bar/baz/c.py

suppose that both a.py and b.py import c. 假设a.py和b.py都导入c。 you have three solutions: 1) b imports c, a import baz.c 2) you move c in foo/bar. 您有以下三种解决方案:1)b导入c,导入baz.c 2)您在foo / bar中移动c。 a.py imports c, b.py imports .c 3) you move c somewhere else (say foo/cpackage/c.py) and then both a and b import cpackage.c a.py导入c,b.py导入.c 3)将c移动到其他位置(例如foo / cpackage / c.py),然后a和b都导入cpackage.c

I tend to prefer 3), but if c.py has no meaning as a standalone module, for example because you want to keep it "private" into the bar package, I would preferentially go for 1). 我倾向于3),但是如果c.py作为独立模块没有任何意义,例如,因为您要将其“私有”保留在bar包中,则我会优先使用1)。

There are many other similar cases. 还有许多其他类似的情况。 My rule of thumb is to reduce the number of dependencies and crossings at a minimum, so to prevent a highly branched, highly interweaved setup, but I could be wrong. 我的经验法则是尽量减少依赖性和交叉的数量,以防止出现高度分支,高度交错的设置,但我可能是错的。

"I drew a diagram of the import dependencies, and I was planning to aggregate classes by layer level." “我绘制了导入依赖关系图,并计划按层级别聚合类。”

Python must read like English (or any other natural language.) Python必须像英语(或其他自然语言)一样阅读。

An import is a first-class statement that should have real meaning. 导入是一流的语句,应具有真实含义。 Organizing things by "layer level" (whatever that is) should be clear, meaningful and obvious. 按“层次”(无论是什么层次)组织事物应该是清晰,有意义和显而易见的。

Do not make arbitrary technical groupings of classes into modules and modules into packages. 不要将类的任意技术分组归入模块,而将模块归入包。

Make the modules and package obvious and logical so that the list of imports is obvious, simple and logical. 使模块和包显而易见且合乎逻辑,以便导入列表显而易见,简单且合乎逻辑。

"Also, I was considering some modification to the classes so to reduce these dependencies." “此外,我正在考虑对类进行一些修改,以减少这些依赖性。”

Reducing the dependencies sounds technical and arbitrary. 减少依赖关系听起来是技术性和任意性的。 It may not be, but it sounds that way. 可能不是,但是听起来是这样。 Without actual examples, it's impossible to say. 没有实际的例子,这是不可能的。

Your goal is clarity. 您的目标是清晰。

Also, the module and package are the stand-alone units of reuse. 而且,模块和包是独立的重用单元。 (Not classes; a class, but itself isn't usually reusable.) Your dependency tree should reflect this. (不是类;是类,但是它本身通常是不可重用的。)您的依赖关系树应该反映出这一点。 You're aiming for modules that can be imported neatly and cleanly into your application. 您的目标是可以整洁干净地导入应用程序的模块。

If you have many closely-related modules (or alternative implementations) then packages can be used, but used sparingly. 如果您有许多密切相关的模块(或替代实现),则可以使用软件包,但要谨慎使用。 The Python libraries are relatively flat; Python库相对扁平; and there's some wisdom in that. 这有一些智慧。


Edit 编辑

One-way dependency between layers is an essential feature. 层之间的单向依赖是一项基本功能。 This is more about proper software design than it is about Python. 这更多的是关于适当的软件设计,而不是Python。 You should (1) design in layers, (2) design so that the dependencies are very strict between the layers, and then (3) implement that in Python. 您应该(1)在各层中进行设计,(2)在设计时要使各层之间的依赖性非常严格,然后(3)在Python中实现。

The packages may not necessarily fit your layering precisely. 这些包可能不一定完全适合您的分层。 The packages may physically be a flat list of directories with the dependencies expressed only via import statements. 这些软件包实际上可以是目录的平面列表,其依赖性仅通过import语句表示。

The question is very vague. 这个问题很模糊。

You can achieve this by having base/core things that import nothing from the remainder of the library, and concrete implementations importing from here. 您可以通过使基本/核心内容从库的其余部分中不导入任何内容,并从此处导入具体的实现方式来实现此目的。 Apart from "don't have two modules importing from each-other at import-time", you should be fine. 除了“在导入时没有彼此导入的两个模块”之外,您应该没问题。

module1.py: module1.py:

import module2

module2.py: module2.py:

import module1

This won't work! 这行不通!

It depends on the project, right? 这取决于项目,对吗? For example, if you are using a model-view-controller design, then your package would be structured in a way that makes the 3 groups of code independent. 例如,如果您使用的是模型视图控制器设计,那么您的程序包将以使三组代码独立的方式进行结构化。

If you need some ideas, open up your site-packages directory, and look through some of the code in those modules to see how they are set up. 如果您需要一些想法,请打开site-packages目录,并查看这些模块中的一些代码以了解如何设置它们。

There is no correct way without knowing more about the module; 如果不了解该模块,就没有正确的方法。 as Ali said, this is a vague question. 正如阿里所说,这是一个模糊的问题。 You really just need to analyze what you have in front of you, and figure out what might work better. 您确实只需要分析自己面前的东西,然后找出可能会更好的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM