Problem Decomposition Guide: PhoneBook Lab

Problem Decomposition Guide: PhoneBook Lab

1. Understanding the Real-World Problem

What Is a Phone Book?

Before diving into code, think about physical phone books:

Questions to Consider:

  • How were phone books organized before smartphones?
  • What operations do people perform with phone books?
  • What makes a phone book different from a simple list?
  • Why might you need to search in both directions?

Exercise: List 5 things you do with your phone’s contact list. Which of these would be easy or hard to implement? Why?

2. The Concept of Abstraction

Why Create a PhoneBook Class?

The lab mentions this is your “first meaningful abstraction.” But what does that mean?

Think About It:

  • You could just use a dictionary/HashMap directly. Why create a class?
  • What problems does wrapping the data structure solve?
  • How does this make your code more maintainable?

Real-World Analogy: A car’s steering wheel is an abstraction. You don’t need to know about rack-and-pinion gears or hydraulic systems—you just turn the wheel. Similarly, users of your PhoneBook class shouldn’t need to know if you use a HashMap, TreeMap, or two separate lists internally.

3. Core Functionality Analysis

Essential Operations

1. Adding Entries

add(name, phoneNumber)

Questions to Consider:

  • What if the name already exists?
  • Should you overwrite or reject?
  • Can one person have multiple numbers?
  • What about invalid inputs?

2. Looking Up by Name

lookup(name) → phoneNumber

Questions to Consider:

  • What if the name doesn’t exist?
  • Should lookup be case-sensitive?
  • What about partial matches?
  • How do you handle middle names or nicknames?

3. Reverse Lookup by Number

reverseLookup(phoneNumber) → name

Questions to Consider:

  • What if multiple people share a number?
  • What if the number doesn’t exist?
  • How is this different from regular lookup?

4. Data Structure Decisions

Choosing Your Internal Storage

Option 1: Single Data Structure

  • One HashMap/Dictionary
  • Keys are names, values are numbers
  • Problem: How do you do reverse lookup efficiently?

Option 2: Dual Data Structures

  • Two HashMaps/Dictionaries
  • One for name→number, one for number→name
  • Problem: How do you keep them synchronized?

Option 3: List of Objects

  • Array/List of PhoneBookEntry objects
  • Each entry has name and number
  • Problem: How do you search efficiently?

Exercise: Draw diagrams of each approach. List pros and cons for each.

5. Edge Cases and Design Decisions

Input Validation Scenarios

Names:

  • Empty names?
  • Names with special characters?
  • Very long names?
  • Duplicate names (John Smith vs. John Smith Jr.)?

Phone Numbers:

  • Different formats: (555) 123-4567 vs 555-123-4567 vs 5551234567
  • International numbers?
  • Extensions?
  • Letters in numbers: 1-800-FLOWERS?

Behavior Decisions

When Adding:

  • If name exists: Update? Error? Add second number?
  • If number exists with different name: Allow? Warning?

When Looking Up:

  • Not found: Return null? Empty string? Throw exception?
  • Multiple matches: Return first? All? Error?

Exercise: For each scenario above, decide what YOUR implementation will do and document why.

6. Implementation Planning

Phase 1: Minimal Viable PhoneBook

Goals:
- Store name-number pairs
- Basic add and lookup
- No error handling yet
- Test with 5 entries

Phase 2: Add Reverse Lookup

Goals:
- Implement reverseLookup
- Ensure consistency between lookups
- Handle not-found cases
- Test both directions work

Phase 3: Handle Edge Cases

Goals:
- Add input validation
- Decide on duplicate behavior
- Add error messages
- Test with problematic inputs

Phase 4: Enhance Usability

Goals:
- Case-insensitive search?
- Partial name matching?
- Format phone numbers?
- Multiple numbers per person?

7. Testing Strategy

Unit Test Categories

Basic Functionality:

  • Add entry, then look it up
  • Add entry, then reverse look it up
  • Look up non-existent name
  • Reverse look up non-existent number

Edge Cases:

  • Empty string inputs
  • Very long inputs
  • Special characters
  • Duplicate entries

State Consistency:

  • After adding 10 entries, all lookups work
  • After updating, both lookups reflect change
  • After removing (if implemented), both lookups updated

Test-Driven Thinking

Before implementing each method, write down:

  1. What should happen in the normal case?
  2. What could go wrong?
  3. What should happen in each error case?

8. Design Patterns and Principles

Encapsulation

Your PhoneBook hides HOW it stores data:

  • Users don’t know if you use HashMap, TreeMap, or Arrays
  • Users don’t care about your internal format
  • You can change implementation without breaking user code

Interface Consistency

All methods should behave predictably:

  • Similar methods return similar types
  • Error handling is consistent
  • Naming follows conventions

Single Responsibility

Each method does ONE thing:

  • add() only adds (doesn’t also search or validate)
  • lookup() only retrieves (doesn’t modify)
  • Validation is separate from storage

9. Common Implementation Pitfalls

Pitfall 1: Inconsistent State

Problem: Name→Number works but Number→Name doesn’t Prevention: Always update both directions together

Pitfall 2: Case Sensitivity Confusion

Problem: “John” and “john” treated as different Prevention: Decide on case handling early and be consistent

Pitfall 3: Null/None Handling

Problem: Returning null/None causes errors in caller code Prevention: Document what you return for “not found”

Pitfall 4: Format Assumptions

Problem: Assuming all numbers look like “555-1234” Prevention: Store numbers as strings, not integers

10. Thinking Exercises

Exercise 1: Real-World Complexity

How would you handle:

  • Business entries with multiple locations?
  • People who change their names?
  • Shared family phone numbers?
  • International calling codes?

Exercise 2: Performance Considerations

If your phone book had 1 million entries:

  • Which operations would be slow?
  • How would you optimize lookup?
  • Would reverse lookup be equally fast?
  • What data structure changes might help?

Exercise 3: Feature Extensions

Design (don’t implement) these features:

  • Search by partial name
  • List all entries alphabetically
  • Remove an entry
  • Export to CSV file
  • Merge two phone books

11. Connecting to Larger Concepts

This Lab Teaches:

Data Structure Selection:

  • Choosing the right tool for the job
  • Understanding trade-offs
  • Thinking about performance

API Design:

  • Creating intuitive method names
  • Consistent parameter ordering
  • Clear return value semantics

Software Engineering:

  • Separation of interface from implementation
  • Planning before coding
  • Thinking about user needs

12. The Bigger Picture

Why This Matters

Phone books are simple, but the concepts apply everywhere:

  • Databases: Store and retrieve any data
  • Caches: Fast lookup of computed values
  • User Systems: Username↔UserID mappings
  • DNS: Domain names↔IP addresses

Every major system needs to store and retrieve data efficiently. By mastering this simple abstraction, you’re learning patterns that scale to complex systems.

Final Challenge Questions

Before you start coding, answer these:

  1. Why is this better than just using a raw HashMap/Dictionary?
  2. What would make your PhoneBook class easy for others to use?
  3. How can you design it so you can change the internals later?
  4. What would you put in the documentation?
  5. How is a PhoneBook different from a general-purpose database?

Remember: The goal isn’t just to make it work—it’s to understand WHY each design decision matters and HOW abstraction makes complex systems manageable!