<代码整洁之道>精彩片段整理

最近在读这本<代码整洁之道>,感觉里面有很多内容都很有启发。整理下来,大家一起看下,顺便看看作者说的有没有道理。这本书的作者是:罗伯特丶马丁,大家经常叫他鲍勃大叔。下面直接进入正题,先看一下目录

文章目录

  • 1、有意义的命名
    • 1.1、变量的命名
    • 1.2、方法的命名
    • 1.3、类名
  • 2、方法的编写
    • 2.1、单一职责原则
    • 2.2、方法中的逻辑要属于一个层级
    • 2.3、不要把返回值作为方法的入参
    • 2.4、方法入参个数
    • 2.5、方法入参类型
    • 2.6、尽量使用异常,少用错误码
    • 2.7、方法中多用return、continue、goto
  • 3、注释
    • 3.1、好的注释
      • 3.1.1、作者的一个重要决策
      • 3.1.2、强调逻辑的重要性
      • 3.1.3、//todo、//fixme注解的使用
    • 3.2、坏的注释
      • 3.2.1、含糊不清的注释
      • 3.1.2、没有任何用处的注释
      • 3.1.3、太长的注释
  • 4、错误处理
    • 4.1、使用未受检异常
    • 4.2、手动抛出的异常要提供足够的上下文
    • 4.3、对异常进行分类
    • 4.4、特例对象简化调用端逻辑
    • 4.5、方法出参不要返回null,方法入参不要传递null
  • 5、边界

1、有意义的命名

这一章主要分成三个小部分。

1.1、变量的命名

主要讲究的就是见名知意,不要随便写一个 abc之类的看不懂意图的名称,会给阅读这段代码的同学造成困扰,同时这种abc的名称也不易检索。另外注意,不要用一些具有误导性的词汇。

1.2、方法的命名

方法一般都讲究单一职责,所以我们是可以根据方法的内容来凝练出一个词语或一个词组来表达这个方法的作用

1.3、类名

一般是名词

2、方法的编写

这一张主要分成三个小部分

2.1、单一职责原则

单一职责原则很好的体现了java的封装原则,一个方法,只做一件事。这样做有两个好处,方法的可复用性强,另外,方法很好阅读。

2.2、方法中的逻辑要属于一个层级

这一段内容,我认为是对单一职责原则的补充。一个方法中,是可能会遇到有多段逻辑的情况,但是这些逻辑做的事需要是一个层级的。比如:小品里说的,要把大象装冰箱,总共分几步?三步。这三步,其实都是围绕着大象装冰箱这个事来的。切忌不能在方法中做一些和主逻辑不相干的事。

2.3、不要把返回值作为方法的入参

这一点,我自己是要反思的,我经常会从外面new一个list,或者对象啥的,通过入参传递到方法中,在方法中改动这个对象。这种方式能避免就避免

2.4、方法入参个数

方法入参越少越好,最好没有入参,尽量不要超过3个,超过3个入参,会让方法理解起来很困难。如果超过了3个,最好采用一些封装的手段,将参数封装到一个对象中,然后方法的参数传递这个对象。
比如:原方法签名为:writeField(OutputStream outputStream,name)
这是一个两参数方法,如何减少方法入参个数呢?
我们可以新定义一个FieldWriter类

public class FieldWriter {private OutputStream outputStream;public void write(String name){........}
}

然后在原来引用writeField方法的地方,替换为fieldWriter.write(name),这样就利用面向对象的思想将outputStream封装到了类中,减少了方法参数的个数

2.5、方法入参类型

尽量不要入参布尔类型,更不要将布尔类型作为方法内部变更逻辑的标志

2.6、尽量使用异常,少用错误码

如果我们使用异常码的话,方法的调用方需要在逻辑中进行一系列的判断。如果方法新增了错误码,调用方很有可能需要跟着改
在这里插入图片描述
但如果用异常的话,我们可以把逻辑简化成下面这样
在这里插入图片描述
这个点,我觉着值得商榷,书上这样的写法,是不关心异常的写法,如果调用方需要根据方法的返回来做不同的逻辑呢?还是要捕获不同异常,来做不同的逻辑。
我觉着作者想表达的思想就是,让方法的调用者处理起来逻辑要简单。我们不要照抄他的说法,多学习他的思想

2.7、方法中多用return、continue、goto

不要一个逻辑写到底,在需要返回的地方,直接返回就可以了,其他人在阅读这段代码的时候,他就很容易知道,逻辑的终止点,梳理起来要容易

3、注释

按照书中作者的说法,如果我们需要给一个方法加注释,自己应该感到羞耻。加注释就意味着,方法的逻辑复杂,我们担心其他人看不懂,所以需要专门说明一下。我觉着作者的想法是有道理的,但也不是说不能用注释,作者就给列举了几个应该用注释的场景,以及如何写好注释

