聊城市排污权交易系统开发复盘——初次真实项目实践总结

前言

在实验室的带领下,我有幸投身于聊城市排污权交易工作管理系统的后端开发项目。初涉真实项目开发领域,我在编码过程中,既察觉到自身代码风格与实际工程要求存在的差距,又收获了珍贵的工程实战经验。接下来,我将从团队协作和代码实践这两个角度,对这段经历展开总结。


一、团队协作实践

1. Git协作流程规范化

在独立开发中,我常采用单分支提交模式。参与真实项目后,深刻认识到版本控制的重要性:

2. 工程化开发工具

使用coding工具

  • 项目协同
  • 代码托管
  • 持续集成
  • 持续部署
    每次合并新分支到主分支能够自动检测分析代码,并且部署相应环境,前端能够拿到对应的swagger接口,进行调试

二、代码开发实践

1. 框架应用

在此之前,使用过ruoyi框架搭建我的项目的后台,见到项目使用yudao进行开发,拉下代码的时候不会感到陌生

2.分层思想

自己独立开发,为了图方便,经常将业务代码放在控制层,控制层需要引入多个不同类型的bean可读性较差,后期维护困难
本次项目严格要求分层,controller->service->mapper
我发现,mapper层继承的并不是Mybatisplus生成的BaseMapper,而是yudao再次进行封装的BaseMapperX
这主要是

  • 在 MyBatis Plus 的 BaseMapper 的基础上拓展,提供更多的能力
    1. {@link BaseMapper} 为 MyBatis Plus 的基础接口,提供基础的 CRUD 能力
    1. {@link MPJBaseMapper} 为 MyBatis Plus Join 的基础接口,提供连表 Join 能力

3. 类型转换规范

项目明令禁止在业务层使用BeanUtils.copyProperties(),强制要求:

  • 定义专用Converter类实现DTO/VO转换
  • 复杂对象采用MapStruct自动生成转换器
  • 转换逻辑必须显式声明字段映射关系
    一开始并不是很理解,后来查阅资料发现许多弊端:类型不一致导致拷贝失败、null值覆盖、导包冲突、浅拷贝特性及低效的反射实现等问题‌‌

为了避免这些问题,使用以下替代方案:

  • ‌手动赋值‌:通过手动编写getter和setter方法进行赋值,虽然工作量大,但可以精确控制每个字段的赋值过程。
  • ‌使用MapStruct工具提供了更灵活且高效的映射机制,支持复杂的映射规则,并且避免了反射带来的性能问题。

4. 地区数据加载

在遇到需要根据地区编号查询地区名称的时候:
我以为的方案,在数据库中查询地区编码和对应的地区名称
实际上:

  1. 提前编写对应的csv(逗号分隔值(Comma-Separated Values,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本)。)静态文件
  2. 项目读取对应的文件,使用map存储在内存中
    private AreaUtils() {  
    long now = System.currentTimeMillis();
    areas = new HashMap<>();
    areas.put(Area.ID_GLOBAL, new Area(Area.ID_GLOBAL, "全球", 0,
    null, new ArrayList<>()));
    // 从 csv 中加载数据
    List<CsvRow> rows = CsvUtil.getReader().read(ResourceUtil.getUtf8Reader("area.csv")).getRows();
    rows.remove(0); // 删除 header for (CsvRow row : rows) {
    // 创建 Area 对象
    Area area = new Area(Integer.valueOf(row.get(0)), row.get(1), Integer.valueOf(row.get(2)),
    null, new ArrayList<>());
    // 添加到 areas 中
    areas.put(area.getId(), area);
    }

    // 构建父子关系:因为 Area 中没有 parentId 字段,所以需要重复读取
    for (CsvRow row : rows) {
    Area area = areas.get(Integer.valueOf(row.get(0))); // 自己
    Area parent = areas.get(Integer.valueOf(row.get(3))); // 父
    Assert.isTrue(area != parent, "{}:父子节点相同", area.getName());
    area.setParent(parent);
    parent.getChildren().add(area);
    }
    log.info("启动加载 AreaUtils 成功,耗时 ({}) 毫秒", System.currentTimeMillis() - now);
    }

三、成果与收获

  1. 掌握Git团队协作流程
  2. 熟悉真实项目开发规范
  3. 完成有偿使用库、建设项目库、确权信息库、拟建项目库等模块的开发,共计153次提交,44次合并请求

结语

本次项目让我深刻认识到,真实项目开发不仅需要技术实现能力,更要建立工程规范意识。
特别感谢实验室各位学长的耐心指导,也特别感谢实验室给予的条件,让我接触到真实的项目开发过程。