🎉🎉《Spring Boot实战案例合集》目前已更新134个案例,我们将持续不断的更新。文末有电子书目录。
💪💪永久更新承诺
我们郑重承诺,所有订阅合集的粉丝都将享受永久免费的后续更新服务。
💌💌如何获取
订阅我们的合集《点我订阅》,并通过私信联系我们,我们将第一时间将电子书发送给您。
环境:Java21
1. 使用魔法值
魔法数字是指直接出现在代码中而没有解释说明的数值。它们通常是任意的数字,在阅读代码时很难理解其含义,从而给未来的开发者(甚至是未来的你自己)带来困惑。它干什么的?什么意思?如下示例:
public class ProductDiscount {public double discount(double price) {// 0.1 代表什么意思?return price * 0.1 ;}}// 又或者public class OrderProcess {public void process(Order order) {Integer status = order.getStatus() ;if (status == 1) {} else if (status == 2) {}// ...}}
如上示例,0.1代表什么?1,2分别又是什么意思?或许时间久了写代码的人估计也不知道了吧!
这样的数字,如果出现在多个地方,很容易的被遗漏。
如何解决?
不要使用魔法数字,而是创建一个具有描述性名称的常量。这样可以提高代码的可读性和可维护性。
public class ProductDiscount {// 一个有意义的名称private static final double DISCOUNT_RATE = 0.1 ;public double discount(double price) {// 看名知意return price * DISCOUNT_RATE ;}}
总结:对于固定值,始终使用常量而不是“魔法数字”。这会使你的代码更具自文档化特性,并且更容易维护。
2. 过渡使用静态方法
在Java中,静态方法经常被误用。虽然静态方法使用起来很方便,但它们违背了面向对象编程(OOP)的原则。静态方法属于类本身,而不是类的实例,这可能会导致代码紧密耦合,难以测试或扩展。如下示例:
public class DatabaseUtils {public static boolean connectToDatabase(String url) {// Some logic to connect to databasereturn true;}}
虽然DatabaseUtils.connectToDatabase()方法看起来很有用,但它通过将所有内容都视为类级别的责任,而不是对象级别的责任,从而违背了面向对象编程(OOP)的原则。
问题:
它使你的类难以扩展。
它使单元测试变得复杂,因为静态方法不容易进行模拟。
它增加了类之间的紧密耦合。
如何解决?
不要将所有内容都设为静态,而是尝试围绕实例和依赖关系来设计你的类。这样,每个类都有自己的数据和行为,从而使你的代码更加灵活。
public class DatabaseConnection {private String url;public DatabaseConnection(String url){this.url = url;}public boolean connect(){// TODOreturn true;}}
现在,DatabaseConnection可以轻松地进行测试和扩展,而且你避免了依赖静态方法。
总结:不要将所有内容都设为静态——尽可能使用实例来提高代码的灵活性和可测试性。
3. 硬编码
在Java代码中硬编码(例如,直接在代码中指定文件位置)是另一种不良实践。这会使你的程序难以移植到不同的环境或系统,并且当文件位置发生变化时可能会导致程序出错。如下示例:
public class FileReader {public void readFile() {// 如果文件路径发生变化呢?File file = new File("D:/data.txt");// TODO}}
问题:
代码不可移植。
由于文件路径可能会随时间或在不同环境之间发生变化,因此容易出错。
如何解决:
不要硬编码,而是通过从环境变量或配置文件中读取来使它们可配置。这将使代码能够轻松适应不同的环境。
public class FileReader {public void readFile() {// 从环境变量中读取String filePath = System.getenv("PACK_DATA_XO") ;File file = new File(filePath);// TODO}}
现在,文件路径是可配置的,可以在不修改代码的情况下进行调整。
总结:避免硬编码像文件路径这样的值。使它们可配置且动态化。
4. 不正确的使用异常
Java提供了强大的异常处理功能,但它们经常被误用。一种常见的不良做法是吞掉异常——即捕获异常但不采取任何措施。如下示例(吞掉异常):
public class FileProcessor {public void processFile() {try {File file = new File("D:/data.txt") ;// TODO} catch (IOException e) {// 什么都不做}}}
问题:
如果不处理异常或至少不记录它,你将丢失有关应用程序中错误的有价值信息。
代码将更难调试,因为你不知道何时或为何会出错。
如何解决:
通过记录异常或将其重新抛给调用者来正确处理异常。这有助于你在问题发生时进行追踪。
public class FileProcessor{public void processFile() throws IOException {File file = new File("D:/data.txt") ;// TODO}}
谁调用谁处理!
你也可以这样将错误记录到日志中
public class FileProcessor {private static final Logger logger = LoggerFactory.getLogger(FileProcessor.class) ;public void processFile(){try {File file = new File("D:/data.txt") ;// TODO} catch (IOException e) {logger.log(Level.SEVERE, "文件处理失败", e) ;}}}
总结:不要忽略异常——要正确处理它们,以免遗漏重要的错误信息。
5. 忽视代码注释
虽然代码应该能够自解释,但有时并非如此。不对代码进行注释或编写很烂的文档是一种不良做法,这会给需要维护代码的其他开发人员(或未来的你自己)带来困惑。
public class TaxCalculator {public double calculateTax(double amount) {// 没有对魔法数字进行说明return amount * 0.18 ;}}
问题:
新开发人员将难以理解代码的目的。
对于代码在做什么缺乏清晰度。
如何解决:
编写有意义的注释,并使用Javadoc来为你的类和方法编写文档。
/*** 计算给定金额的税款** @param 需要计算的金额.* @return 计算后的税款.*/public double calculateTax(double amount){final double TAX_RATE = 0.18 ;return amount * TAX_RATE ;}
总结:为你的代码编写适当的注释或文档,以便其他人能够理解它,并且便于将来进行维护。
6. 过渡使用null
使用null来表示缺失或未定义的值是一种代码异味。它经常导致NullPointerException,并使代码更难推理。
public class User{private String name;public String getName() {if (name == null) {return"无" ;}return name ;}}
问题:
对null的检查会导致样板代码,并增加运行时异常的风险。
它难以追踪,并可能导致不可预测的行为。
如何解决:
在Java中使用Optional<T>,它是一个容器,用于存储可能不存在或存在的对象。
import java.util.Optional;public class User {private Optional<String> name = ... ;public String getName(){return name.orElse("无") ;}}
现在,Optional迫使你明确地思考一个值是否存在,从而使你的代码更加健壮和易读。
总结:避免过度使用null——使用Optional来优雅地处理缺失值。
有关Optional更多用法,请查看下面文章:
7. 忽视单元测试
跳过单元测试似乎可以节省时间,但往往会导致后续花费更多时间进行调试。单元测试有助于确保你的代码按预期运行,并且易于修改。
如下示例,我们应该对关于的操作进行单元测试:
public class ProductService {public Object processPrice(Product product) {// TODO}}// 编写单元测试public class ProductServiceTest {private ProductService productService ;public void testProcessPrice()Product product = new Product() ;// ...assertEquals(66, productService.processPrice(product)) ;}}
总结:始终编写单元测试以验证你的代码是否按预期工作。
以上是本篇文章的全部内容,如对你有帮助帮忙点赞+转发+收藏
推荐文章
SpringBoot强大的分布式锁组件Lock4j,支持多种实现
技术专家!Spring Boot 增强版 @RequestMapping 添加限流功能
高级开发!Spring Boot 乐观锁正确处理的3种方案,第三种方案最优雅
优雅!Chain 结合 Spring Boot 轻松实现强大的责任链模式
优雅重构Spring Boot代码,我用这6种策略消灭if else
在Spring Boot中具有多个实现的接口正确注入的6种方式


