写点什么

Java 开发中常见的危险信号(下)

  • 2013-12-17
  • 本文字数:2336 字

    阅读完需:约 8 分钟

Dustin Marx 是一位专业软件开发者,从业已经有 17 年的时间,他拥有电子工程学士学位,还是一位 MBA。Dustin 维护着一个博客,专门介绍软件开发的各个主题。近日,他撰文谈到了Java 开发中常见的危险信号,提出了在日常的Java 开发中我们需要尽力避免的一些不正确的做法。感兴趣的读者可以参见本系列文章的第一部分第二部分

编译器警告与IDE 或工具的警告、提示及发现

来自于 javac 编译器的警告以及 IDE 和其他代码分析工具的提示信息是 Java 中明显的危险信号。可以这么说,几乎每一个警告与提示信息都是潜在的危险信号。事实上,我在文中所提及的很多危险信号都是来自于 javac 编译器或是其他工具与 IDE 的警告或提示信息。这些警告与提示信息不仅直接对应于很多 Java 代码的危险信号,而且他们一起出现时更是表明代码出现了严重的问题,这需要引起开发者的足够重视。

关闭编译器警告与 IDE 和工具的警告及提示信息

当然了,我并不认为 FindBugs 所标识出的 Java 代码中的每个问题都是 Bug 或是 Defect。事实上,在某些情况下,我甚至会禁用掉某些提示信息,因为我并不认为这些提示信息是正确的,他们会搞乱 FindBugs 的输出。也就是说,如果关闭提示信息你需要非常谨慎才行,确保只忽略掉那些不正确的提示信息而保留下重要的警告信息。类似地,我倾向于开启很多 IDE 警告,不过会将其中一小部分关闭掉。我觉得在禁用掉 javac 警告的情况下来构建 Java 应用并不是明智之举。这样做会隐藏掉出现的危险信号,不过关闭这些警告信息的动作本身很可能就是个更大的危险信号,因为这些警告与提示信息会指出很多潜在的危险信号,需要你重点关注。

过度工程化与过早优化

过于复杂的软件通常是一种常见的开发者失调行为的结果。为了代码的灵巧而丧失可读性,或是关注于灵活性及进行没必要的过早优化而造成可读性的降低常常会导致其他问题的产生。过度工程化的开发者常常会这么做,看看能否用点什么新玩儿意,不过这对于高质量的软件来说却并没有什么好处。一旦软件变得过于复杂并且难以理解,那么维护起来就不是那么容易的事情了,而且常常会导致修改时出现问题。

举个例子,在阅读代码时你可能想知道为什么开发者没有采取更加直接的方式来实现。一方面,你可能感叹于开发者能够使用一些更加高级的特性,但另一方面,你可能又会觉得这么做要比正常情况更加复杂了。有很多事实可以证明这是一个危险信号,不过我只在几个地方看到有人会这么做。一种情况是将本来用静态Java 代码实现好好的众多功能改用反射、Spring 或是其他依赖注入、动态代理、观察者模式等方式来实现。如果用得好的话当然没什么问题,不过我经常看到有人过度使用或是滥用这些特性,这直接导致其他开发者很难理解代码的意图与作用。

将日志消息直接输出到控制台

Java 中的日志框架由来已久,如今已经有为数不少的日志框架(有些框架构建在别的框架之上),这包括传统的Log4j 1.2、Log4j 2、java.util.logging(Java Logging API)、Apache Commons Logging 及SLF4J 等。既然有这么多的日志框架,因此我会很奇怪为什么很多Java 代码中还有System.out 与System.err 语句。

Java 代码中存在着向标准输出与标准错误中进行输出可能有很多原因。其中一个原因就是有些代码还不太成熟,后面还会修改,改成输出到日志,不过到最后也没有改。使用标准输出与标准错误的另一个弊端就是这些日志消息并不会被写到日志文件中,而使用日志框架的日志消息则会被写到文件中,这样就会出现不一致的情况。第3 个问题就是日志框架提供了不少优秀的特性,如果直接写到标准输出或是标准错误中就无法使用这些特性了。这些特性包括轻松控制日志消息的级别、轻松将捕获到的异常关联到一个日志错误消息上、轻松将输出重定向到不同的目标及使用不同的格式等。虽然在直接使用输出与错误流时这些都可以通过手工来实现,不过这需要自己编写代码而不是“开箱即用的”。

除了直接使用System.out 与System.err 外,有些Java 代码还是会将信息写到标准输出与标准错误上(通常也是隐含使用了System.out 与System.err)。比如说, Throwable.printStackTrace() (在处理异常时常常会用到)就会这么做,根据 Javadoc 的说明,它会将异常与堆栈信息打印到标准错误流中。

使用 StringBuffer 而非 StringBuilder

坦白地说,这只是个小问题而已,不过却能标识出过时的 Java 代码(StringBuffer 是 JDK 1.0 引入的,而 StringBuilder 则是 J2SE 5 引入的)或是开发者并没有真正理解他们之间的区别。在大多数情况下,这两者之间的性能差别对于应用来说是微乎其微的,但由于 StringBuilder 更适合于大多数使用了 StringBuffer 的场景,因此我们还是可以从 StringBuilder 获得性能上的微小提升。 我很少发现使用 StringBuffer 而不能使用 StringBuilder 的情况。

