# Chapter 10: Putting It All Together
**"The OOA&D Lifecycle"**
## Overview
This chapter serves as the grand finale of the book. It takes all the tools, principles, and techniques learned in Chapters 1β9 and applies them to a single, end-to-end project: the **Objectville Subway Route Finder**. The chapter demonstrates the full software development lifecycle, from gathering initial feature requests to delivering a robust, flexible application.
---
## Case Study: Objectville Subway (The Problem)
Objectville needs a system to help tourists and travel agents find routes between subway stations.
* **The Goal:** A program that takes a starting station and an ending station and prints out the directions (the route).
* **The Input:** A text file containing all station connections (`ObjectvilleSubway.txt`).
---
## Phase 1: Gathering Requirements (Features & Use Cases)
The lifecycle starts with understanding what we are building.
### 1. Feature List
We identify the high-level features the system needs:
1. Represent the subway network (stations and lines).
2. Load the subway network from a file.
3. Calculate the route between two stations.
4. Print the route directions.
### 2. Use Cases
We map these features to user interactions.
* **Primary Use Case:** "Get Directions"
* **Actor:** Tourist / Travel Agent.
* **Goal:** Find a path from Station A to Station B.
* **Steps:**
1. User provides Start Station and End Station.
2. System calculates the route.
3. System displays the route.
* **Supporting Use Case:** "Load Network"
* *Note:* This is an administrative or startup task required for the system to function, even if the end user doesn't explicitly trigger it every time.
---
## Phase 2: Analysis (Breaking it Down)
We break the system into logical modules to ensure separation of concerns (**High Cohesion**).
### Modular Architecture
1. **Subway Loader:** Responsible for reading the file and creating the network.
2. **Subway:** Represents the network itself (Stations and Connections).
3. **Subway Printer:** Handles outputting the directions (UI logic).
4. **Tester:** Proves the system works.
### Class Identification (Domain Analysis)
* **Station:** A specific location (Name).
* **Connection:** A link between two stations (Station 1, Station 2, Line Name).
* **Subway:** The container for all Stations and Connections.
---
## Phase 3: Iterative Design & Development
We don't build the whole thing at once. We iterate.
### Iteration 1: Representing the Subway
* **Goal:** Create the `Station`, `Connection`, and `Subway` classes and verify we can load data.
* **Key Design Decision:** `Station` Equality.
* *Problem:* If we load "HTML Heights" twice, is it the same object?
* *Solution:* Override `equals()` and `hashCode()` in the `Station` class. Two stations are "equal" if they have the same name. This simplifies the logic significantlyβwe don't need to manage complex object references, just names.
* **Code Snippet (Defensive Coding):**
```java
public boolean equals(Object obj) {
if (obj instanceof Station) {
Station otherStation = (Station) obj;
if (otherStation.getName().equalsIgnoreCase(this.name)) {
return true;
}
}
return false;
}
```
### Iteration 2: Calculating the Route (The Algorithm)
* **Goal:** Implement the routing logic.
* **The Problem:** How do we find a path?
* **The Solution:** Breadth-First Search (BFS).
* We don't need to invent this; we use a known algorithm.
* *Logic:* Start at A. Look at all neighbors. If B is a neighbor, done. If not, add neighbors to a queue and keep searching.
* **Refactoring:** We might realize `Connection` needs to be bidirectional or that `Subway` needs a helper method like `hasStation()` to validate inputs before routing.
### Iteration 3: Printing the Route (Separation of Concerns)
* **Goal:** Output the results.
* **Design Principle:** **Single Responsibility Principle (SRP)**.
* The `Subway` class should *calculate* the route (return a List of Connections), but it should *not* print it.
* The `SubwayPrinter` class handles the formatting and printing. This allows us to change the output format (e.g., to HTML or JSON) without touching the core logic.
---
## Phase 4: Testing (Proving It)
We write a `SubwayTester` class to verify the system works in the real world.
* **Happy Path:** Valid Start and End stations -> Returns correct route.
* **Alternate Paths:**
* Station doesn't exist.
* Start and End are the same.
* No route exists (unreachable island).
* **File Loading Test:** What if the file is missing or malformed? (Handled by the Loader).
---
## Key Takeaways from the Lifecycle
1. **Flexibility comes from OOA&D.** Because we separated the *Printer* from the *Logic*, and the *Loader* from the *Network*, we can easily swap out components (e.g., load from a Database instead of a file).
2. **Use existing solutions.** We didn't invent a new routing algorithm; we used standard graph search theory.
3. **Objects should protect themselves.** `Station` protects its identity via `equals()`. `Subway` protects its state by validating inputs.
4. **Iterate.** We didn't write the printer until the network loading worked. We built the system layer by layer.
---
## Chapter Summary (Bullet Points)
* **The OOA&D Lifecycle is circular.** Requirements -> Analysis -> Design -> Implementation -> Testing -> (Repeat).
* **Modules = Sanity.** Breaking a large system into distinct modules (Loader, Model, Printer) makes it manageable.
* **Delegate.** The `Subway` object delegates printing to `SubwayPrinter` and loading to `SubwayLoader`.
* **Protect your users.** Abstract the complexity. The user of your code shouldn't need to know how `Connection` is implemented; they just ask the `Subway` for directions.
* **The "Black Box".** To the outside world (the `SubwayTester`), the system is a black box. You put in station names, and you get out directions. The internal complexity is **encapsulated**.