【开发】结构化工程
Created: July 15, 2024 9:40 AM Type: Reading Reviewed: No Status: Done
结构化要解决的问题:
-
哪个函数应该深入到哪个模块?
-
数据在项目中如何流转?
-
什么功能和函数应该组合或独立?
本文的目的:
-
从不同层面讨论如何构建可扩展且测试、可靠的代码
仓库结构
布局 | 作用 |
---|---|
./sample/ | |
./sample.py | 核心代码 |
./LICENSE | 许可证 |
./setup.py | 打包和分布管理 |
./requirements.txt | |
./Pipfile, ./Pipfile.lock | 开发依赖 |
./docs/ | 包的参考文档 |
./test_sample.py | |
./tests |
- test_basic.py - test_advanced.py | 包的集合和单元测试 |
| ./Makefile | 常规的管理任务(不是C语言也可以用于管理) |
测试的环境配置
测试样例需要读入包来测试,有两种方法来处理:
-
将包安装到site-packages中。
-
通过简单直接的路径设置来解决导入的问题。(推荐)
通过设置包含上下文环境的文件 tests/context.py
来设置运行:
import os import sys sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) # 将上级目录插入到 sys.path列表第一个位置 # sys.path 列表中的路径是Python解释器在导入模块时搜索的路径。 import sample # test_xxx.py from .context import sample # 实现导入
结构管理
-
Q1:多重且混乱的循环依赖关系
-
例子:Table, Chair 类导入Carpenter类以回答
table.isdoneby()
问题;Carpenter类导入Table, Chair类回答carpenter.whatdo()
问题,造成了循环依赖 -
A1:推荐一些不怎么靠谱的小技巧:比如在函数或方法内部使用import语句实现延时导入
隐含耦合:一个类实现的代码中的任意改变会打破许多与其无关的测试用例,由于他影响了另一个类中的代码,这要求谨慎操作以适应改变。这种就意味着后者中包含了太多前者的假设关联。
-
-
Q2:大量使用全局变量或上下文
模块
Python模块是最主要的抽象层之一,抽象层允许将代码分为不同部分,每个部分包含相关的数据与功能。
比如说在项目中,可以一层控制用户操作相关接口,一层处理底层数据操作。模块名称要短,使用小写,避免使用特殊符号,不推荐在模块名中使用下划线。
具体来说,对于import modu
语句,解释器递归的在PYTHONPATH
环境变量中寻找该文件,如果没有找到,抛出ImportError异常。而一旦找到该模块,Python解释器将在隔离的作用域内执行该模块,所有的顶层语句会被执行,包括其他的引用。方法与类的定义会存储到模块字典中。然后,这个模块的变量、方法和类通过命名空间暴露给调用方。
from mode import xxx
不如直接import mode
好,前者唯一的优点就是少打点字
包
任意包含 __init__.py
文件的目录都被认为是一个Python包。
__init__.py
文件将集合 所有包范围内的定义。
这是一个例子,可以看到,我们想引入的是s3000_score下的views,但是引入的过程会先在views目录下寻找__init__.py
,之后执行其中的所有资源,因此s3000_score中的资源也可以获取。
一个常见的问题是在__init__.py
中加了过多代码。