Defensive Programming Tips
Introduction to Defensive Programming
Defensive programming is a systematic approach to software development that focuses on anticipating and mitigating potential errors, vulnerabilities, and unexpected scenarios.
Core Principles of Defensive Programming
mindmap
root((Defensive Programming))
Validation
Input Checking
Boundary Validation
Error Handling
Graceful Degradation
Comprehensive Exception Management
Code Robustness
Immutability
Fail-Fast Mechanisms
Argument Validation Techniques
public class UserService {
public void registerUser(String username, String email, int age) {
// Validate username
if (username == null || username.trim().isEmpty()) {
throw new IllegalArgumentException("Username cannot be empty");
}
// Email validation
if (!isValidEmail(email)) {
throw new IllegalArgumentException("Invalid email format");
}
// Age range validation
if (age < 18 || age > 120) {
throw new IllegalArgumentException("Invalid age range");
}
// Proceed with user registration
}
private boolean isValidEmail(String email) {
return email != null && email.matches("^[A-Za-z0-9+_.-]+@(.+)$");
}
}
Defensive Coding Strategies
Strategy |
Description |
Example |
Null Checking |
Prevent null pointer exceptions |
Objects.requireNonNull() |
Immutable Objects |
Create unmodifiable objects |
Collections.unmodifiableList() |
Defensive Copying |
Create copies of mutable objects |
new ArrayList<>(originalList) |
Parameter Validation |
Check method inputs |
if (value < 0) throw new IllegalArgumentException() |
Error Handling Patterns
Fail-Fast Mechanism
public class AccountManager {
private static final int MAX_WITHDRAWAL = 1000;
public void withdraw(double amount) {
// Fail-fast validation
if (amount <= 0) {
throw new IllegalArgumentException("Withdrawal amount must be positive");
}
if (amount > MAX_WITHDRAWAL) {
throw new IllegalStateException("Withdrawal amount exceeds daily limit");
}
// Proceed with withdrawal
}
}
Immutability and Thread Safety
public final class ImmutableUser {
private final String username;
private final String email;
public ImmutableUser(String username, String email) {
// Defensive copying and validation
this.username = Objects.requireNonNull(username, "Username cannot be null");
this.email = Objects.requireNonNull(email, "Email cannot be null");
}
// Only getter methods, no setters
public String getUsername() {
return username;
}
public String getEmail() {
return email;
}
}
Advanced Defensive Techniques
Optional Usage
public Optional<User> findUserById(int id) {
return Optional.ofNullable(userRepository.findById(id))
.filter(user -> user.isActive())
.orElseThrow(() -> new UserNotFoundException("User not found"));
}
LabEx Best Practices
At LabEx, we recommend implementing comprehensive defensive programming techniques to create more reliable and maintainable software solutions.
flowchart TD
A[Defensive Programming] --> B{Performance Impact}
B -->|Minimal Overhead| C[Recommended Validations]
B -->|Significant Overhead| D[Optimize Validation Logic]
Conclusion
Defensive programming is not about creating perfect code, but about anticipating and gracefully handling potential issues before they become critical problems.