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

045-代码味道-数据泥团

代码味道-数据泥团

代码味道之Data Clumps:数据泥团的识别与重构实践

一、定义与特征

Data Clumps(数据泥团)是代码异味中的一种典型表现,指一组数据元素(变量、参数等)频繁在多个地方成组出现,但未被封装为独立对象。其核心特征包括:

  • 参数耦合:多个参数总是一起传递(如
    void processOrder(int orderId, string userId, double amount, Date date)
  • 成员变量散落:多个类中存在重复的变量组合(如订单号+用户ID+金额)
  • 逻辑分散:对数据的操作分散在多个函数中

二、C++示例代码演示

问题代码(Data Clumps存在)

// 订单处理类
class OrderProcessor {
public:void createOrder(int orderId, string userId, double amount, Date date) {validateOrder(orderId, userId, amount, date);saveToDatabase(orderId, userId, amount, date);}void updateOrder(int orderId, string userId, double amount, Date date) {// 重复的参数组合 checkUserCredit(userId, amount);updateDatabase(orderId, userId, amount, date);}private:void validateOrder(int orderId, string userId, double amount, Date date) {// 验证逻辑 }
};

重构后代码(Data Clumps消除)

// 封装订单数据 
struct OrderData {int orderId;string userId;double amount;Date date;bool isValid() const {// 集中式验证逻辑 return orderId > 0 && !userId.empty()  && amount > 0;}
};// 重构后的订单处理类
class OrderProcessor {
public:void createOrder(const OrderData& data) {if (data.isValid())  {saveToDatabase(data);}}void updateOrder(const OrderData& data) {checkUserCredit(data.userId,  data.amount); updateDatabase(data);}private:void saveToDatabase(const OrderData& data) {// 数据库操作 }
};

三、重构过程分析

1. 识别数据泥团

通过以下线索发现Data Clumps:

  • 参数列表冗长createOrderupdateOrder均传递4个参数
  • 重复参数组合userIdamount在多个函数中成组出现
  • 验证逻辑分散:订单有效性验证分布在多个函数中
2. 封装策略

采用**Introduce Parameter Object(引入参数对象)**模式:

  1. 创建OrderData结构体封装相关字段
  2. 将分散的验证逻辑迁移至OrderDataisValid()方法
  3. 修改函数参数为OrderData对象
3. 改进效果
指标重构前重构后
函数参数数量41
重复代码量3处0
维护成本
扩展性

四、解决方案总结

1. 核心原则
  • 单一职责:数据操作与业务逻辑分离
  • 封装性:通过对象隐藏数据细节
  • DRY原则:消除重复参数组合
2. 实践步骤
  1. 识别泥团:通过参数列表、成员变量分布定位
  2. 创建对象:将相关数据封装为独立类/结构体
  3. 迁移逻辑:将关联操作迁移到新对象中
  4. 修改接口:调整函数参数为新对象类型
3. 工具辅助
  • 静态分析工具:SonarQube可检测长参数列表
  • IDE重构功能:利用Extract Class等重构操作

五、扩展思考

当数据泥团涉及跨类操作时,可进一步采用**Domain-Driven Design(领域驱动设计)**模式,例如:

// 领域对象设计 
class Order {
private:OrderData data;BillingService billing;public:void placeOrder() {if (data.isValid())  {billing.processPayment(data.amount); saveToRepository();}}
};

通过这种设计,数据泥团不仅被封装,还与业务逻辑形成有机整体,符合高内聚低耦合的设计原则。

作者郑天佐
邮箱zhengtianzuo06@163.com
主页http://www.zhengtianzuo.com
githubhttps://github.com/zhengtianzuo
http://www.xdnf.cn/news/12023.html

相关文章:

  • 量子比特实现方式
  • 【Linux基础知识系列】第十一篇-Linux系统安全
  • 2025年低延迟业务DDoS防护全攻略:高可用架构与实战方案
  • 「数据分析 - NumPy 函数与方法全集」【数据分析全栈攻略:爬虫+处理+可视化+报告】
  • 如何基于Mihomo Party http端口配置git与bash命令行代理
  • Kafka 核心架构与消息模型深度解析(二)
  • graylog收集rsyslog实现搜索解析
  • Linux驱动:register_chrdev_region、 alloc_chrdev_region
  • Kaggle-Predicting Optimal Fertilizers-(多分类+xgboost)
  • 灵活控制,modbus tcp转ethernetip的 多功能水处理方案
  • 第二章 2.4 数据共享与使用之数据共享方式
  • 在 CentOS 上安装 Docker 和 Docker Compose 并配置使用国内镜像源
  • 仓库自动化搬运:自动叉车与AGV选型要点及核心技术解析
  • javaweb -html -CSS
  • uniapp微信小程序视频实时流+pc端预览方案
  • uniapp+<script setup lang=“ts“>解决有数据与暂无数据切换显示,有数据加载时暂无数据闪现(先加载空数据)问题
  • QObject::connect: Cannot queue arguments of type ‘xxx‘
  • 4.2 HarmonyOS NEXT分布式AI应用实践:联邦学习、跨设备协作与个性化推荐实战
  • Flask-SQLAlchemy使用小结
  • 学习路之php--性能优化
  • Linux信号捕捉技术深度解析
  • html-pre标签
  • 解锁Java线程池:性能优化的关键
  • Spring Boot缓存组件Ehcache、Caffeine、Redis、Hazelcast
  • 在 Ubuntu 24.04 LTS 上安装 Jenkins 并配置全局工具(Git、JDK、Maven)
  • 余氯传感器在智慧水务系统中如何实现IoT集成
  • 数字证书_CA_详解
  • 超越传统:AAT Bioquest Calbryte探针的高信噪比与快速动力学特性解析
  • 实时数据仓库是什么?数据仓库设计怎么做?
  • 攻防世界-XCTF-Web安全最佳刷题路线