防御式编程是一种编程范式,旨在减少软件缺陷,提高代码的健壮性和可维护性。通过在编写代码时考虑各种可能的错误情况,并采取相应的措施来防止这些错误,来确保程序在遇到异常情况时仍能正常运行。本文将介绍防御式编程的两个方面:保护程序免受无效输入的侵害(Protecting Programs From Invalid Inputs)和设置路障(Barricade)。
1. 保护程序免受无效输入的侵害(Protecting Programs From Invalid Inputs)
无效输入是导致程序错误的常见原因之一。为了防止这种错误,我们需要在代码中添加验证和错误处理机制,对来自外部的数据源仔细检查、对每个函数的输入参数合法性要做仔细检查,并决定如何处理非法输入,以确保程序在收到无效输入时能够正确地响应。
以下是一些保护程序免受无效输入侵害的方法:
①验证输入:在处理用户提供的数据之前,首先检查它们是否满足预期的条件。
public void setAge(int age) {
if (age < 0 || age > 150) {
throw new IllegalArgumentException("Illegal age: " + age);
}
this.age = age;
}
在这个例子中,我们检查年龄是否在有效范围内(0到150岁)。如果年龄无效,我们抛出一个IllegalArgumentException
。
②使用默认值:当输入缺失或无效时,考虑使用默认值来替换它们。这至少可以确保程序在缺少输入的情况下仍能继续运行。
public void setUsername(String username) {
if (username == null || username.isEmpty()) {
this.username = "unNanmed_user";
} else {
this.username = username;
}
}
在这个例子中,我们检查用户名输入为空时,我们将其设置为默认值“unNamed_user”。
2.设置路障(Barricade)
“路障”是指在程序的关键部分设置检查点,以确保只有满足特定条件的数据才能通过。这可以帮助开发人员更早地发现潜在的问题,从而避免更严重的错误。
以下是一些设置路障的方法:
①断言:断言是一种在代码中插入检查点的方法。它们通常用于验证内部状态的正确性,例如对象的属性或局部变量。
public void processArray(int[] array) {
assert array.length > 0 : "Array must have at least one element";
// ...
}
在这个例子中,我们使用断言确保数组至少包含一个元素。如果数组为空,程序将抛出一个AssertionError
。
②设计不变式:通过在类和方法中建立一组固定的条件(也称为不变式),可以确保对象始终处于有效状态。这可以通过在构造函数、方法中添加验证和错误处理来实现。
public class BankAccount {
private double balance;
public BankAccount(double initialBalance) {
if (initialBalance < 0) {
throw new IllegalArgumentException("Initial balance must be non-negative");
}
this.balance = initialBalance;
}
public void deposit(double amount) {
if (amount <= 0) {
throw new IllegalArgumentException("Deposit amount must be positive");
}
balance += amount;
}
}
在这里,我们确保BankAccount
的balance
属性始终为非负值。我们通过在构造函数(设置初始余额)和deposit
方法中添加验证来实现这一点。