目 录CONTENT

文章目录

单一职责原则(SRP)—— 面向对象设计的边界感

冰点
2020-01-23 / 0 评论 / 0 点赞 / 1 阅读 / 4444 字

前言

大家好,我是冰点,今天我们来聊聊软件开发中的 单一职责原则。在多年的实操经验中,我始终坚信:单一职责原则(SRP)是构建可维护、可复用系统的第一道防线,也是每个后端开发者必须吃透的基础设计原则。

它的核心定义其实非常简洁,却藏着面向对象设计的精髓:一个类有且仅有一个引起它变化的原因。

说起来简单,但在实际开发中,尤其是新手同学,很容易陷入“功能相关就放一起”的误区。前段时间的一次项目组代码review,我就遇到了这样一个典型案例。

实操踩坑:一个类包揽三个“不相干”职责

新加入的开发同学提交了一段代码,其中设计的VehicleManage类,竟然同时承担了三个完全不相关的职责,堪称“职责混乱”的典型:

  1. 车辆信息的增删改查(CRUD):处理车辆基础信息的录入、修改、删除和查询;

  2. 车联网定位数据解析:接收车联网终端推送的定位数据,解析经纬度、速度、状态等信息;

  3. TMS调度异常报警:根据调度计划,判断车辆是否超时、偏离路线,触发异常报警并推送消息。

整个类的代码足足几百行,三种完全不同的业务逻辑混杂在一起,没有任何清晰的边界。我找他沟通时,他的解释很直白:“这些功能都和车辆相关,放在一个类里,后续调用起来更方便。”

能理解这种“图方便”的想法,但在物流SaaS、车联网这类业务复杂、迭代频繁的系统中,这种做法无异于“埋雷”。

我可能有着强迫症,受不了这种代码,所以我严格要求这个同学重构,并且约会下次再过。

隐患剖析:职责耦合的三大核心痛点

我当时耐心给他分析了其中的关键问题:这三个职责的“变化动机”完全不同,就像三个独立的齿轮,硬被塞进同一个机器里,迟早会互相干扰。

我们可以拆解来看:

  • 车辆信息CRUD的变化,源于业务方的需求调整——比如业务要新增车辆年检日期、运营资质等字段,需要修改这部分逻辑;

  • 定位数据解析的变化,源于车联网终端协议的升级——比如终端厂商更新了数据格式,或者新增了油耗、电量等解析字段,需要调整解析逻辑;

  • 异常报警的变化,源于运营方的规则调整——比如运营要修改超时报警的阈值、调整报警消息的推送渠道(短信/企业微信),需要修改报警逻辑。

如果把它们放在同一个类里,风险会非常明显:

比如,运营方要求修改报警消息的格式,开发时不小心改动了定位数据解析的代码,就可能导致定位信息解析失败,车联网监控大屏无法正常显示车辆位置;再比如,业务方新增车辆字段,修改CRUD逻辑时,误删了报警相关的代码,就会导致调度异常无法及时发现,影响整个TMS系统的正常运转。

结合我多年的架构设计经验,违背单一职责原则,通常会带来三大无法回避的痛点:

  1. 可读性差:新接手的开发需要花费大量时间,从杂乱的代码中筛选出自己需要维护的逻辑,理清类的核心功能;

  2. 可维护性低:不同职责的修改相互干扰,牵一发而动全身,容易引入线上故障,且故障排查难度极大;

  3. 复用性差:比如后续开发车联网监控大屏,只想复用定位数据解析的功能,却不得不引入整个VehicleManage类及其所有依赖,造成严重的代码冗余,也增加了系统负担。

重构方案:各司其职,明确边界

意识到问题后,我指导这位同学对代码进行了重构,核心思路就是“拆分职责,明确边界”——将原来的VehicleManage类,拆分为三个独立的类,每个类只专注于自己的核心职责:

  1. VehicleService:专注于车辆信息的管理,只负责车辆基础信息的增删改查、字段校验,不涉及任何定位和报警逻辑;

  2. PositionParseUtil:专注于车联网定位数据的解析,适配不同终端的定位协议,提供统一的解析接口,供其他模块调用;

  3. VehicleAlarmService:专注于TMS调度异常报警,负责报警规则的判断、异常事件的触发,以及报警消息的推送。

重构之后,三个类各司其职,逻辑清晰、边界分明,它们之间通过简单的依赖关系协作(比如VehicleAlarmService依赖PositionParseUtil获取车辆实时位置,判断是否偏离路线),没有任何不必要的耦合。

后续再修改某一个职责的逻辑时,只需要改动对应的类,不会影响到其他两个类,可读性、可维护性和复用性都得到了大幅提升。比如后续开发监控大屏,直接复用PositionParseUtil即可,无需引入多余的依赖。

写在最后

很多同学会觉得,遵循单一职责原则会增加类的数量,增加少量的开发成本。但在物流SaaS这种需要长期迭代、高频维护的系统中,这种“前期投入”是完全值得的。

SRP的本质,是给面向对象设计加上“边界感”——让每个类、每个方法、每个模块,都只专注于自己该做的事,不越界、不包揽。它能大幅降低系统的长期维护成本,有效避免因职责耦合引发的线上故障,也是我们构建高可用、可复用物流SaaS系统的基础。

希望今天的分享,能帮助大家更好地理解和落地单一职责原则。后续我也会继续分享更多面向对象设计原则在物流SaaS、车联网、TMS系统中的实操经验,欢迎大家留言交流~

0

评论区