# tut-3 explain code tags: software systems, se time: 2025-12-06 07:40:58 ### **Step 1: The "Before" State (The Dirty Code)** --- ### **Step 2: The Quantitative Check (Metrics)** **Teacher Action:** Ask the class to count with you. * **Formula:** $1 + \text{Decision Points}$ (if, else if, &&, ||). * **The Count:** 1. Base = 1 2. `if (license == null)` (+1) 3. `|| license.isEmpty()` (+1) 4. `if (age < 18)` (+1) 5. `if (type.equals("E-Bike"))` (+1) 6. `if (age < 25)` (+1) 7. `else if (type.equals("Scooter"))` (+1) 8. `if (age < 21)` (+1) 9. `else if (type.equals("StandardBike"))` (+1) * **Total Cyclomatic Complexity:** **9** * **Verdict:** This method is dangerously close to the "double digits" danger zone (Video 58). It requires 9 unique test cases just to cover the paths. --- ### **Step 3: The Qualitative Check (Smells)** 1. **Code Smell 1: Long Method (Bloater)** * *Evidence:* The method validates, calculates price, checks age rules, and formats strings. * *Lecture Reference:* Video 56 ("Longer a procedure, more difficult it is to understand"). 2. **Code Smell 2: Switch Statements (OO Abuser)** * *Evidence:* The chain of `if (type.equals...` * *Lecture Reference:* Video 51/52 (Payment example) & Video 57. This violates the Open-Closed Principle. 3. **Code Smell 3: Long Parameter List / Primitive Obsession** * *Evidence:* Passing `street`, `city`, `zip` individually. * *Lecture Reference:* Video 54 (Missing Abstraction). 4. **Long Method (Bloater):** * This method does Validation AND Pricing AND Formatting. * *Lecture:* "Longer a procedure, more difficult it is to understand." 5. **Primitive Obsession (Bloater):** * `street`, `city`, `zip` passed as loose strings. * *Lecture:* "Missing Abstraction" / Data Clumps. 6. **Switch Statements (OO Abuser):** * Checking `type.equals("E-Bike")` manually. --- ### **Step 4: The Refactoring (The Fix)** **Refactoring 1: Extract Method (Fixing Long Method)** Isolate the pricing logic. **Problem:** The method is doing too much. **Solution:** Extract the pricing logic. *Result:* `processRental` no longer cares *how* price is calculated. ```java // Extracted Method private double calculatePrice(String type, int age, double basePrice) { if (type.equals("E-Bike")) { return (basePrice * 1.1) + (age < 25 ? 5.0 : 0); } // ... rest of logic return basePrice; } ``` **Refactoring 2: Introduce Parameter Object (Fixing Primitive Obsession)** Create a class for Address (Video 54). **Problem:** Feature Envy. `RentalService` is formatting addresses. **Solution:** Create a `CustomerAddress` class. *Result:* `processRental` signature becomes cleaner: `processRental(String type, int age, CustomerAddress addr...)` ```java // New Abstraction public class CustomerAddress { private String street; private String city; private String zip; // Logic moved here (Fixing Feature Envy) public String getFormattedLabel() { return street + "\n" + city + ", " + zip; } } ``` **Refactoring 3: The Resulting Clean Code** **New Complexity Score:** **2** (Base + 1 if check). **Readability:** High. ```java public class RentalService { // Complexity dropped to 2 (Base + 1 validation check) public String processRental(String type, int age, String license, CustomerAddress addr, double basePrice) { if (!isValidDriver(license, age, type)) { return "Error: Validation Failed"; } double price = calculatePrice(type, age, basePrice); // Delegating address formatting to the Address object return "CONFIRMED\n" + addr.getFormattedLabel() + "\nPrice: " + price; } } ``` --- # Summary of the Process This is exactly what you will do in the **Refactor Studio** assignment: 1. **Scan** the code. 2. **Calculate** the Complexity (Before). 3. **Identify** the Smells (using lecture terms). 4. **Refactor** (Extract methods, Create classes). 5. **Calculate** the Complexity (After) to prove success.