第2章:ERP系统架构设计

架构设计这事儿,说白了就是给系统搭骨架。骨架搭好了,后面加功能、修bug都顺溜。搭不好?嗯,那后面就有得哭了。我见过太多项目,前期图省事随便搞搞,结果后期改一次架构比重新写还痛苦。

今天咱们聊聊ERP系统的架构设计。我会把单体架构、微服务架构、分层设计、技术选型这些核心内容掰开揉碎了讲。你想想看,一个ERP系统要管采购、销售、库存、财务、生产……这么多模块,架构选错了,后面就是无底洞。

2.1 单体架构 vs 微服务架构

先说说最基础的选择题:用单体还是微服务?

单体架构,就是把所有功能都塞进一个应用里。前端、后端、数据库,全在一个项目里跑。优点是简单,开发快,部署也方便。我早期做的一个ERP项目就是单体架构,团队就5个人,三个月就上线了。

但单体有个致命问题——牵一发动全身。你改个采购模块的代码,可能把财务模块搞崩了。我记得有一次,团队里一个小伙子在库存模块加了个缓存,结果订单模块的查询全乱了。排查了两天才找到原因。

微服务架构就不一样了。每个模块独立成一个服务,各自部署,各自维护。采购一个服务,库存一个服务,财务一个服务。服务之间通过API通信。

微服务的优势很明显:

  • 独立部署:改采购模块不用重启整个系统
  • 技术异构:采购用Java,财务用Python,都行
  • 故障隔离:库存服务挂了,不影响订单服务
  • 团队自治:每个团队管自己的服务

但微服务也不是银弹。我见过一个团队,项目刚启动就上微服务,结果光搭建基础设施就花了两个月。服务间通信、数据一致性、分布式事务……这些坑一个接一个。

我的建议:

  • 团队小于10人,业务复杂度不高 → 单体架构
  • 团队大于20人,模块间耦合低 → 微服务架构
  • 不确定?先单体,等业务膨胀了再拆分

避坑指南:我曾经接手过一个项目,团队为了"技术先进"硬上微服务,结果每个服务只有几百行代码,却要维护一套完整的部署流水线。说白了,微服务是解决复杂度的工具,不是炫技的手段。

2.2 分层架构

不管单体还是微服务,内部都得分层。经典的三层架构:表现层、业务逻辑层、数据访问层。

表现层:负责和用户打交道。接收请求,返回响应。说白了就是Controller那层。我个人习惯把表现层做得尽量薄,只做参数校验和结果封装,不写任何业务逻辑。

业务逻辑层:核心中的核心。所有业务规则、流程控制、计算逻辑都放这里。我见过一些新手把业务逻辑写在Controller里,结果后面想复用都找不到地方。

数据访问层:和数据库打交道。CRUD操作、事务管理、缓存策略。这一层要尽量通用,换数据库的时候只改这一层就行。

举个例子,一个订单创建流程:

// 表现层
@PostMapping("/orders")
public Result createOrder(@RequestBody OrderDTO dto) {
    // 参数校验
    if (dto.getProductId() == null) {
        return Result.error("商品ID不能为空");
    }
    // 调用业务层
    return orderService.createOrder(dto);
}

// 业务逻辑层
@Service
public class OrderService {
    public Result createOrder(OrderDTO dto) {
        // 检查库存
        Stock stock = stockRepo.findByProductId(dto.getProductId());
        if (stock.getQuantity() < dto.getQuantity()) {
            return Result.error("库存不足");
        }
        // 计算价格
        BigDecimal total = priceService.calculate(dto);
        // 创建订单
        Order order = new Order(dto, total);
        orderRepo.save(order);
        // 扣减库存
        stockRepo.decrease(dto.getProductId(), dto.getQuantity());
        return Result.success(order);
    }
}

// 数据访问层
@Repository
public class OrderRepository {
    public void save(Order order) {
        // 执行SQL
        jdbcTemplate.update("INSERT INTO orders ...");
    }
}

注意:分层不是死的。我见过一些项目,为了"严格分层",连DTO转换都要写三层。其实没必要。小项目可以适当简化,比如表现层直接调用数据访问层。但大项目一定要分层清晰,否则后期维护成本会指数级上升。

2.3 技术选型

