Error Handling and Exceptions
# CHAPTER 7
Error Handling and Exceptions
1. Introduction
Things go wrong in software. Databases crash, network requests timeout, and users upload massive files they shouldn't. Handling these errors is a mandatory part of programming. However, if error handling obscures the main business logic, the code is not clean. In legacy systems, developers used "Error Codes" (e.g., returning-1 if a function failed), leading to massive, deeply nested webs of if/else checks that buried the actual logic. In this chapter, we will master Clean Error Handling. We will abandon return codes in favor of Exceptions, learn how to prevent "Silent Failures," and explore Defensive Programming to ensure our applications fail gracefully.
2. Learning Objectives
By the end of this chapter, you will be able to:- Contrast legacy "Error Return Codes" with modern "Exceptions."
-
Write clean
try-catch-finallyblocks that do not obscure business logic.
- Avoid the catastrophic anti-pattern of "Silent Failures."
- Create descriptive, custom Exception classes.
- Implement Defensive Programming to fail fast and fail loudly.
3. Use Exceptions, Not Return Codes
In the past, functions would return a special flag to indicate failure. *Bad (Return Codes):**The Problem:* The caller is forced to check for errors immediately after every single function call. This creates deeply nested, unreadable code where the error handling dominates the business logic.
*Clean (Exceptions):*
*The Solution:* The business logic is clean and uninterrupted in the try block. The error processing is cleanly separated into the catch blocks.
4. The "Silent Failure" Anti-Pattern
The most dangerous thing a developer can do is catch an exception and do nothing. *Catastrophic (Silent Failure):**The Result:* The payment failed, but the system continues executing as if it succeeded. The company loses money, and there is zero log data to investigate. Always log exceptions or throw them up the chain.
5. Provide Context with Exceptions
When you throw an exception, provide enough context so the developer reading the log file instantly knows what happened.-
*Bad:*
throw new Exception("Error in file upload.");
-
*Clean:*
throw new FileUploadException("Upload failed for User ID: {$userId}. File size exceeded the 5MB limit.");
6. Custom Exception Classes
Do not throw genericException objects everywhere. Create custom exception classes that map to your business domain.
-
Example:
InsufficientFundsException,InvalidTokenException,DatabaseConnectionException.
catch blocks that handle different errors in completely different ways (e.g., showing a UI message for insufficient funds, but triggering a pager alert for a database crash).
7. Diagrams/Visual Suggestions
*The Try-Catch Separation of Concerns*8. Best Practices
-
Fail Fast: If a function receives invalid arguments, do not let it execute half its logic before failing. Check the arguments on Line 1 of the function, and
throw new InvalidArgumentException()immediately. This is defensive programming.
-
Don't Return Null: Returning
nullforces the caller to writeif ($obj === null)everywhere. Instead, throw an Exception, or use the "Special Case Object" pattern.
9. Common Mistakes
- Using Exceptions for Control Flow: Exceptions are for *exceptional*, unexpected errors (database down, file missing). Do not use them for standard logic routing (e.g., throwing an exception just because a user typed the wrong password; that is a normal business rule, not an application crash).
10. Mini Project: Refactor Error Handling
Scenario: Fix this login controller that uses error codes and silent failures. *Before:**After (Clean Exceptions):*
*(The controller calling login() will wrap it in a try-catch to handle the UI responses).*
11. Practice Exercises
-
1.
Explain why returning
-1orfalseto indicate an error is an outdated and dangerous practice compared to throwing an Exception.
- 2. What is a "Silent Failure"? Write a brief example of how it can destroy data integrity.
12. MCQs with Answers
According to Clean Code, why should developers prefer Exceptions over returning Error Codes?
Which of the following is considered an abuse of Exceptions?
13. Interview Questions
-
Q: You are reviewing code and see an empty
catchblock (Catch and Ignore). Explain to the developer the catastrophic risk they are introducing to the production environment.
- Q: Explain the concept of "Fail Fast." Why is it better for an application to throw a massive error on startup than to run quietly with corrupt configuration data?
-
Q: A developer has a function that searches for a user. If the user isn't found, they return
null. Explain the maintenance issues this causes (NullPointerExceptions) and propose a cleaner alternative.
14. FAQs
Q: Should I put a try-catch block inside every single function? A: No! That creates massive clutter. Usually, exceptions are allowed to "bubble up" to a central handler (like the framework's Router or Controller), which catches them all in one place, logs the error, and returns a clean 500/400 HTTP response.15. Summary
In Chapter 7, we learned that error handling is a necessity, but it must not obscure our business logic. We discarded legacy error codes that cause unreadableif/else nesting, adopting the clean separation provided by try-catch exception handling. We identified the catastrophic danger of silent failures and committed to failing fast and loudly. By creating rich, context-heavy custom Exceptions, we empower our monitoring systems and future developers to instantly diagnose and resolve production incidents.