悠悠楠杉
如何构建工整的工程结构?这份设计规约值得细读
一、为什么你的项目总像"破旧仓库"?
上周review同事的代码时,我看到这样的目录结构:
/src
/utils
helper.js (1200行)
/components
HomePage.js (直接调用了数据库)
config.json (混入敏感信息)
这让我想起刚入行时犯过的错误——结构缺失综合征。当项目规模超过万行代码后,这样的代码库会变成开发者的噩梦。
二、模块化设计的黄金分割
2.1 垂直切割原则
好的工程结构应该像精心设计的橱柜:
- 业务层:/features/user
(按功能聚合)
- 核心层:/lib/auth
(跨业务通用能力)
- 基础设施:/infra/database
(技术细节封装)
参考Spring的"三明治架构",控制流应当是从上至下的单向依赖。我曾参与改造的电商系统,通过这种划分使编译速度提升40%。
2.2 水平分层禁忌
避免传统MVC模式常见的陷阱:markdown
反面教材
/controllers
UserController.js
/models
User.js
/views
userProfile.ejs
这种结构会导致:
1. 修改用户功能需跳转3个目录
2. 容易产生循环依赖
3. 业务逻辑分散到各层
三、依赖管理的艺术
3.1 依赖注入容器
在Node.js项目中,我们采用这样的解决方案:javascript
// core/container.js
const db = require('./db');
module.exports = {
userService: new UserService(db)
}
// 使用时
const { userService } = require('../core/container');
3.2 循环依赖检测
配置Webpack的circular-dependency-plugin
:
javascript
new CircularDependencyPlugin({
failOnError: true,
allowAsyncCycles: false
})
四、配置管理的进阶实践
4.1 多环境配置方案
bash
config/
├── default.json
├── development.json
├── production.json
└── custom-environment-variables.json
通过convict
库实现类型安全的配置读取:
javascript
const conf = convict({
port: {
format: 'port',
default: 3000
}
});
五、文档即设计的理念
在每个模块根目录放置ARCHITECTURE.md
:markdown
支付模块设计
数据流
- 前端发起支付请求
- 生成支付流水(状态:PENDING)
- 调用第三方API
- 更新流水状态
幂等性处理
采用XID分布式事务ID...
六、持续演进的架构
去年在重构物流系统时,我们采用渐进式方案:
1. 第一阶段:统一代码风格(ESLint+Prettier)
2. 第二阶段:建立模块边界(Webpack Module Federation)
3. 第三阶段:引入领域驱动设计
六个月内将平均需求交付时间从5天缩短到1.8天。
好的工程结构不是一次性工作,而是需要持续重构的习惯。就像整理房间,每天花10分钟调整,远比季度大扫除更有效。从明天开始,试着在你的项目中应用这些原则,三个月后你会感谢现在的决定。