吃透软件开发六大设计原则,告别烂代码

做开发久了,大概率都接手过别人的"烂摊子代码":明明只是改一个小bug,结果牵一发而动全身,连带好几个正常功能崩溃;新增个简单需求,却要翻遍整个项目改一堆老代码;代码堆砌杂乱,冗余逻辑遍地,排查问题耗时又费力。

很多人以为烂代码是技术不行、代码写得少导致的,其实根本原因大多是从一开始就没遵守基础的代码设计原则。只顾实现当下功能,完全不考虑后续迭代、维护和扩展。

软件开发经典的SOLID六大设计原则,是所有设计模式、架构设计的底层根基,也是程序员写出高质量代码的核心准则。不用死磕晦涩的官方文档,本文结合日常业务开发场景,用通俗易懂的大白话+真实正反案例讲透,看完就能直接落地到项目中,轻松写出低耦合、易维护、可扩展的业务代码。

一、单一职责原则:一个类,只干一件事

核心核心(开发人话):无论是类、方法还是接口,只负责一项核心业务,只有一种场景需要修改它。

新手开发最容易踩的坑,就是写"万能类""万能方法"。很多人为了省事,把一堆不相关的逻辑全部堆砌在一个类里:一个用户服务类,既要处理用户注册、登录、修改资料的业务逻辑,又要操作数据库、打印日志、导出文件数据。

短期来看,代码集中、写得快,但项目迭代几次后,弊端会彻底暴露。

❌ 反面实战案例(踩坑范本)

自定义UserService类,同时承载三大无关职责:用户业务逻辑校验、数据库数据增删改查、全局日志打印。后续只要日志格式调整、数据库读写规则变更,哪怕和用户业务毫无关系,都必须修改这个核心类,极易改动原有正常逻辑,催生隐性bug,排查难度极大。

✅ 正面实战案例(规范写法)

严格拆分职责,模块各司其职:UserService 专注用户核心业务逻辑处理,UserDao 专门负责数据库持久化操作,自定义LogUtil 工具类统一处理项目日志打印。三个模块相互独立,修改任意一个功能,完全不会影响其他模块逻辑。

遵循原则的核心价值

  • 代码逻辑清晰,单个模块功能单一,新人接手也能快速读懂

  • 大幅降低bug概率,局部修改无牵连,避免连锁问题

  • 提升迭代、排查问题效率,后期维护成本大幅降低

二、开闭原则:只做扩展,不改老代码

核心核心(开发人话):对功能扩展开放,对原有代码修改关闭。已经上线、稳定运行的成熟代码,尽量不去改动,新增需求通过新增代码实现。

这是六大设计原则中最核心、最重要的一条,也是保障项目可持续迭代的关键。绝大多数项目越迭代越乱、改一次崩一次,本质都是违背了开闭原则:每次加新需求,都直接修改核心老代码,不断堆砌if-else,让代码越来越臃肿。

❌ 反面实战案例(迭代噩梦)

项目初期仅需实现微信登录,开发者直接将登录逻辑写死在LoginService类中。后续产品迭代,需要新增QQ、抖音、手机号登录功能,开发人员直接在原有类中不断新增if-else判断、叠加新逻辑。

最终登录类代码冗长、逻辑杂乱,每新增一种登录方式都要修改核心代码,不仅代码可读性极差,每次修改都存在破坏原有登录功能的风险,线上事故概率大幅提升。

✅ 正面实战案例(优雅迭代)

提前抽象Login登录接口,统一定义登录规范,预留功能扩展入口。微信、QQ、抖音、手机号等不同登录方式,各自创建独立的实现类,实现对应专属登录逻辑。

后续无论新增多少种登录方式,只需新建接口实现类即可,零改动原有核心老代码,从根源规避迭代风险,代码整洁且扩展性极强。

遵循原则的核心价值

  • 稳定代码无需反复修改,规避改代码带来的隐性bug

  • 功能扩展灵活,适配产品快速迭代需求

  • 代码层级清晰,彻底告别臃肿的if-else堆砌

三、里氏替换原则:子类能完全替代父类

核心核心(开发人话):所有可以使用父类的场景,都能无条件用子类替换,替换后不会出现任何报错、逻辑异常,子类不能重写、篡改父类的核心通用逻辑。

简单来说:子类是父类的延伸,而非颠覆。很多开发者继承父类后,随意重写父类方法,导致父类原有通用功能失效,破坏代码继承体系,这就是典型的违背里氏替换原则。

❌ 反面实战案例(继承踩坑)

定义通用鸟类父类Bird,包含fly()飞行方法。创建子类Ostrich(鸵鸟)继承Bird后,由于鸵鸟不会飞,开发者直接重写fly()方法,抛出"无法飞行"异常。

后续项目中所有调用Bird飞行方法的场景,一旦传入鸵鸟子类对象,就会直接报错,程序逻辑崩溃,完全违背继承的意义。

✅ 正面实战案例(规范继承)

优化抽象设计,拆分通用能力:单独定义「飞行接口Flyable」,只有会飞行的鸟类(鸽子、麻雀)实现该接口;鸵鸟、鸡鸭等不会飞行的鸟类,仅继承通用Bird父类,不实现飞行接口。

父类通用方法保证稳定,子类只扩展专属特性,不篡改父类逻辑,所有父类调用场景均可安全替换子类。

遵循原则的核心价值

  • 规范继承体系,避免子类破坏父类原有逻辑

  • 保证多态调用的稳定性,杜绝替换报错问题

  • 代码复用更规范,继承关系清晰不混乱

