如何向历史遗留系统学习

入职半年以来, 除了新系统的开发之外, 还一直在维护一个历史遗留系统, 其间也经历了种种酸甜苦辣, 借此机会来从一个新人的角度谈谈如何向历史遗留系统学习.

何为历史遗留系统?

  • 运行了足够长的时间
  • 原有开发者大多已离职

历史遗留系统为何遭人诟病?

  • 原有开发者大多已离职, 业务知识丢失
  • 文档不完善, 过期或缺失
  • 各种历史遗留bug
  • 设计缺陷
  • 技术落后
  • 依赖严重, 牵一发而动全身

我的例子

我所接手的系统是一个业务中间层系统, 主要功能包含3个部分:

  • 为控制台前端提供各种REST接口, 主要包括用户注册登录, 密钥管理
  • 封装底层接口, 以统一形式提供给前端, 相当于一个代理
  • 封装底层接口, 为内部服务提供API, 并通过白名单控制访问权限
  • 提供统一的签名认证服务

系统架构大概是这样的:

此处缺少一张图

系统由独立的中间平台服务和认证服务组成, 两个系统共用同一个数据库. 然而, 这种设计是有缺陷的: 共用数据库导致两个服务耦合, 而两个服务独立部署又导致信息无法完全共享. 例如, 认证服务对性能要求较高, 需要对数据进行缓存. 而两个系统共用数据库, 从中间平台服务对认证服务相关数据更新的话, 认证服务无法感知到, 导致出现脏数据影响认证结果. 现在来看, 这还是一个挺大的bug, 有可能影响用户安全性.

此外, 还有一些代码上的缺陷:

  • 使用老版本的工具, Spring 3.1, JDK 6. 这在系统搭建时(2012年)也算是比较新的技术, 但是随着时间的推移, 并没有进行技术上的更新.
  • 代码层次差, 好歹用个事务脚本模式吧, Controller, Service, DAO三层总该有吧, 然而并没有, 所有的参数校验和业务逻辑全部写在Controller中, 直接调用DAO接口, 没有Service层, 有的Controller方法甚至有五六百行.
  • 代码规范差. 能明显感觉到作者写代码的时候比较随意, 甚至可以说有些不负责任, 比如把HTTP status和result code搞混, 返回的HTTP status出现7xx这种不规范的数字. 大量的复制粘贴, 用IDEA打开以后满屏的黄色波浪线提示重构. 然而完全没有单元测试和集成测试, 导致重构困难, 泪奔.
  • 接口文档与接口是分离编写的, 有些接口更新时文档没有同步更新, 导致文档没用甚至起反作用.

说句实话, 刚开始接手这个系统时, 我的心态是爆炸的. 然而我很快发现, 这种系统既像一本错题集, 又像一本历史书, 是值得学习的.

如何面对历史遗留系统?

  • 调整心态: 既然无处可逃, 那就死磕到底.
  • 时空穿越: 如果当时是我写的这些代码, 现在再来看, 会不会更糟?
  • 深度思考: 系统是如何走向”腐化”的?
  • 尝试改变: 有没有可能在原有基础上, 修复bug, 做些重构, 完善一下文档?
  • 上帝视角: 技术变革对软件开发有什么影响?

那么, 新系统呢?

  • 用尽可能新的技术: 延长系统的保质期
  • 良好的系统设计: 方便今后自己和其他人对系统进行修改
  • 完善的各种文档(用户帮助文档, 设计文档, 接口文档)
  • 永远不要降低对代码质量的要求, 并且不断重构!

最后, 希望我们每个人能够正视历史遗留系统, 因为它们都是软件发展史上最宝贵的财富!