Course Overview
Object-Oriented Software Design focuses on building understandable, maintainable, extensible, and testable software systems using object-oriented analysis and design principles. The course treats software development as a communication-intensive engineering process: requirements, analysis artifacts, design artifacts, code, tests, and demos must remain consistent with one another.
The course is intentionally project-heavy. Students learn to transform requirements into use cases, domain models, system sequence diagrams, design class diagrams, design sequence diagrams, and working code. Recent offerings emphasize iterative development, Java and Python implementations, unit testing, logging, exception handling, GitHub-based collaboration, and design quality over unnecessary feature expansion.
Learning Outcomes
Requirements and Analysis
- Explain software development as an iterative and evolutionary process.
- Prepare requirement-analysis artifacts such as problem statements, scope definitions, glossaries, use cases, domain models, and system sequence diagrams.
- Separate real-world domain concepts from software design concepts in analysis artifacts.
UML and Design Artifacts
- Create UML class diagrams and sequence diagrams with correct attributes, methods, parameters, return types, messages, loops, and lifelines.
- Maintain traceability from requirements to analysis, from analysis to design, and from design to code.
- Explain why a design class diagram and a domain model are different artifacts with different purposes.
Object-Oriented Design Quality
- Apply encapsulation, low coupling, high cohesion, information expert, controller, polymorphism, dependency inversion, and open/closed design decisions.
- Use interfaces, abstract classes, composition, inheritance, and design patterns purposefully rather than mechanically.
- Justify design decisions using principles such as KISS, YAGNI, SOLID, GRASP, and “program to an interface, not an implementation.”
Implementation and Team Practice
- Implement a running system whose code matches its analysis and design documents.
- Use GitHub repositories, meaningful commits, clear folder organization, and reproducible demos.
- Write unit tests, use exception handling and logging, and preserve project history across iterations.
Textbooks and Core References
Recent offerings use instructor slides, project handouts, and selected textbook chapters. The two main textbook references are:
- Craig Larman. Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development, 3rd edition.
- Martin Fowler. UML Distilled: A Brief Guide to the Standard Object Modeling Language, 3rd edition.
Selected topics also draw on general object-oriented design principles, SOLID, GRASP, GoF design patterns, Python type hints, testing practices, and microservices architecture.
Core Topic Map
The exact order may vary by semester, but recent offerings cover the following themes.
1. Software Development as a Design Problem
Large software projects, complexity, communication problems, maintainability, understandability, iterative development, KISS, YAGNI, premature optimization, and why code is written for humans as well as computers.
2. Software Lifecycles and Unified Process
Lifecycle models, iterative and incremental development, Unified Process phases, inception, requirements discovery, risk-driven planning, and why projects should not attempt to implement all requirements in a single step.
3. Requirement Analysis
Vision, scope, problem statement, glossary, functional and non-functional requirements, IEEE-style software requirements thinking, stakeholder concerns, and early domain understanding.
4. Use Cases, Domain Models, and SSDs
Actors, goals, main success scenarios, alternative flows, domain model concepts, attributes without software implementation details, associations, system-as-black-box thinking, and system sequence diagrams.
5. UML Class and Sequence Diagrams
UML notation, class diagrams, sequence diagrams, lifelines, messages, loops, method signatures, attributes, parameter types, return types, and diagram-code consistency.
6. Object Design and GRASP
Information Expert, Creator, Controller, Low Coupling, High Cohesion, Polymorphism, Pure Fabrication, Indirection, Protected Variations, and responsibility assignment.
7. SOLID and Core OO Principles
Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, Dependency Inversion, encapsulation, composition over inheritance, and program-to-interface design.
8. GoF Design Patterns
Pattern motivation, applying patterns when they solve a real design problem, Strategy-like polymorphism, dependency inversion through abstractions, and avoiding pattern overuse.
9. Java and Python Implementation
Object-oriented Java implementation, porting to Python, type hints, interfaces/abstract classes as appropriate, Python object-oriented design, functional programming, NumPy, Pandas, and clean module organization.
10. Testing, Logging, Exceptions, and Architecture
Unit testing, test coverage, exception handling, logging, separation of UI from business logic, configuration files, reproducible command-line execution, and microservices architecture in light of OO principles and design patterns.
Recurring Materials and Reading Structure
Analysis and Modeling
- Software lifecycles and Unified Process phases
- Requirement analysis
- Use cases
- Domain models
- System sequence diagrams
- UML class diagrams and sequence diagrams
Design and Implementation
- Review of object orientation
- Modeling with classes
- Modeling interactions and behavior
- GRASP responsibility assignment
- GoF design patterns
- Visibility, encapsulation, unit testing, logging, and exceptions
Python and Tooling
- Python language review
- Python object-oriented programming
- Type hints
- Functional programming
- NumPy and Pandas
- Testing and project organization
Architecture Extensions
- Microservices architectures
- Extensibility and plug-in architecture
- Policy routing and caching concepts in recent RAG-oriented projects
- Evaluation harnesses and reproducible experiment output
Recent Term Project Style
The course project changes by semester, but its purpose is stable: students must demonstrate object-oriented analysis, design, implementation, testing, and iterative improvement. Recent offerings used a Mini RAG University Helpdesk project, while earlier offerings used Java/Python simulations and other domain systems. The implementation may be intentionally simple; the design quality must not be simple-minded.
Example Recent Project: Mini RAG University Helpdesk
Students build a command-line helpdesk system that answers questions over a small university-helpdesk knowledge base stored in YAML/JSON files. The project is used to practice requirements analysis, domain modeling, UML design, extensibility, testing, and code-document consistency.
Iteration 1: Simple Java System
A keyword-based implementation is sufficient. No chunking, embedding model, vector index, or complex retrieval pipeline is required. Students focus on analysis artifacts, domain design, UML quality, simple working scenarios, encapsulation, SRP, OCP, DIP, low coupling, high cohesion, and meaningful polymorphism where appropriate.
Transition: Java to Python Port
Students port the first iteration implementation to Python without changing the functionality first. Variables, function parameters, and return values should use type hints. Separate directories or clearly separated versions are recommended so project evolution remains visible.
Iteration 2: Extensibility and Evaluation
The project adds more extensible components such as an intent detector, query writer or decomposer, multiple rerankers, a RAG orchestrator or pipeline, query cache, batch CLI, and evaluation harness. Students report coverage@k, simple accuracy, latency, and design changes across iterations.
Expected Project Artifacts
Project evaluation focuses on whether the artifacts are technically correct, mutually consistent, and visibly improved across iterations.
Requirements and Analysis
- RAD or requirement-analysis document
- Vision, problem statement, scope, and glossary
- Use cases with meaningful actors and system responses
- Domain model showing real-world concepts only
- System sequence diagrams that treat the system as a black box
Design
- Design class diagram with complete attribute and method type information
- Design sequence diagrams with messages, parameters, return types, loops, and lifelines
- Clear traceability from analysis artifacts to design artifacts
- Design changes clearly highlighted in later iterations
Implementation
- Running code that matches the design documents
- Encapsulated classes with meaningful responsibilities
- Separated UI, business logic, and persistence/configuration concerns
- Meaningful inheritance and polymorphism when justified
Quality and Collaboration
- Unit tests and test coverage expectations
- Exception handling and logging
- GitHub commits from all group members
- Demo readiness, reproducibility, and ability to answer design/code questions
Design Rules Emphasized in the Course
Encapsulation is Not Just Private Fields
Classes should not become passive data holders. Domain classes should own data-related responsibilities and process their own data where appropriate. Uncontrolled getters and setters can still break encapsulation.
Design Must Match Code
DCD and DSD artifacts must correspond to the implementation. Significant differences between diagrams and code are treated as design failures, not merely documentation problems.
Polymorphism Must Be Meaningful
Polymorphism should be implemented through interfaces or abstract classes with different concrete behavior. Type checking and casting are not accepted as a substitute for polymorphic design.
Favor Simplicity and Justification
Students are expected to avoid unnecessary functionality and unnecessary complexity. Every inheritance relationship, design pattern, abstraction, and module should solve a real problem in the project.
Assessment Patterns
Exact weights vary by semester. Recent offerings use quizzes, exams, and a substantial project with iteration demos. Project grading usually considers the quality of analysis artifacts, design artifacts, code, tests, GitHub collaboration, iteration-to-iteration improvement, and the ability of all team members to explain the system.
Exams and quizzes may include conceptual questions, UML interpretation, artifact correction, design-principle application, and diagram construction. Students are expected to prepare from the textbooks, not only from slides.
Study Questions
The following questions summarize the kind of understanding expected from students and may help readers understand the depth of the course.
Software Process, Requirements, and Analysis
- Why is software development described as a communication problem as much as a coding problem?
- Explain why large software systems should be designed for understandability and maintainability rather than only for short code or local optimization.
- What is the difference between iterative development and trying to implement all requirements in one large phase?
- Define KISS and YAGNI. Give an example of a project feature that violates YAGNI.
- What information should appear in a problem statement, scope section, and glossary of a requirement-analysis document?
- What is a use case? How is a use case different from a list of user-interface screens?
- Identify actors and system responsibilities for a university-helpdesk question-answering system.
- Why should a domain model contain real-world concepts rather than software classes such as controllers, repositories, or database managers?
- What is the difference between a domain model and a design class diagram?
- What is a system sequence diagram? Why should it treat the system as a black box?
UML, Class Diagrams, and Sequence Diagrams
- Given a set of requirements, identify candidate domain classes and associations.
- Draw a domain model for a course-registration simulation without including implementation-level software objects.
- Draw a design class diagram for a simple helpdesk system with classes such as KnowledgeBase, QueryProcessor, Retriever, Reranker, and AnswerGenerator.
- Why must all attribute types, method parameter types, and return types be shown in design artifacts?
- What is the difference between an attribute in a class diagram and a local variable inside a method?
- In a sequence diagram, how do you decide which object should receive a particular message?
- Why is it wrong for a design sequence diagram to show a message being sent to an object that does not define the corresponding method?
- Explain the role of lifelines, activation boxes, loops, and return messages in a design sequence diagram.
- How would you show a batch query-processing operation in a sequence diagram?
- How can teams make iteration-to-iteration changes visible in UML documents?
Encapsulation, Coupling, Cohesion, and SOLID
- Why is a class with only private fields and public getters/setters not necessarily well encapsulated?
- Give an example of moving responsibility from an external controller into the class that owns the relevant data.
- Explain Single Responsibility Principle with an example from a query-answering system.
- Explain Open/Closed Principle. How can a system add a new reranking strategy without modifying existing retrieval code?
- Explain Liskov Substitution Principle using a base interface and two concrete implementations.
- Explain Interface Segregation Principle. Why are large “god interfaces” problematic?
- Explain Dependency Inversion Principle. Why should high-level modules depend on abstractions?
- What is low coupling? Give an example of reducing coupling in a design.
- What is high cohesion? Give an example of a class whose responsibilities are not cohesive.
- Why should UI logic be separated from business-domain classes?
GRASP and Design Patterns
- What is the Information Expert pattern? Apply it to a course-registration or helpdesk example.
- What is the Controller pattern? How is a controller different from a domain object?
- How do Low Coupling and High Cohesion sometimes create trade-offs in responsibility assignment?
- Explain Protected Variations. How can it help when different retrieval or reranking algorithms may be added later?
- Explain Pure Fabrication. When is it acceptable to introduce a software class that is not a domain concept?
- Explain Strategy pattern using a Reranker interface and two implementations.
- How can Factory or Creator-like decisions improve object creation responsibility?
- Why is using a design pattern without a real design problem harmful?
- What is the difference between inheritance for reuse and inheritance for substitutable behavior?
- Why is composition often preferred over inheritance?
Project Implementation, Testing, and GitHub
- What should a GitHub repository contain for a reproducible course project?
- Why should each iteration be preserved rather than overwritten?
- What is a meaningful commit? Why are very large last-minute commits weak evidence of contribution?
- Write a simple testing plan for a keyword-based helpdesk system.
- What unit tests would you write for a Retriever class?
- What unit tests would you write for an IntentDetector class?
- Why is 80% method coverage useful but not sufficient to prove software quality?
- Give examples of exceptions that should be handled in a command-line JSON/YAML based project.
- What should be logged in a system that answers helpdesk questions?
- How can a config file improve demo quality and reproducibility?
Python Porting, Type Hints, and Architecture
- What are Python type hints, and why are they useful in a team software-design project?
- How can Java interfaces or abstract classes be represented in Python?
- What should remain unchanged when porting a first-iteration Java project to Python?
- Why should the port be completed before adding new functionality?
- What is the difference between a module, class, and package in a Python project structure?
- How can functional programming be useful without destroying object-oriented structure?
- When would Pandas be appropriate in an OOSD project, and when would it be unnecessary?
- What is a microservice? How does microservice decomposition relate to coupling and cohesion?
- What design problems can occur if a small project imitates microservices too early?
- How do testing, logging, and exception handling change when a system is decomposed into services?
Exam-Style Design Tasks
- Given a short requirement text, write one use case with actor, precondition, main success scenario, and alternative flows.
- Given the same requirement text, draw a domain model and clearly exclude software implementation classes.
- Transform one use case into an SSD with exactly an actor lifeline and a system lifeline.
- Create a DCD for the same scenario and include attributes, methods, parameter types, and return types.
- Create a DSD for one operation and ensure every message corresponds to a method in the receiving class.
- Identify three violations of encapsulation in a sample class and rewrite the design to fix them.
- Given a design with a large controller class, redistribute responsibilities using GRASP.
- Given two similar algorithms implemented with if/else blocks, refactor the design using polymorphism.
- Given two project iterations, list how RAD, DCD, DSD, code, and tests should be updated and highlighted.
- Explain how a simple keyword-based system can evolve into an extensible retrieval pipeline without violating OCP and DIP.