方法与构造方法中使用了过多的参数

当方法与构造方法拥有太多的参数时,我总是担心客户端无法正确地使用他们,特别是有些参数是相同类型的情况。如果一个方法接收了 3 个字符串和 3 个布尔值,那么客户端就很容易搞混传递进去的值。编译器在这种情况下也无能为力,检测问题的唯一办法就是在运行期(通过单元测试或是其他测试)查看调用结果。过多的参数表明了不恰当的设计。

过多的显式类型转换

显式类型转换最有可能是个危险信号,因为类型转换本身并不会影响到任何功能或是逻辑,不过这却表明情况与预想的不一致。类型转换表明了不太好的设计决策(比如说没有正确利用好多态、在不合适的地方使用了继承、或是强制将一些本不该放在一些的东西放到了一起)。当然了,显式类型转换在很多情况下是恰当和必要的(比如说在获取 Spring 框架的 Bean 时),不过有时也表明设计上出现了问题。类型转换还表明 API 定义的范围过大或是 API 中使用的接口范围过大。

2013-12-17 11:182293
用户头像

发布了 88 篇内容, 共 262.0 次阅读, 收获喜欢 8 次。

关注

评论

发布
暂无评论
发现更多内容

探索支付宝云开发,开启一段100ms的神奇旅程!

TRaaS

支付宝小程序 云开发

接口测试|Fiddler界面工具栏介绍(三)

霍格沃兹测试开发学社

零基础自学:2023年的今天,请谨慎进入网络安全行业

网络安全学海

黑客 网络安全 信息安全 计算机 渗透测试

Vue插槽详解

高端章鱼哥

Vue 插槽

SQL 优化(一):慎用 SQL 函数

hungxy

Java MySQL 后端

教学实训模块升级,助力应用型数据科学人才培养|ModelWhale 版本更新

ModelWhale

数据分析 大模型 教学实训 在线编程 云课堂

完全自动驾驶车辆何时才能成为现实

来自四九城儿

小程序容器技术在移动警务中的业务价值

FinFish

小程序容器 移动警务 警务app

数智时代:新基建与低代码的绝妙碰撞!

快乐非自愿限量之名

低代码 新基建 数智转型 数智时代

视觉系统对自动驾驶至关重要|数据堂

来自四九城儿

Selenium 中并行测试的重要性

FunTester

何时使用Kafka而不是RabbitMQ

越长大越悲伤

Kafk Rabbit MQ 消息列队

复旦大学智能计算平台与世界科学智能大赛启动仪式

新云力量

智能 计算 复旦大学

解决QT QGraphicsView提升到QChartView报错的问题

芯动大师

强化学习从基础到进阶-案例与实践[6]:演员-评论员算法(advantage actor-critic,A2C),异步A2C、与生成对抗网络的联系等详解

汀丶人工智能

人工智能 深度学习 强化学习 6 月 优质更文活动 A3C算法

唯一入选中国厂商!灵雀云获Gartner® 首份《DevOps平台魔力象限报告》“荣誉提及”

York

容器 DevOps 云原生 Gartner 平台工程

Scrum看板工具在项目管理中的作用

顿顿顿

敏捷工具 scrum工具 scrum敏捷工具

强化学习从基础到进阶-常见问题和面试必知必答[6]:演员-评论员算法(advantage actor-critic,A2C),异步A2C、与生成对抗网络的联系等详解

汀丶人工智能

人工智能 深度学习 强化学习 6 月 优质更文活动

面向对象设计的逆向建模方法和开源工具

高鹏

Java 开源 架构 DDD 架构设计

机遇与挑战——超级自动化产品的国产化替代已成为大势所趋

九科Ninetech

接口测试|Fiddler抓包设置及证书配置

霍格沃兹测试开发学社

接口测试|Fiddler设置手机抓包

霍格沃兹测试开发学社

2024深圳电子展,中国国际电子信息博览会(CITE电博会)

AIOTE智博会

电子展

StarRocks & Friends 上海站活动回顾(含 PPT 下载链接)

StarRocks

数据库 OLAP MPP 大数据 开源

es笔记一之es安装与介绍

Hunter熊

elasticsearch Kibana 安装Kibana

分享一个在Reddit上保存视频到手机相册的办法真的YYDS!reddit video downloader!

frank

接口测试|Fiddler会话栏中添加IP列

霍格沃兹测试开发学社

接口测试|Fiddler弱网测试

霍格沃兹测试开发学社

如何通过场景规划帮助企业实现全面预算管理?

智达方通

智达方通 全面预算管理 财务规划和分析 财务规划与预测 全面预算管理系统

【领域驱动设计专题】一文带领你透视DDD领域驱动模型的本质和设计原理分析指南(通用语言体系)

洛神灬殇

领域驱动设计 DDD 领域驱动设计思想 领域驱动模型

Java开发中常见的危险信号(下)_Java_张龙_InfoQ精选文章