当前位置: 首页 > ds >正文

【代码坏味道】膨胀类 Bloaters

🐘 长方法(Long Method)

📍 什么是长方法?

一个函数(方法)写得太长了,比如超过了 10 行代码,就要开始警惕了。

❗ 为什么不好?

  • 一开始只是加两行代码,觉得“没必要单独写个函数吧”,但一直加一直加,就变成“面条式代码”。
  • 别人读这个函数会很费劲,自己写的时候也难维护。

✅ 怎么解决?

  • 如果你想在方法里加注释解释某段逻辑,说明这段代码应该拆出去成单独方法。
  • 哪怕是只有一行代码,如果需要说明,也应该单独封装成一个有意义的方法。

🔨 可以使用的技巧:

  • 提取方法(Extract Method)

  • 如果受限于变量,可以使用:

    • 用查询代替临时变量(Replace Temp with Query)
    • 引入参数对象(Introduce Parameter Object)
    • 保留整个对象(Preserve Whole Object)

💰 好处:

  • 小方法的代码更容易看懂、改动风险小。
  • 重复代码也更容易被发现和删除。
  • 不用担心“方法太多影响性能”,其实几乎没影响。

🏢 大类(Large Class)

📍 什么是大类?

一个类(类似于一块代码模块)里面包含太多变量、方法、代码行

❗ 为什么不好?

  • 类一开始很小,但功能一多,就越写越大。
  • 程序员偷懒,喜欢往原来的类里加功能,而不是重新建一个类。

✅ 怎么解决?

  • 把类拆成更小的类,一个类只负责一种职责。

  • 使用:

    • 提取类(Extract Class)
    • 提取子类(Extract Subclass)
    • 提取接口(Extract Interface)
    • 如果是界面类太大,考虑拆成“界面类 + 数据类”

💰 好处:

  • 更容易记住和管理类里的内容。
  • 避免重复代码,代码结构更清晰。

⚙️ 原始类型痴迷(Primitive Obsession)

📍 什么是“痴迷”原始类型?

就是你过度使用 int、string 这些基本类型,而不愿意封装成对象。

比如:

  • 电话号码用 string,金额用 float,而不是专门建个 PhoneNumberMoney 类。
  • 用常量 1, 2, 3 来表示权限等级,而不是定义角色类。

❗ 为什么不好?

  • 这些基本类型不好加规则,也不好扩展。
  • 常量意义不清晰,还容易出 bug。

✅ 怎么解决?

  • 使用对象代替基本类型,比如把 price 封装成 Money 类。
  • 用类表示状态、角色,而不是数字或字符串。
  • 参数多时,用类打包(Introduce Parameter Object)

💰 好处:

  • 代码更灵活,规则清晰。
  • 更容易找到重复代码,修改也集中,不怕出错。

📬 长参数列表(Long Parameter List)

📍 什么是长参数列表?

如果一个方法需要传超过 3~4 个参数,那就太多了。

❗ 为什么不好?

  • 参数太多让方法调用变复杂,容易传错。
  • 有时为了减少依赖,把对象提前创建好再传进来,结果传了一堆参数。

✅ 怎么解决?

  • 如果多个参数来自一个对象,可以直接传这个对象(Preserve Whole Object)。
  • 如果来自不同地方,但经常一起用,就打包成一个类(Introduce Parameter Object)。

💰 好处:

  • 方法调用更简洁,代码更清晰。
  • 还能发现重复逻辑,方便提取成公共方法。

🧱 数据泥团(Data Clumps)

📍 什么是数据泥团?

如果你在多个地方看到总是成组出现的变量(比如数据库连接的 host、port、user、pass),那就是一个“数据泥团”。

❗ 为什么不好?

  • 这些变量成组出现,一变就全变,容易出错。
  • 多次复制粘贴,非常不优雅。

✅ 怎么解决?

  • 把这些成组变量封装进一个类,比如 DbConfig
  • 如果是方法参数太多,也可以用“参数对象”。

💰 好处:

  • 所有相关操作集中在一个类中,更好维护。
  • 大大减少代码行数,也避免写重复的东西。

✅ 小结:什么时候该重构?

异味类型表现处理方式
长方法方法超过 10 行拆方法、封装注释
大类类里方法、变量太多拆类、抽子类/接口
原始类型痴迷int/string 代替对象用对象封装、引入类型
长参数列表传参超过 4 个保留整个对象或参数对象
数据泥团相同变量反复出现抽成类统一管理
http://www.xdnf.cn/news/10418.html

相关文章:

  • 力扣热题100之翻转二叉树
  • C++哈希表:unordered系列容器详解
  • day15 leetcode-hot100-28(链表7)
  • C++ —— B/类与对象(下)
  • 流媒体基础解析:从压缩到传输的基本了解
  • Linux研学-用户解析
  • Java Spring 之过滤器(Filter)详解与实战
  • Correlations氛围测试:文本或图像的相似度热图
  • 2024年ESWA SCI1区TOP,自适应学习灰狼算法ALGWO+无线传感器网络覆盖优化,深度解析+性能实测
  • DeepSeek 赋能数字孪生城市,筑牢应急管理智慧防线
  • day42 简单CNN
  • C++ list数据删除、list数据访问、list反转链表、list数据排序
  • HCIE-STP复习
  • C# 密封类和密封方法
  • simulink mask、sfunction和tlc的联动、接口
  • CSS专题之层叠上下文
  • 小明的Java面试奇遇之:支付平台高并发交易系统设计与优化[特殊字符]
  • [SC]SystemC在CPU/GPU验证中的应用(三)
  • 【2025年软考中级】第二章 2.1 程序设计语言的基本概念
  • 【C语言】讲解 程序分配的区域(新手)
  • 论文笔记: Urban Region Embedding via Multi-View Contrastive Prediction
  • C#数字图像处理(一)
  • 【Hot 100】55. 跳跃游戏
  • Unity3D仿星露谷物语开发57之保存库存信息到文件
  • ROS2与Unitree机器人集成指南
  • Linux 基础IO(上)
  • javaweb-maven以及http协议
  • (LeetCode 每日一题) 909. 蛇梯棋 (广度优先搜索bfs)
  • 电子电器架构 --- OTA测试用例分析(上)
  • 华为OD机试_2025 B卷_小明减肥(Python,100分)(附详细解题思路)