本文目录导读:

- Python:最成熟的模块化体系
- JavaScript (Node.js):基于 CommonJS 或 ES Modules
- Shell (Bash):通过
source或函数导出 - 通用模块化设计原则
- 实战建议(以 Python 示例)
在脚本开发中,模块化设计是提升代码可维护性、复用性和可读性的核心方法,不同语言(如Python、JavaScript、Shell等)的实现方式略有不同,但底层思想一致:将功能独立封装,降低耦合,通过明确的接口进行交互。
以下是几种主流脚本语言实现模块化的具体方案:
Python:最成熟的模块化体系
Python 通过 模块(Module) 和 包(Package) 实现。
-
模块(一个
.py文件):将相关函数、类、变量放在一个文件中。# math_operations.py def add(a, b): return a + b def multiply(a, b): return a * b PI = 3.14159 -
包(一个包含
__init__.py的文件夹):将多个模块组织成目录。# my_package/__init__.py # 可以是空文件,也可以写初始化代码 # my_package/string_utils.py def capitalize_words(s): return ' '.join(word.capitalize() for word in s.split()) -
导入与使用:
# main.py from math_operations import add, PI from my_package.string_utils import capitalize_words print(add(3, 5)) # 输出 8 print(PI) # 输出 3.14159 print(capitalize_words("hello world")) # 输出 Hello World
JavaScript (Node.js):基于 CommonJS 或 ES Modules
-
CommonJS(Node.js 默认,使用
require):// math.js function add(a, b) { return a + b; } module.exports = { add }; // 导出对象 // main.js const math = require('./math.js'); // 注意相对路径 ./ console.log(math.add(2, 3)); // 输出 5 -
ES Modules(现代标准,使用
import/export):// math.mjs (或 package.json 中设置 "type": "module") export const add = (a, b) => a + b; export default function multiply(a, b) { return a * b; } // main.mjs import multiply, { add } from './math.mjs'; console.log(add(2, 3)); // 输出 5 console.log(multiply(4, 5)); // 输出 20
Shell (Bash):通过 source 或函数导出
Shell 脚本本身是顺序执行的,模块化主要依赖 文件引入(source) 和 环境隔离。
-
核心思路:将功能函数或变量定义在单独文件中,用
source在当前 Shell 环境中执行该文件。# utils.sh (模块文件) #!/bin/bash function log_info() { echo "[INFO] $(date): $1" } function calculate_disk_usage() { df -h / | tail -1 | awk '{print $5}' } # config.sh (配置模块) MAX_RETRIES=3 BACKUP_DIR="/data/backups" -
主脚本调用:
# main.sh #!/bin/bash source ./utils.sh # 导入工具函数 source ./config.sh # 导入配置变量 log_info "开始备份..." current_usage=$(calculate_disk_usage) echo "当前磁盘使用率: $current_usage" if [ -d "$BACKUP_DIR" ]; then echo "备份路径: $BACKUP_DIR, 最大重试次数: $MAX_RETRIES" fi -
注意:
source(或 命令)会使子模块的变量/函数注入到当前 Shell 中,为避免命名冲突,尽量为函数名添加前缀(如utils_log_info)。
通用模块化设计原则
无论用哪种语言,脚本模块化都遵循以下原则:
- 单一职责:一个模块只做一件事。
database.py只处理数据库连接与查询,user_service.py只处理用户业务逻辑。 - 明确的接口:模块对外暴露的只是有限的函数、类或变量,内部细节对外隐藏,通过 (Python)、 私有函数(JSDoc)等方式标记内部实现。
- 低耦合:模块之间尽量只通过参数、返回值或简单的消息传递通信,避免一个模块直接修改另一个模块的内部状态,不要在一个模块里
import另一个模块的全局变量并直接修改。 - 高内聚:模块内部的功能紧密相关,
file_reader.py里所有函数都是围绕文件读取的。 - 避免循环依赖:模块 A 依赖 B,B 又依赖 A,会导致无法加载或死循环,这通常需要通过引入中间模块(如
common.py)来解耦。
实战建议(以 Python 示例)
假设你要写一个数据清洗脚本,可以这样设计目录结构:
data_cleaner/
├── main.py # 入口,负责调度
├── config.py # 配置,如文件路径、参数
├── readers/ # 读取模块包
│ ├── __init__.py
│ └── csv_reader.py
├── processors/ # 处理逻辑包
│ ├── __init__.py
│ ├── remove_duplicates.py # 去重
│ └── validate_data.py # 校验
└── writers/ # 输出模块包
├── __init__.py
└── excel_writer.py
核心设计:
- 入口脚本 (
main.py):只关注“读取 -> 处理 -> 写入”的流程编排,不关心具体实现。 - 配置模块 (
config.py):所有可变参数都在这里修改,避免硬编码。 - 子模块:每个
.py文件只包含高度相关的几个函数。
这样,当需求变更(如输入文件从 CSV 变为 Excel)时,你只需要修改 readers/csv_reader.py 或新增 readers/excel_reader.py,而 main.py 几乎不需要改动。
- Python:天然支持模块和包,用
import和from ... import。 - JavaScript:CommonJS 用
require/module.exports,ESM 用import/export。 - Shell:用
source引入外部脚本文件。 - 核心:不写大而全的“脚本块”,而是拆成小文件(模块),每个模块负责单一功能,通过明确的导入结构协作。
模块化设计不是语言特性绑定,而是一种思维习惯:写任何脚本前,先思考“这堆代码能否拆成3-5个独立的文件/类/函数?每个部分的职责是什么?”,这样做一次,后续维护时你会感谢当年的自己。