【架构设计】你的类足够“专一”吗

news2024/11/23 9:41:09

前言

软件设计SOLID原则中有一个最基础的原则就是单一职责原则,我想绝大部分的程序员都知道,而且都理解它的意思,甚至觉得很简单。但是往往“看懂”和“会用”是两回事,而“用好”更是难上加难。好比我们项目,一开始一直和大家强调类的单一职责,随着业务不断发展,不同的同事都往这个类“添砖加瓦”,最终导致一个类5000多行,如下图所示,连IDE都受不了,变得卡顿,可想后面维护成本有多大了,究竟为什么会这样呢?又该如何解决呢?

欢迎关注微信公众号「JAVA旭阳」交流和学习

什么是单一职责原则(SRP)?

单一职责原则的英文是 Single Responsibility Principle,缩写为 SRP。这个原则的英文描述是这样的:A class or module should have a single reponsibility。如果我们把它翻译成中文,那就是:一个类或者模块只负责完成一个职责(或者功能)。简单来说,一个类只负责完成一个职责或者功能。也就是说,不要设计大而全的类,要设计粒度小、功能单一的类。

上例子,比如,一个类里既包含订单的一些操作,又包含用户的一些操作。而订单和用户是两个独立的业务领域模型,我们将两个不相干的功能放到同一个类中,那就违反了单一职责原则。为了满足单一职责原则,我们需要将这个类拆分成两个粒度更细、功能更加单一的两个类:订单类和用户类。

如何判断类是否够“专一”?

听起来类的单一职责很简单,很容易区分清楚,就比如上面的例子中的用户和订单,那为什么我们在开发过程中还是容易把一个类写的越来越大呢?好吧我们项目中的这个5000多行的类,实际上都是和“指标”这个领域模型的相关操作,所以对于大部分同事很难去界定出来哪些功能归为一类,属于一个职责范围之内的,既然搞不清楚,那么我就都写一起好了,大部分都是这样去写代码的。

这边再用一个实际的例子解释下这种模糊的情况。

比如下面的UserInfo类的设计是否满足单一职责原则呢?

public class UserInfo {
 private long userId;
 private String username;
 private String email;
 private String telephone;
 private long createTime;
 private long lastLoginTime;
 private String avatarUrl;
 private String provinceOfAddress; // 省
 private String cityOfAddress; // 市
 private String regionOfAddress; // 区
 private String detailedAddress; // 详细地址
 // ... 省略其他属性和方法...
}
  • 有人认为,UserInfo 类包含的信息都是用户相关的行为,满足单一职责原则。
  • 有人认为,地址信息在 UserInfo 类中,所占的比重比较高,可以继续拆分成独立的 UserAddress 类,UserInfo 只保留除 Address 之外的其他信息,拆分之后的两个类的职责更加单一。

其实是否满足单一职责原则,需要结合具体的业务场景,如果你现在是社交场景中,地址单纯用来展示使用,那么它就是符合单一职责原则。如果在电商场景中,地址就要订单、物流等信息中出现,那么就要做进一步拆分。

所以说,不同的应用场景、不同阶段的需求背景下,对同一个类的职责是否单一的判定,可能都是不一样的。在某种应用场景或者当下的需求背景下,一个类的设计可能已经满足单一职责原则了,但如果换个应用场景或着在未来的某个需求背景下,可能就不满足了,需要继续拆分成粒度更细的类。

小结:

评价一个类的职责是否"专一",我们并没有一个非常明确的、可以量化的标准,可以说,这是件非常主观、仁者见仁智者见智的事情。实际上,在真正的软件开发中,我们也没必要过于未雨绸缪,过度设计。所以,我们可以先写一个粗粒度的类,满足业务需求。随着业务的发展,如果粗粒度的类越来越庞大,代码越来越多,这个时候,我们就可以将这个粗粒度的类,拆分成几个更细粒度的类,进行持续重构

该具体怎么做?