四、依赖倒置原则:依赖抽象,不依赖具体

核心核心(开发人话):高层业务逻辑不要依赖底层具体实现类,统一依赖抽象接口。底层实现变动,不会影响高层核心业务。

日常开发中,很多新手习惯直接new具体对象实现功能,这种写法耦合度极高。一旦底层实现类修改、重构,所有调用的高层代码都要跟着改,牵一发而动全身。

❌ 反面实战案例(高耦合代码)

业务类OrderService直接new AliPay(支付宝支付)具体类,实现订单支付逻辑。代码强依赖支付宝支付实现,如果后续需要新增微信支付、银联支付,或者支付宝支付逻辑重构,必须大面积修改OrderService核心业务代码,改动成本极高。

✅ 正面实战案例(低耦合规范)

抽象统一支付接口PayInterface,定义pay()通用支付方法。支付宝、微信、银联支付分别实现该接口。

高层OrderService业务类仅依赖PayInterface抽象接口,通过注入方式获取支付对象,不关联任何具体实现。后续新增、删除、修改支付方式,完全无需改动订单核心业务代码。

遵循原则的核心价值

  • 彻底解耦高层业务与底层实现,降低代码耦合度

  • 底层逻辑迭代升级,不影响核心业务稳定性

  • 适配Spring依赖注入思想,贴合企业级开发规范

五、接口隔离原则:接口按需拆分,拒绝臃肿

核心核心(开发人话):不要定义大而全的臃肿接口,根据业务场景拆分细化接口。类只需要依赖自己需要的接口,无需继承多余、无用的方法。

很多开发者为了省事,将所有相关、不相关的方法全部塞进一个通用接口中,导致接口极度臃肿。实现类被迫继承大量无用方法,还要空实现、冗余代码堆积,严重影响代码整洁度。

❌ 反面实战案例(臃肿接口)

定义一个万能UserOperation接口,包含用户新增、删除、修改、查询、导出数据、批量导入、权限校验等所有方法。

后台管理员类需要实现全部方法,但前端普通用户类仅需查询用户信息,却必须实现接口中所有无用的增删改、导出方法,只能空实现占位,代码冗余且不规范。

✅ 正面实战案例(按需拆分)

按照业务能力拆分细化接口:QueryUserInterface(用户查询)、EditUserInterface(用户增删改)、UserFileInterface(用户数据导入导出)。

普通用户类仅实现查询接口,管理员类实现全部所需接口,各司其职,没有多余冗余方法,接口职责单一、干净整洁。

遵循原则的核心价值

  • 杜绝接口臃肿冗余,每个接口职责清晰单一

  • 实现类无需承载无用方法,精简代码体积

  • 接口复用性更强,适配不同业务场景

六、迪米特法则:最少知道原则,少耦合多隔离

核心核心(开发人话) :一个类、模块尽量少和其他模块交互,只和直接朋友通信,不了解无关模块的内部细节。通俗说:陌生人不打交道,细节不对外暴露

开发中很多耦合问题,都源于违背迪米特法则:一个类直接调用另一个类的私有属性、内部方法,层层嵌套依赖,一旦其中一个模块改动,所有关联模块全部受影响。

❌ 反面实战案例(过度耦合)

用户订单类Order,直接调用用户信息类User的私有属性(用户手机号、地址),还嵌套调用User内部的信息校验方法。

一旦User类内部属性、方法名称调整,Order类的所有关联代码全部报错,两个无关模块深度绑定,维护成本极高。

✅ 正面实战案例(低耦合隔离)

模块之间通过公开方法交互,隐藏内部细节。User类对外提供getUserInfo()公开方法,统一返回所需用户信息,内部属性、校验方法全部私有化封装。

Order类仅调用User类的公开接口获取数据,无需了解User内部实现细节,内部改动完全不会影响外部调用模块。

遵循原则的核心价值

  • 模块之间高度解耦,相互隔离,互不影响

  • 减少代码嵌套依赖,降低整体项目复杂度

  • 模块可独立复用、单独迭代,适配大型项目架构


最后总结

软件开发六大设计原则,不是纸上谈兵的理论知识,而是解决代码冗余、耦合严重、难维护、难迭代的实战利器。

简单汇总核心精髓,方便大家记忆落地:

  • 单一职责:各司其职,拒绝万能模块

  • 开闭原则:扩展新增,不改稳定老代码

  • 里氏替换:子类兼容父类,不破坏继承体系

  • 依赖倒置:依赖抽象接口,不依赖具体实现

  • 接口隔离:细分接口,拒绝臃肿冗余

  • 迪米特法则:最小交互,隐藏内部细节

写代码的终极目标,从来不是"能跑就行",而是易读、易改、易扩展、易维护。坚持遵循这六大原则,长期下来,你的代码质量和架构思维都会远超同行。

相关推荐
咖啡八杯1 小时前
GoF设计模式——命令模式
java·设计模式·架构
花椒技术17 小时前
HJPusher / HJPlayer SDK 实践:我们为什么把直播推播链路拆成一套可复用能力
设计模式·harmonyos·直播
艺艺生辉1 天前
迭代器模式-"我也想被增强for循环"
设计模式
咖啡八杯3 天前
GoF设计模式——策略模式
java·后端·spring·设计模式
槑有老呆4 天前
别再手搓 Prompt 了,那个叫"手动挡循环"
设计模式
用户6919026813395 天前
Vibe Coding 开发项目的基本范式
人工智能·设计模式·代码规范
怕浪猫6 天前
领域特定语言(Domain-Specific Language, DSL)
设计模式·程序员·架构