3.1、好的注释

3.1.1、作者的一个重要决策

比如一段算法的改进,我们可以加一个注释,说明一下我们的设计思路,使用的场景之类,这样读者可以更容易的掌握这段算法

3.1.2、强调逻辑的重要性

我们可能会写一些看似无关紧要的逻辑,如果我们担心其他人改动的时候,影响到这段逻辑,此时可以加一些注释,提醒一下。

3.1.3、//todo、//fixme注解的使用

我们要注意使用这两个特殊的注释,来表明我们将来要做的事,或者目前是一个临时的写法,未来可以改进到更好

3.2、坏的注释

3.2.1、含糊不清的注释

比如下面这段方法,这是一个著名开源项目中的一个代码片段
在这里插入图片描述
在捕获到IOException后,源码作者写了一个注释:
//No properties files means all defaults are loaded
针对这段注释,鲍勃大叔发起了一系列追问
1)、谁来加载默认的配置
2)、调用loadedProperties.load方法的时候,默认配置加载完了吗?
3)、捕获到IOException异常后,作者没有做任何的处理,就只写了一个注释,那作者是觉着不用处理,还是后面会继续处理?
这段注释能被人问出这么多问题,就证明注释写的非常失败

3.1.2、没有任何用处的注释

下面的这几个例子,就是纯纯的废话,没有提供任何有用的信息。我们完全可以使用一个有意义的变量来替代注释
在这里插入图片描述

3.1.3、太长的注释

下面这个注释,说实话,我是不想读的。太长了
在这里插入图片描述

4、错误处理

4.1、使用未受检异常

我们先看一下受检异常,受检异常,如果不捕获,程序编译会失败。我们常见的IOException,就是受检异常。
未受检异常,比如:RuntimeException。不捕获,程序可以正常编译。
使用未受检异常,代码看起来更清爽

4.2、手动抛出的异常要提供足够的上下文

足够的上下文,其实就是我们平时所说的堆栈信息。方法报错,如果能看到完整的堆栈,方法的调用者很快就能定位到问题

4.3、对异常进行分类

未分类前
在这里插入图片描述
需要捕获各种异常,看着很乱。
我们可以对异常进行一些分类,如下:
在这里插入图片描述
可以看到,我们构建出了一个PortDeviceFailure异常。然后在LocalPort类的open方法中,对各种异常进行了分类,和PortDeviceFailure异常属于一类的异常,都统一抛出PortDeviceFailure异常

4.4、特例对象简化调用端逻辑

我们看下面的一段代码。
如果未捕获到异常,调用MealExpenses的getTotal方法。
如果捕获到MealExpensesNotFound异常,调用getMealPerDiem方法
在这里插入图片描述
我们可以考虑使用多态 + 特例的方式简化以上逻辑
在这里插入图片描述
可以看到我们将getMealPerDiem方法封装成了PerDiemMealExpenses对象。如果抛出了MealExpensesNotFound异常,我们就返回PerDiemMealExpenses对象,就类似下面的处理方式

public class ExpenseReportDao {MealExpenses getMeals(String id) {try {return new NormalMealExpenses();} catch (MealExpensesNotFound e) {return new PerDiemMealExpenses();}}
}

这样,调用端的逻辑就不需要在捕获MealExpensesNotFound的异常,直接调用getMeals(String id)方法拿到MealExpenses对象,然后调用其getTotal方法就可以了

MealExpenses mealExpenses = expenseReportDao.getMeals(employee.getID());
m_total += mealExpenses.getTotal();

这样,方法调用者的处理逻辑就简化了很多。

4.5、方法出参不要返回null,方法入参不要传递null

这个很好理解,如果随意返回null或者入参有null,我们就需要判空,众所周知,判空的代码,很丑陋。

public class MetricsCalculator{public double xProjection(Point p1,Point p2){if(p1 == null){throw new IllegalArgumentException("P1 should not be null")}if(p2 == null){throw new IllegalArgumentException("P2 should not be null")}......}
}

考虑使用断言
在这里插入图片描述
断言要比传统的判断,形式上更美观一些。

5、边界

边界的理解就是:我们要将方法调用者不关心的部分封装到方法内部,不要让方法的调用者感知到,本质上还是面向对象的思想
看下面的例子

Map sensors = new HashMap();
Sensor s = (Sensor)sensors.get(sensorId);

这样的代码,相信你看到并不会陌生,这是一个强制类型转换的逻辑。
你可能会说,可以给Map加一个Sensor的泛型,这样就可以不用强转了,但是Map里可以放很多东西,不一定只放Sensor类型,如果放了其他类型,那Map的泛型就只能是Object类型,强转不可避免。
此时,我们可以考虑封装一个Sensor类

public class Sensors{private Map sensors = new HashMap();public Sensor getById(String id){return (Sensor)sensors.get(id);}...
}