上面判定一个类是否具备单一职责,还是比较模糊、主观,那么有没有具体地、可执行的标准来判断呢?比如以我们的项目为例:

  • 最关键的一条,如果类中的代码行数、函数或属性过多,影响到代码的可读性和可维护性,就需要考虑对类进行拆分。我们项目后面要求代码不能超过1500行,函数最好不要超过20个。
  • 私有方法过多,我们就要考虑能否将私有方法独立到新的类中,设置为 public 方法,供更多的类使用,从而提高代码的复用性;
  • 类中大量的方法都是集中操作类中的某几个属性,比如,在 UserInfo 例子中,如果一半的方法都是在操作 address 信息,那就可以考虑将这几个属性和对应的方法拆分出来。
  • 另外一个很关键的一点是,在为了一个加方法、属性的时候,一定要想清楚这是不是这个属于这个类职责,不清楚,就问问团队其他人,慢慢培养自己的“专业感”,千万不要有无脑地放哪里都行、实现功能就行的心态。

总结

本文探讨了类的单一职责原则,如何判定一个类是否"专一",以及具体该如何做。不仅仅是类,我们可以进行引申,你的方法足够单一吗?你的模块或者服务足够单一吗?另外,很关键的一点就是你在写代码的时候,一定要动脑子,思考这段代码写这里合适吗?,为这段代码找到一个真正属于它的“家”。多多思考,那么你一定会变得越来越专业。

欢迎关注微信公众号「JAVA旭阳」交流和学习
更多学习资料请移步:程序员成神之路

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/115172.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

取代OpenFeign:Spring Framework 6全新声明式客户端@HttpExchange

本文已被https://yourbatman.cn收录;女娲Knife-Initializr工程可公开访问啦;程序员专用网盘https://wangpan.yourbatman.cn;技术专栏源代码大本营:https://github.com/yourbatman/tech-column-learning;公号后台回复“…

【几种可调动对象,Function和bind;线程的调动方式举例】

1.可调动对象的调动方式 方法 1、函数指针调动 方法2 、类类型的括号的重载 调动可调动对象 #include<iostream> #include<functional> using namespace std; struct Foo {void operator()(int x){cout<<"Foo operator "<<x<<endl;}…

CSS3【定位的基本使用[静态定位\相对定位\绝对定位]、子绝父相、固定定位、元素的层级关系】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录一、定位1.1定位的基本介绍1.1.1 网页常见布局方式1.1.2 定位的常见应用场景1.2 定位的基本使用1.2.1 定位初体验1.2.2 使用定位的步骤1.2.3 静态定位1.2.4 小结1.2.…

使用 Docker Hub 完美地存储 Helm 图表实战

使用 Docker Hub 完美地存储 Helm 图表实战 Helm 是 Kubernetes 的包管理器。它是一个开源容器编排系统。它通过提供一种简单的方法来定义、安装和升级复杂的 Kubernetes 应用程序&#xff0c;帮助您管理 Kubernetes 应用程序。 使用 Helm&#xff0c;您可以将您的应用程序打包…

git教程

教程目录Git 教程Git 与 SVN 区别Git 与 SVN 区别点&#xff1a;Git 安装配置Linux 平台上安装Debian/UbuntuCentos/RedHatWindows 平台上安装Mac 平台上安装Git 配置用户信息文本编辑器##差异分析工具查看配置信息Git 工作流程Git 工作区、暂存区和版本库基本概念Git 创建仓库…

semargl 软件使用方法简介

文章目录前言一、semargl 软件使用简介1.semargl 软件简介2.准备演示软件操作所需的数据3.使用 semargl 获取频谱关系4.使用 semargl 获取特定频率模式的空间分布5.使用 semargl 获取自旋波的色散关系二、笔记05第三节内容的补充1.优化多进程读取磁化数据文件的代码2.新增获取特…

【JavaSE】 常用类(447~515)

String 447.常用类-每天一考 1.画图说明线程的生命周期&#xff0c;以及各状态切换使用到的方法等 状态&#xff0c;方法 2.同步代码块中涉及到同步监视器和共享数据&#xff0c;谈谈你对同步监视器和共享数据的理解&#xff0c;以及注意点。 synchronized(同步监视器){//操…

Python手势识别与追踪

程序示例精选 Python手势识别与追踪 如需安装运行环境或远程调试&#xff0c;见文章底部微信名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对<<Python手势识别与追踪>>编写代码&#xff0c;代码整洁&#xff0c;规则&#xff0c;易读。 应…

【日常】圣诞节、颜色⛄

2022年圣诞节到来啦&#xff0c;很高兴这次我们又能一起度过~ 关于圣诞节&#x1f384;&#xff0c;大家想到什么颜色&#xff1f;⛄&#x1f98c;&#x1f381;&#x1f385;&#x1f525; demo online - https://codepen.io/adamlindqvist/pen/EaPeJg html <!-- Christ…