技术选型这事儿,我踩过的坑比走过的路还多。咱们一个个说。

后端:Java/Spring Boot

Java在ERP领域是绝对的主流。为什么?稳定、生态好、人才多。Spring Boot更是把Java开发的门槛降到了最低。

我个人习惯用Spring Boot + MyBatis Plus。Spring Boot负责框架,MyBatis Plus负责数据库操作。为什么不用JPA?嗯,ERP系统里复杂查询太多了,JPA的自动生成SQL有时候不太可控。

举个例子,一个多表关联的分页查询:

@Service
public class ReportService {
    public PageResult<ReportVO> queryReport(ReportQuery query) {
        // 使用MyBatis Plus的Lambda查询
        LambdaQueryWrapper<Report> wrapper = new LambdaQueryWrapper<>()
            .eq(Report::getCompanyId, query.getCompanyId())
            .between(Report::getCreateTime, query.getStartDate(), query.getEndDate())
            .orderByDesc(Report::getCreateTime);
        
        Page<Report> page = new Page<>(query.getPageNum(), query.getPageSize());
        Page<Report> result = reportMapper.selectPage(page, wrapper);
        
        // 转换为VO
        List<ReportVO> voList = result.getRecords().stream()
            .map(this::convertToVO)
            .collect(Collectors.toList());
        
        return new PageResult<>(voList, result.getTotal());
    }
}

前端:Vue vs React

这两个框架我都用过。说实话,没有绝对的好坏。

维度 Vue React
学习曲线 平缓,上手快 陡峭,概念多
生态 官方全家桶 社区驱动
适合场景 中小型项目 大型复杂项目
国内流行度 中等

我的建议是:如果团队前端经验不足,选Vue。如果团队有React高手,选React。ERP系统里表单多、表格多、流程多,Vue的模板语法写起来更直观。但如果你要做复杂的交互,比如拖拽、实时协作,React的灵活性更强。

数据库:MySQL vs PostgreSQL

这两个数据库我都在生产环境用过。MySQL胜在生态好,文档多,运维工具丰富。PostgreSQL胜在功能强,支持JSON、数组、全文检索。

ERP系统里,我一般这样选:

  • 业务数据(订单、库存、财务)→ MySQL,稳定可靠
  • 配置数据(流程定义、规则引擎)→ PostgreSQL,JSON支持好
  • 日志数据 → Elasticsearch,全文检索

我的经验:曾经有个项目,用MySQL存JSON字段,查询性能惨不忍睹。后来换成PostgreSQL的JSONB类型,查询速度提升了10倍。所以,选数据库要看具体场景,别盲目跟风。

2.4 API设计原则

API设计这事儿,看似简单,实则坑多。我见过太多API设计得乱七八糟的项目,前端和后端天天吵架。

RESTful原则,说白了就是用HTTP动词表达操作:

  • GET → 查询
  • POST → 创建
  • PUT → 更新
  • DELETE → 删除

举个例子,订单相关的API:

GET    /api/orders          # 查询订单列表
GET    /api/orders/{id}     # 查询单个订单
POST   /api/orders          # 创建订单
PUT    /api/orders/{id}     # 更新订单
DELETE /api/orders/{id}     # 删除订单

但RESTful不是万能的。有些操作用RESTful表达很别扭,比如"审核订单"、"取消订单"。这时候我建议用动词:

POST   /api/orders/{id}/approve    # 审核订单
POST   /api/orders/{id}/cancel     # 取消订单

API设计还有几个要点:

  • 版本控制:URL里带版本号,比如 /api/v1/orders
  • 统一返回格式:{ code: 200, message: "成功", data: {} }
  • 分页:查询列表必须支持分页,返回总条数
  • 错误处理:返回有意义的错误信息,别只给个500

避坑指南:我曾经见过一个项目,API返回格式五花八门。有的返回{ success: true },有的返回{ status: "ok" },前端解析的时候还得猜。后来我定了个规范:所有API统一返回Result对象,包含code、message、data三个字段。从此天下太平。

好了,架构设计这块就聊这么多。记住一句话:架构没有银弹,只有最适合当前场景的方案。下一章咱们聊聊数据库设计,那可是ERP系统的地基,打不好后面全白搭。