Ch 05: Good Design = Flexible Software
Source: Head First Object-Oriented Analysis & Design | Pages: 232-313
🎯 Learning Objectives
Master object-oriented analysis and design principles for building flexible, maintainable software.
📚 Key Concepts
Encapsulation
Code reuse
Delegation
Composition vs Inheritance
Design patterns intro
📖 Detailed Notes
This chapter focuses on practical OOA&D principles and techniques for real-world software development.
1. Encapsulation
Essential for mastering object-oriented analysis and design.
Key Principles:
Focus on creating flexible, maintainable software
Apply OO thinking to real-world problems
Use proper analysis before implementation
2. Code reuse
Essential for mastering object-oriented analysis and design.
Key Principles:
Focus on creating flexible, maintainable software
Apply OO thinking to real-world problems
Use proper analysis before implementation
3. Delegation
Essential for mastering object-oriented analysis and design.
Key Principles:
Focus on creating flexible, maintainable software
Apply OO thinking to real-world problems
Use proper analysis before implementation
4. Composition vs Inheritance
Essential for mastering object-oriented analysis and design.
Key Principles:
Focus on creating flexible, maintainable software
Apply OO thinking to real-world problems
Use proper analysis before implementation
5. Design patterns intro
Essential for mastering object-oriented analysis and design.
Key Principles:
Focus on creating flexible, maintainable software
Apply OO thinking to real-world problems
Use proper analysis before implementation
💡 Three Key Takeaways
Encapsulation - Core principle for this chapter
Code reuse - Applying concepts in practice
Delegation - Industry standards and approaches
✅ Self-Check Questions
What are the main OOA&D concepts covered in this chapter?
How do these principles improve software design?
Can you apply these concepts to a real project?
What are the trade-offs of different design approaches?
🔄 Quick Revision Checklist
📝 Practice Exercises
Apply the chapter concepts to your current project
Create diagrams and models using the techniques learned
Review existing code and identify improvement opportunities
Discuss design decisions with your team
🔗 Related Topics
Software architecture patterns
Design principles and best practices
UML diagrams and modeling
Agile development practices
For complete details, case studies, and examples, refer to Head First OOA&D, pages 232-313.
Chapter 5: Nothing Ever Stays the Same
"Good Design = Flexible Software"
Overview
This chapter marks a transition from analysis back to design. It revisits the "Rick's Guitars" application from Chapter 1. The business is expanding to sell Mandolins (and eventually Banjos), but the current design is rigid. The chapter focuses on using Abstract Classes, Interfaces, and UML to create a flexible application that can handle change without breaking.
Case Study: Rick's Guitars (Expansion)
1. The Problem: Adding Mandolins
Rick decides to start selling Mandolins.
The Quick Fix (Bad Design): Copy the
Guitarcode, rename itMandolin, and add it to the system.Why it fails:
Duplicate Code:
GuitarandMandolinshare fields likeprice,serialNumber, andbuilder. If you fix a bug in one, you have to remember to fix it in the other.Maintenance Nightmare: The
Inventoryclass now needs separate lists for guitars and mandolins, and separate search methods (search(GuitarSpec)vssearch(MandolinSpec)).
2. The Solution: Abstraction
To solve the duplicate code problem, we lift common behavior and attributes into a parent class.
Abstract Base Class (
Instrument):Created to hold shared properties:
serialNumber,price,InstrumentSpec.Why Abstract? You never have just an "Instrument" in the store; it's always a specific type (Guitar, Mandolin). Therefore,
Instrumentshould not be instantiated directly.
Abstract Base Class (
InstrumentSpec):Created to hold shared spec properties:
builder,model,type,backWood,topWood.
3. The Design Flaw: Rigid Subclasses
Even with the Instrument class, the design is still brittle.
Scenario: Rick wants to sell Banjos.
Problem: Banjos don't have a "back wood" or "top wood" in the same way guitars do. If we force
Banjoto inherit fromInstrumentSpec, we might inherit properties that don't make sense.The "Ripple Effect": Every time a new instrument type is added, we have to create new subclasses and potentially modify the
Inventorysearch logic.
Key Concepts & Principles
1. Abstract Classes vs. Interfaces
Abstract Class: Use when you have shared code (behavior/state) that subclasses should inherit.
Example:
Instrument(all instruments have a price and serial number).
Interface: Use when you have shared roles or capabilities that valid classes must fulfill, but they don't share implementation code.
Concept: Defines what a class can do, not how it does it.
2. Encapsulate What Varies (Revisited)
The properties of instruments vary wildly (Guitars have strings, Banjos have heads, Drums have skins). Hardcoding these into the class structure (e.g., getNumStrings()) is bad design.
Dynamic Properties: Instead of hardcoded fields, use a flexible data structure like a
Map(Dictionary) to store properties.Implementation:
Map properties = new HashMap();Benefit: You can add "numStrings" for a Guitar and "skinType" for a Drum without changing the
InstrumentSpecclass code.
3. Cohesion & Single Responsibility
Cohesion: A measure of how closely related the functionality of a class is.
High Cohesion: The class does one thing well (e.g.,
InstrumentSpeconly stores instrument specifications).Low Cohesion: The class tries to do everything (e.g.,
Inventorystoring items, searching, and managing sales).
Single Responsibility Principle: Every class should have only one reason to change.
The "Search" Refactoring
The most critical improvement in this chapter is the generic search method.
Before (Rigid):
Last updated