详细介绍关于自定义类型:结构体、枚举、联合【c语言】

文章目录结构体结构体的声名特殊的声明结构成员的类型结构的自引用结构体变量的定义和初始化结构体内存对齐修改默认对齐数结构体变量访问成员结构体传参结构体实现位段&#xff08;位段的填充&可移植性&#xff09;位段的内存分配位段的跨平台问题枚举枚举类型的定义枚举的…

【Linux】用户与用户组操作_补

文章目录一.用户1.1 用户与用户组概念1.2 与用户管理相关的系统文件1.3 查看用户组1.3.1用户组密码配置文件&#xff0f;etc&#xff0f;gshadow1.4用户管理创建用户修改用户添加密码一.用户 1.1 用户与用户组概念 用户和用户组的对应关系有&#xff1a;一对一、一对多、多对一…

【C语言进阶】指针练习题

写在前面 这是指有关指针的小题 正文 练习一 int main() {int a[5][5];int (*p)[4];pa;printf("%p,%d", &p[4][2]-&a[4][2], &p[4][2]-&a[4][2] );return 0; } 解析&#xff1a; a[4][2]为如图粉色部分&#xff0c;p[4][2]为如图蓝色部分。a的…

【ROS通信机制实战练习】通过话题发布实现turtlesim小乌龟圆周运动

本节记录下使用ROS中的话题机制&#xff0c;实现turtlesim中小乌龟的圆周运动。 如果想通过话题通信机制&#xff0c;实现小乌龟的圆周运动&#xff0c;需要首先明确小乌龟的运动情况&#xff0c;以及所涉及的指挥运动的参数&#xff0c;这里需要首先手动发布一个turtlesim的节…

springboot整合mybatis代码快速生成

特别说明&#xff1a;本次项目整合基于idea进行的&#xff0c;如果使用Eclipse可能操作会略有不同&#xff0c;不过总的来说不影响。 springboot整合之如何选择版本及项目搭建 springboot整合之版本号统一管理 springboot整合mybatis-plusdurid数据库连接池 springboot整合…

String 字符串

String 基本介绍 String 应该是 Java 中最常用的一个对象&#xff0c;他不是八种基本数据类型的其中之一&#xff0c;但是随便翻了一下项目代码&#xff0c;用 String 定义的变量超过百分之八十。 public final class Stringimplements java.io.Serializable, Comparable<…

VUE3-计算属性和监听器《五》

目录 一&#xff0c;计算属性 二&#xff0c;监听器 在vue3种&#xff0c;当界面上需要处理一些数据的时候&#xff0c;可以通过计算属性和监听器处理&#xff0c;他们都是对一个属性进行操作的&#xff0c;然后返回数据。 他们的区别是&#xff0c;计算属性&#xff0c;是通…

20221226英语学习

今日短文 When we are shown two options, our eyes tend to flick from one to the other and back again several times as we deliberate on the pros and cons of each. Researchers at Johns Hopkins University in the US have found that the speed with which our ey…

Hbase是什么?

Hadoop Database简介表结构数据只能读不能改>生成新版本总结简介 永远的百度百科 HBase是一个分布式的、面向列的开源数据库&#xff0c;一个结构化数据的分布式存储系统”。 HBase不同于一般的关系数据库&#xff0c;它是一个适合于非结构化数据存储的数据库。另一个不同的…

过年首秀 - 用python写一个自动生成春联的软件并打包exe

前言 哈喽啊&#xff0c;我亲爱的铁铁们&#xff0c;I am back &#xff01;&#xff01; 别管&#xff0c;我也是阳过的人了&#xff0c;这么久都没有更新&#xff0c;今天就带来个小玩意吧 这不是过完圣诞就要过年了吗 这不得准备准备&#xff0c;春节的表演&#xff1f;…

excel数据处理技巧:组合函数统计产品批号

这是一个看似普通的编号问题&#xff0c;可竟然动用了TEXT和SUMPRODUCT两个重量级的函数共同出手才得以解决。以往遇到的编号问题&#xff0c;大多数都是COUNTIF的拿手好戏&#xff0c;但是今天这个问题COUNTIF完全插不上手&#xff0c;来看看模拟的数据吧。 如图所示&#xff…