持续更新…

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【MySQL】操作库 —— 表的操作 -- 详解

一、增加表 1、创建表 mysql> create database [if not exists] table_name ( -> field1 datatype, -> field2 datatype, -> field3 datatype -> ) character set 字符集 collate 校验规则 engine 存储引擎; 注意 &#xff1a;最后一行也可以写成&#x…

一、ActiveMQ介绍

ActiveMQ介绍 一、JMS1.jms介绍2.jms消息传递模式3.jms编码总体架构 二、消息中间件三、ActiveMQ介绍1.引入的原因1.1 原因1.2 遇到的问题1.3 解决思路 2.定义3.特点3.1 异步处理3.2 应用系统之间解耦3.3 实际-整体架构 4.作用 一、JMS 1.jms介绍 jms是java消息服务接口规范&…

基于PSO优化的LSTM多输入回归预测(Matlab)粒子群优化长短期神经网络回归预测

目录 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 亮点与优势&#xff1a; 二、实际运行效果&#xff1a; 三、部分代码展示&#xff1a; 四、完整代码数据分享下载&#xff1a; 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 本代码基于Matl…

哈希切分

目录 一 二 三 2.单个子文件太大怎么办&#xff1f;&#xff08;分两种情况讨论&#xff09; 一 这样的题目典型就是KV模型的问题&#xff0c;即通过key IP找对应的value 出现次数&#xff0c;对于KV模型的问题首先想到的就是用map来统计次数&#xff0c;但是100G大小的文件…

【计算机网络】多路复用和多路分解

多路分解 demultiplexing 数据到达接收主机时&#xff0c;需要指定对应的套接字&#xff0c;所以在运输层报文段中放置了一些字段用于套接字的识别&#xff0c;从而将报文段定向到套接字&#xff0c;将运输层报文段数据交付到正确套接字的工作就是多路分解。多路复用 multiple…

Spring Task定时任务

目录 1、介绍 2、cron表达式 2.1、在线生成器 2.2、通配符 3、代码示例 3.1、使用步骤 3.2、 代码开发 3.3、测试 &#x1f343;作者介绍&#xff1a;双非本科大三网络工程专业在读&#xff0c;阿里云专家博主&#xff0c;专注于Java领域学习&#xff0c;擅长web应用开发…

计算机设计大赛 深度学习OCR中文识别 - opencv python

文章目录 0 前言1 课题背景2 实现效果3 文本区域检测网络-CTPN4 文本识别网络-CRNN5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习OCR中文识别系统 ** 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;…

Python魔法方法 单例模式

前言 本文介绍一下python中常用的魔法方法以及面向对象中非常重要的单例模式。 魔法方法 python中一切皆对象&#xff0c;因为python是面向对象的编程语言。python给类和对象提供了大量的内置方法&#xff0c;这些内置方法也称魔法方法。这些魔法方法总是在某种条件下自动触…

嵌入式培训机构四个月实训课程笔记(完整版)-Linux ARM驱动编程第四天-ARM Linux编程之IIC与uart (物联技术666)

链接&#xff1a;https://pan.baidu.com/s/1V0E9IHSoLbpiWJsncmFgdA?pwd1688 提取码&#xff1a;1688 教学内容&#xff1a; 1、I2C总线&#xff1a; I2C&#xff08;Inter&#xff0d;Integrated Circuit),PHILIPS公司开发的两线式半双工同步串行总线&#xff1b;可以用来连…

MySQL安装及环境配置

目录 下载安装检验安装是否成功配置环境变量 下载 MySQL下载链接 安装 点击安装包进行安装 选择Server only&#xff0c;点击Next 点击Execute 点击Next 提示我们需要进行一些配置&#xff0c;点击Next 输入管理员密码&#xff0c;点击Next 点击Execute&#xff0c;安装配…

auto.js教程(autojs教程、autox.js、autoxjs)笔记(二)环境搭建——2、安卓手机投屏软件scrcpy的安装和使用(scrcpy教程)

参考文章&#xff1a;【自动化技术】Autojs从入门到精通 参考文章&#xff1a;AutoXJS开发入门简介菜鸟教程 参考文章&#xff1a;关于Auto.js的下架说明 参考文章&#xff1a;Auto.js 4.1.0 文档 文章目录 005--【环境搭建】2、安卓手机投屏软件scrcpy的安装和使用scrcpy官…

相机图像质量研究(15)常见问题总结:光学结构对成像的影响--暗角

系列文章目录 相机图像质量研究(1)Camera成像流程介绍 相机图像质量研究(2)ISP专用平台调优介绍 相机图像质量研究(3)图像质量测试介绍 相机图像质量研究(4)常见问题总结&#xff1a;光学结构对成像的影响--焦距 相机图像质量研究(5)常见问题总结&#xff1a;光学结构对成…