模块化设计原则
模块化是代码组织的核心思想,良好的模块设计能显著提升代码可维护性和复用性。
模块化核心概念
什么是模块
模块是独立的功能单元,具有:
- 单一职责:一个模块只做一件事
- 明确接口:公开API,隐藏内部实现
- 独立依赖:明确声明依赖关系
模块化价值
- 代码组织更清晰
- 依赖关系更明确
- 复用性更高
- 维护成本更低
- 测试更容易
ES6模块系统
导出语法
JavaScript
// 命名导出
export const name = 'module';
export function greet() { return 'hello'; }
export class User { constructor(name) { this.name = name; } }
// 批量导出
const name = 'module';
function greet() { return 'hello'; }
export { name, greet };
// 重命名导出
export { name as moduleName, greet as sayHello };
// 默认导出
export default class User {
constructor(name) { this.name = name; }
}
// 混合导出
export default User;
export const createUser = (name) => new User(name);
导入语法
JavaScript
// 命名导入
import { name, greet } from './module.js';
// 重命名导入
import { name as moduleName } from './module.js';
// 默认导入
import User from './module.js';
// 混合导入
import User, { createUser } from './module.js';
// 全部导入
import * as module from './module.js';
module.name;
module.greet();
// 动态导入
const module = await import('./module.js');
模块特点
JavaScript
// 模块是单例
import { counter } from './counter.js';
counter.increment(); // counter.value = 1
import { counter } from './counter.js'; // 同一个实例
counter.increment(); // counter.value = 2
// 模块内部变量私有
// module.js
const privateVar = 'private'; // 外部无法访问
export const publicVar = 'public';
// 模块执行时机
import { name } from './module.js'; // 静态声明,首次导入时执行
const module = await import('./module.js'); // 动态导入,按需执行
模块划分原则
按功能划分
JavaScript
src/
├── modules/
│ ├── auth/ # 认证模块
│ │ ├── index.js
│ │ ├── login.js
│ │ ├── token.js
│ ├── user/ # 用户模块
│ │ ├── index.js
│ │ ├── profile.js
│ │ ├── permissions.js
│ ├── order/ # 订单模块
│ │ ├── index.js
│ │ ├── create.js
│ │ ├── list.js
按层级划分
JavaScript
src/
├── components/ # UI组件层
│ ├── Button/
│ ├── Modal/
├── services/ # 业务服务层
│ ├── api.js
│ ├── auth.js
├── utils/ # 工具层
│ ├── format.js
│ ├── validate.js
├── constants/ # 常量层
│ ├── config.js
│ ├── enums.js
模块大小原则
JavaScript
// 模块不宜过大
// ❌ 一个文件包含多个不相关功能
class UserService {
login() {}
logout() {}
// 100+ 行不相关代码...
formatDate() {}
validateEmail() {}
}
// ✅ 按职责拆分
// userService.js
export class UserService {
login() {}
logout() {}
}
// formatUtils.js
export function formatDate(date) {}
// validateUtils.js
export function validateEmail(email) {}
模块接口设计
公开API设计
JavaScript
// 模块入口文件:index.js
// 只导出必要的接口,隐藏内部实现
// ❌ 导出所有内容
export * from './internal.js';
// ✅ 精选导出
export { UserService } from './service.js';
export { createUser, validateUser } from './helpers.js';
// 内部实现不导出
// internal.js 不会被外部访问
接口命名规范
JavaScript
// 使用一致的命名风格
export class UserService {} // 类:首字母大写
export function createUser() {} // 函数:动词开头
export const USER_ROLES = {} // 常量:大写蛇形
// 导出对象集中管理
export const api = {
getUser,
createUser,
updateUser,
deleteUser
};
// 使用时
import { api } from './user.js';
api.getUser(id);
类型导出
JavaScript
// 导出类型定义(TypeScript风格)
export interface User {
id: number;
name: string;
}
export type UserRole = 'admin' | 'member' | 'guest';
// JavaScript中使用JSDoc
/**
* @typedef {Object} User
* @property {number} id
* @property {string} name
*/
export { User };
模块依赖管理
循环依赖处理
JavaScript
// ❌ 循环依赖:a.js和b.js相互依赖
// a.js
import { bFunc } from './b.js';
export function aFunc() {
bFunc(); // b.js还未完全初始化
}
// b.js
import { aFunc } from './a.js';
// ✅ 解决方案1:重构,消除循环依赖
// 将共享逻辑提取到独立模块
// shared.js
export const shared = {};
// a.js
import { shared } from './shared.js';
// b.js
import { shared } from './shared.js';
// ✅ 解决方案2:延迟导入
// a.js
export function aFunc() {
const { bFunc } = require('./b.js'); // 延迟导入
bFunc();
}
// ✅ 解决方案3:函数参数传递
// a.js
export function aFunc(bFunc) {
bFunc(); // 通过参数传入
}
依赖注入
JavaScript
// 模块依赖外部注入
// config.js - 配置模块
export function createConfig(env) {
return {
apiUrl: env.API_URL,
timeout: env.TIMEOUT
};
}
// api.js - API模块
export function createApiService(config) {
return {
async fetch(url) {
return fetch(config.apiUrl + url);
}
};
}
// 组装模块
// app.js
import { createConfig } from './config.js';
import { createApiService } from './api.js';
const config = createConfig(process.env);
const apiService = createApiService(config);
模块复用策略
纯函数模块
JavaScript
// 纯函数模块:无副作用,易复用
// math.js
export function add(a, b) { return a + b; }
export function subtract(a, b) { return a - b; }
export function multiply(a, b) { return a * b; }
// 无外部依赖,可在任何环境使用
import { add } from './math.js';
工厂函数模块
JavaScript
// 工厂函数:创建可配置实例
// logger.js
export function createLogger(options = {}) {
const { level = 'info', output = console } = options;
return {
log(message) {
if (level !== 'silent') {
output.log(message);
}
},
error(message) {
output.error(message);
}
};
}
// 使用
const logger = createLogger({ level: 'debug' });
const silentLogger = createLogger({ level: 'silent' });
高阶模块
text
// 高阶模块:增强其他模块
// withRetry.js
export function withRetry(service, options) {
return {
async call(method, ...args) {
for (let i = 0; i < options.maxRetries; i++) {
try {
return await service[method](...args);
} catch (error) {
if (i === options.maxRetries - 1) throw error;
await sleep(options.delay);
}
}
}
};
}
// 使用
import { createApiService } from './api.js';
import { withRetry } from './withRetry.js';
const api = createApiService();
const retryApi = withRetry(api, { maxRetries: 3, delay: 1000 });
模块化最佳实践
目录结构标准
text
src/
├── index.js # 入口文件
├── modules/
│ ├── user/
│ │ ├── index.js # 模块入口,导出公开API
│ │ ├── service.js # 内部实现
│ │ ├── types.js # 类型定义
│ │ ├── utils.js # 内部工具
│ │ └── test.js # 测试文件
模块文档
text
/**
* User模块 - 用户管理功能
* @module user
*/
/**
* 获取用户信息
* @param {number} userId - 用户ID
* @returns {Promise<User>} 用户信息
*/
export async function getUser(userId) {
// ...
}
好的模块:单一职责、明确接口、无循环依赖、易测试易复用。
要点总结
- ES6模块:静态导入、单例模式、私密性好
- 模块划分:按功能或层级,保持单一职责
- 接口设计:精选导出、隐藏内部、命名规范
- 依赖管理:避免循环依赖、使用依赖注入
- 复用策略:纯函数、工厂函数、高阶模块
存放路径:articles/JS/专家/设计模式与架构思想/模块化设计原则.md
📝 发现内容有误?点击此处直接编辑