Skip to main content
Object Oriented Design, Analysis and Programming

Designing Object Systems with GRASP and Interaction Diagrams

Published: 2026-08-19
Level: postgraduate
Audience: Postgraduate students in Object Oriented Design, Analysis and Programming

Prerequisite Knowledge

This lecture builds on the following concepts from earlier lectures. If any feel unfamiliar, review the linked notes before proceeding.

Previously Covered in This Subject

  • 1.3 Analysis versus Design — covered in Lecture 1: Object-Oriented Analysis and Design
  • 1.3.2 The scope: analysis and design are for big software — covered in Lecture 1: Object-Oriented Analysis and Design
  • 2.1.3 Exam Notes — covered in Lecture 2: Object-Oriented Analysis and Design
  • 2.3 The OOAD Roadmap: Requirements, Analysis, Design, and Implementation — covered in Lecture 2: Object-Oriented Analysis and Design
  • 3.2 The Analysis, Design, and Implementation Pipeline — covered in Lecture 3: Object-Oriented Analysis and Design: Objects, Models, and the Software Process
  • 3.5.2 Messages Become Methods — covered in Lecture 3: Object-Oriented Analysis and Design: Objects, Models, and the Software Process
  • 4.2.4 Analysis Paralysis and Endless Design — covered in Lecture 4: Unified Process Model and UML
  • 4.4.3 Worked Example: The Die — covered in Lecture 4: Unified Process Model and UML
  • 5.4.3 Worked Example: Hospital Drug Information System — covered in Lecture 5: Requirements Engineering and Use Case Modeling
  • 5.4.4 Worked Example: Exception Handling in a Cash Payment System — covered in Lecture 5: Requirements Engineering and Use Case Modeling
  • 6.7.2 The Use Case View and Diagram Notation — covered in Lecture 6: Use Case Modeling and Analysis
  • 7.3 System Sequence Diagrams — Events and Operations at the System Boundary — covered in Lecture 7: System Sequence Diagrams, Activity Diagrams and UML Foundations
  • 7.3.1 Purpose and Why It Is Not the Same as a Sequence Diagram — covered in Lecture 7: System Sequence Diagrams, Activity Diagrams and UML Foundations
  • 8.1.2 Analysis, Design and Programming Share One Vocabulary — covered in Lecture 8: Object-Oriented Analysis and the Domain Model
  • 9.1.3 Student Questions and Answers — covered in Lecture 9: Object Oriented Design with UML Interaction Models
  • 9.1.4 Industry Applications — covered in Lecture 9: Object Oriented Design with UML Interaction Models

# Designing Object Systems with GRASP and Interaction Diagrams

10.1 From Analysis to Design and Responsibility-Driven Design

10.1.1 Concept Overview

Hook: How do you move from a picture of the world — customers, products, sales — to working classes and methods without guessing where each method belongs? The answer is not more diagrams alone, but a disciplined way to assign who does what and to justify that choice so any teammate can check it.

Object design builds on what analysis has already produced, but it is not a copy. Requirements, both functional and non-functional, set the boundary of what must be fulfilled. Analysis objects act as a framework that inspires the design rather than dictates it. Real-world objects identified during analysis — Sale, Product, Customer, Register — become software or logical objects, which are then turned into classes and programmed as actual runtime objects. Design operates at two levels at once: the high-level overall architecture (layers, subsystems, packages) and the inner working of how objects collaborate moment by moment to make a use case happen.

An object-oriented solution is therefore best understood as a collaboration of objects that carry responsibilities and capabilities to perform tasks together. The design job is to take objects already named in analysis, add responsibilities in the form of methods, and describe the result with UML diagrams that let us think and communicate before coding. Doing this well depends on accumulated experience from more than thirty to forty years of software design: rules, principles, idioms, and common ways of judging a decision without solving every problem from scratch. The aim is to reuse solutions — not to invent a new clever arrangement for a problem that has been solved a hundred times before.

A pattern is a collection that pairs a general problem with a general solution. More precisely, a pattern names a recurring problem in a context, a solution structure, and guidance on trade-offs and variations when adapting it. Design patterns document such problem and solution combinations. They are general and need adaptation to a specific context; a dress pattern for a sari is not sewn exactly like one for jeans, yet the pattern tells you what pieces exist and how they relate. Learning good designs also benefits from reverse engineering existing programs, tracing why a working design took a particular decision rather than just admiring that it works. Design remains a creative process often described as an art, yet it is learned by applying standard rules, design guidelines, and principles until the principles become instinct.

Intuition — the gardener and the architect: Think of an office where every task arrives as a letter. If the letter is about gardening, you hand it to the gardener, because that person holds the skill and the tools. If it is about accounting, you hand it to the accountant. Responsibilities flow to the information-and-skill holder, not to a random willing person. That is the everyday logic behind Responsibility-Driven Design. Now pair it with a second picture: an architect who sketches a building from a site survey. The survey inspires the blueprint, but the blueprint adds walls, wiring, and plumbing that the survey never contained. Analysis is the survey; design is the blueprint that adds responsibilities.

Where the analogy breaks: In a human office, a skilled person might refuse the task or be overloaded; in software, an object that receives a message is contractually obligated to perform it. Also, human experts can improvise without data access; software experts cannot act without visibility to the data they need.

10.1.2 The Core Principle of Responsibility Assignment

Responsibility-Driven Design (RDD) in one statement: A responsibility is a contract or obligation of an object — either knowing (what it knows or can derive) or doing (what it does or coordinates). RDD designs a system as a community of collaborating responsible objects by (1) identifying candidate objects (from the domain model and new design needs), (2) assigning each responsibility to the object that can fulfill it with the information it already holds, and (3) justifying every assignment with a named principle or pattern so the decision can be communicated and checked.

The golden rule is deliberately simple: whoever holds more of the information needed for the job should do the job. We ignore personal interest and focus on functional capability and data possession. This pushes behavior and data to the same place — the expert already has the data, so asking it to also carry the behavior keeps coupling low and cohesion high. A common way to state this is the Do It Myself or Animation idea: in the real world a sale is inanimate, but in software we animate it — we give the Sale object the ability to compute its own total because it already knows its line items.

Real-world grounding was built step by step in the lecture. An election illustrates the idea concretely. An election as an event is managed by a state administration. An election booth needs several distinct roles: managing the queue, validating identity against a list, marking voters with ink, and a polling officer coordinating the whole station. No single person does everything; work is distributed by competence and access to the right information (the queue manager sees the line, the validator holds the register). The same reasoning transfers directly to software: map the roles to objects and assign each object the responsibility it is best equipped to hold. If we were to computerize the booth, the Queue object manages ordering, the Registry object validates identity, and the PollingOfficer object coordinates — because each holds the relevant data.

A complementary everyday phrasing of the same rule is to keep data and the behavior that needs that data together, so lightweight classes collaborate to meet a responsibility rather than one bloated class carrying everything. Collaboration is therefore not a workaround; it is the intended outcome of correct assignment.

Visual intuition — what the design evolution looks like: Imagine a two-panel figure. The left panel shows Analysis: a domain model with boxes for Sale, SalesLineItem, ProductSpecification connected by associations, with attributes like time and quantity written inside. No methods are shown yet. The right panel shows Design: the same boxes now have method compartments added — getTotal(), getSubtotal(), getPrice() — and lifelines with arrows between them indicating messages. An arrow labeled "inspires" goes from left to right, not "copies", to emphasize that methods are added and collaborations are decided. The takeaway in one sentence: analysis tells you what exists; design decides who does what and how they talk.

Scope: RDD and the golden rule apply when you have a domain model or use-case narrative to start from and when objects will collaborate via messages. They assume you are working in an object-oriented language where behavior lives in classes. Assumption: The analysis objects are a reasonable approximation of the domain; if the domain model is missing a key concept, you must first discover that concept — RDD cannot invent domain knowledge you have not captured. When it breaks: If you copy analysis attributes blindly into software without asking who needs what data to act, you get anemic objects (data holders with no behavior) and a procedural script manipulating them. If you assign responsibilities by intuition alone without a justifying principle, two designers will assign the same job to two different classes and have no way to argue which is better.

Pitfall — "Design is just drawing sequence diagrams": Beginners equate design with producing a UML diagram. The diagram is a thinking tool, not the goal. The real design work is the decision hidden behind each arrow — why does this object send this message to that object? If you cannot state the reason in terms of information possession or a named pattern, the diagram is decoration. Always ask: does the receiver already hold the needed data?

Pitfall — "Analysis object = design class one-to-one": Not every conceptual class becomes a software class, and software classes appear that have no real-world counterpart (e.g., a handler or factory). Treat the domain model as inspiration with low representational gap, not as a mandate.

Pitfall — "One expert does everything": Giving one object many unrelated responsibilities because it happens to have one piece of data creates low cohesion and high coupling. Expertise is about the right information for a specific responsibility, not about being generally knowledgeable.

10.1.3 Communicating Design Decisions Through Patterns

Design decisions should be explainable to another developer without retelling the whole story. Just as a step in mathematics is justified by citing a theorem, a design step is justified by citing a pattern or principle. Saying that a decision follows Information Expert or Creator is like citing Pythagoras theorem: the name carries a whole set of intent, structure, and trade-off, so a single sentence can replace a paragraph of hand-waving.

That makes patterns a communication tool among developers and architects. Chunking ideas under names also helps memory, so a name can bring the full picture to mind when you later recall it. The lecture drew the parallel explicitly:

A pattern name carries whole intent as Pythagoras theorem carries a whole proof. Hearing the name, you reconstruct the triangle, the squares, the relationship.

When we choose a solution there are always trade-offs, with pros and cons. A pattern advises how a solution applies in varying circumstances and what forces are at play. There is no single beautiful or ugly design in the abstract; the quality comes from how well dependencies and responsibilities are balanced. Human factors that allow work to continue in the real world despite imbalance — people compensating, improvising — cannot be relied on in software, so the design must aim for low dependence among objects and a fair distribution of work where each object does its part and acts as an expert for its job.

In GRASP terminology, many of these guidelines are presented as patterns even when strictly they are principles or advices. Larman uses the pattern form deliberately as a learning aid: naming, structuring, and remembering classic assignment reasoning so that instead of saying "it felt right," you can say "assigned by Expert because this class already aggregates the needed data, which also supports Low Coupling."

10.1.4 Student Questions and Answers

Q: We were asked to think about an election booth and say who does what. What are the different people there and what do they do?

A: Responses named queue management, identity validation, assignment of the voting marker, and a polling officer to coordinate. The point was transferred to software: to computerize or automate the same process, picture the roles as objects — QueueManager, IdentityRegistry, MarkingOfficer, PollingOfficer — and assign each object the responsibility for which it holds the information and capability. The queue manager sees the line, the registry holds the voter list, the marking officer holds the ink and procedure. The pattern is general: give the job to the skill-and-information holder. This is the very origin of the Expert intuition that reappears in the formal GRASP principles later in the lecture.

10.1.5 Industry Applications

Election booth organization shows how to map physical roles and responsibilities to object assignments and how the expert rule operates outside software — a technique still used in domain-driven design workshops where stakeholders role-play processes to discover candidate objects. Viewing many existing designs and applying reverse engineering to see why a working program is organized a certain way is presented as a practical learning method. Teams that inherit a codebase often reconstruct the interaction diagrams from code to uncover the original responsibility decisions before changing them.

10.1.6 Exam Notes

Exam note: Be ready to explain any assignment of a responsibility with a reason, not by appeal to intuition alone; cite the guideline or pattern that justifies the decision — for example, "Sale gets getTotal() by Information Expert because Sale aggregates SalesLineItem data, which also keeps coupling low." Practice stating both the assignment and the justification in one sentence.

Recap + Bridge: Analysis discovers what exists; Responsibility-Driven Design decides who does what by giving each job to the information holder and justifying the choice with a named principle so the team can reason together. This foundation explains why the next step — capturing collaborations as messages in interaction diagrams — directly reveals the methods each class must provide. → Next, we turn messages into methods via sequence and collaboration diagrams.

10.2 Interaction Diagrams and Messages as the Path to Methods

10.2.1 Concept Overview

Hook: If a use case says "the cashier ends the sale," which class actually learns a new method? Interaction diagrams answer that in one step: follow the arrows, and every arrow becomes a method.

For each system event or scenario within a use case we identify all participating objects and see how messages pass among them. Message passing leads directly to methods that will be added to class descriptions. A message is a request from one object to another for help, behavior, or expected action. If object A sends a message to object B, then B must have the capability and therefore a method to serve it. The message identifies the target object, whether communication is synchronous or asynchronous, the message name kept as abstract as possible, and the parameters. Whoever possesses the needed data supplies it as a parameter.

Interaction diagrams capture this dynamic view. Both sequence diagrams and communication (collaboration) diagrams are used. System events described in a system sequence diagram (SSD), such as seminar details entry or pressing an end-of-sale button, correspond to single operations that are then expanded into finer-grained interactions among domain objects. A sequence diagram or a collaboration diagram is drawn per scenario or per system event. The two forms are semantically equivalent — the same messages among the same objects — so a team can start with whichever is easier to sketch on a wall.

Intuition — the office memo chain: Think of a system event as a memo that lands on the front desk (the UI). The front desk does not act; it forwards the memo to the first responsible office (the Controller), which then sends internal memos to specialists: one to verify, one to look up data, one to create a record. Each memo is a message; each office that receives one must know how to handle that memo type — that is its method. The sequence from top to bottom in the diagram is the memo chain in time.

Where it breaks: In an office a memo can be ignored; in software a message without a matching method is a compile or runtime error. Also, office memos are informal; UML messages have precise syntax including name, parameters, and return.

10.2.2 Notation, Numbering, and Diagram Organization

Core notation and what each choice means:

Synchronous vs asynchronous: A synchronous message is shown with a filled arrowhead — the sender waits (blocks) until the receiver returns, like a phone call. An asynchronous message uses an open (stick) arrowhead — the sender continues without waiting, like dropping a letter in a mailbox. This distinction matters for multi-threaded environments where you need to know who blocks.

Collaboration (communication) diagram numbering: Sequence numbers on links show order and nesting. 1: is the first message, 1.1: is a nested call inside 1:, 2: follows 1:. Special forms: mutual exclusion is shown as 1a: and 1b: (only one of the alternatives executes, governed by a guard such as [code valid]); parallel execution uses parallel frames or par combined fragments; iteration or looping uses * or loop with a guard like [i = 1..n] or * [for each lineItem].

Sequence diagram frames: UML 2 frames structure control flow: opt for optional, alt for mutually exclusive alternatives, loop for repetition, par for parallel, ref for reference to another diagram. A message expression generally follows return := message(parameter : type) : returnType, where type information can be omitted when obvious (e.g., d = getProductDescription(id)).

Legal numbering rule: Use a consistent, readable numbering scheme so a reader can follow the flow without hunting. The simplest guide is: do not number the starting message into the diagram, then number each outgoing message sequentially with nesting encoded by dots.

The fundamental rule across both diagram types is to keep messages simple and the diagram uncluttered so that what is going on remains understandable and the collaboration diagram can be converted to a sequence diagram directly without loss.

Large use cases that become too complex should be broken into multiple diagrams. A reference frame (often labeled ref), shown as a box that refers to another diagram, connects them. This ref notation is part of the Larman textbook conventions for linking diagrams and allows a main diagram to stay readable while detail lives in a referenced sub-diagram. Conditions, loops, and parallel fragments all have standard forms and should be learned for both diagram types so you can read any team's sketch.

The same system can be shown either way: the information is semantically equal in sequence and collaboration forms, so either diagram type can be used to create the design. Practical advice given in the lecture is to include the collaboration sequence numbers even when you sketch a sequence, to keep clarity because no single modeling view is ever complete. Also, keep message names abstract — createRegistration(...) rather than callCreateRegistrationSQL() — so the diagram stays at design level, not code level.

Visual intuition — what the two views emphasise: Imagine two figures side by side showing the same three-object interaction (UI → Controller → Domain). The left figure is a sequence diagram: vertical lifelines for each object, time flows downward, horizontal arrows carry messages verifyCode() then getSchedule(). The right figure is a communication diagram: the same three boxes placed as a triangle, numbered arrows 1: verifyCode() and 2: getSchedule() looping along links. The x-axis in the sequence view is objects, the y-axis is time; the x-axis in the communication view is space (layout freedom) and the numbers encode time. The takeaway: sequence shows time explicitly, communication shows topology compactly — choose by what you need to emphasise.

Scope — when this notation applies: Use synchronous filled arrows as the default for ordinary method calls within a single thread. Use asynchronous open arrows only when you explicitly intend concurrency — for example, Thread.start() or a message queue. Use alt/opt/loop frames when the scenario indicates a condition such as "if valid" or an iteration such as "for each"; otherwise linear numbering suffices. Assumption: Objects have been identified before diagramming — you have an SSD or use-case step that names the system event you are expanding. If you lack participant objects, step back to the domain model before drawing arrows.

Pitfall — cluttered diagram that tries to show everything: Beginners pack every conditional branch and error path onto one diagram until it is unreadable. The professor explicitly warns this as a failure mode. Instead, use a ref frame to factor out a sub-interaction and keep each diagram focused on one happy-path scenario plus at most one alternate. A cluttered diagram is a signal to split.

Pitfall — numbering that hides the flow: Random numbers like 3:, 1:, 2.1: out of order force the reader to hunt. Follow legal numbering consistently. Also, do not invent a new sequence number for a reply; show replies as return := message() or as a dashed return arrow, not as a new numbered forward message.

Pitfall — confusing synchronous vs asynchronous by arrow shape: On a whiteboard it is tempting to draw all stick arrows because they are easier. Readers may then misinterpret blocking behavior. Decide intentionally and label if unsure.

10.2.3 Worked Example: Department Seminar Scheduling

Worked example — department seminar scheduling to registration creation:

Scenario: A department schedules a seminar for a given term and year, then creates a registration (or class section) for students.

Participants: :UI (or :Frontend), :Department, :Scheduling (or ScheduleClass), :Registration — plus the data carried as parameters: deptCode, year, term.

Flow described in the lecture (happy path with one guard):

  1. Enter the department code, year, and term via the UI. System event: enterScheduleInfo(deptCode, year, term) arrives at the system boundary.
  2. The Department class receives this information and first verifies whether the department code exists. This is a guard: [deptCode valid]. If invalid, the alternate path ends with an error (shown in an alt frame).
  3. If valid, the department asks for the scheduling class for that department for the given term and year — message getSchedule(term, year) to the scheduling collection or factory, which returns a Schedule object.
  4. From that, it determines how many classes or sections are needed and creates the registration for the semester with the number of students to be registered into the class — message createRegistration(schedule, capacity) or makeRegistration(...) that instantiates a Registration (or ClassOffering) object.

How to draw it:

Sequence form (top to bottom):

:Actor -> :UI : enterScheduleInfo(deptCode, year, term)
:UI -> :Department : verifyDepartment(deptCode)
alt [valid]
  :Department -> :Scheduling : getSchedule(term, year) : Schedule
  :Department -> :Registration : create(deptCode, year, term, capacity)
else [invalid]
  :Department --> :UI : error("unknown department")
end

Collaboration form (same messages, numbered):

  • Link :UI:Department carries 1: verifyDepartment(deptCode) and 1.1: nested inside.
  • Link :Department:Scheduling carries 1.1: getSchedule(term, year) (only if valid).
  • Link :Department:Registration carries 1.2: create(...) with {new} stereotype.

What becomes a method: Each distinct message becomes a method on the receiver: Department.verifyDepartment(), Scheduling.getSchedule(), Registration.create(...) (often a constructor). The parameters are exactly the data the sender already holds — deptCode, year, term — which later become arguments.

Additional illustrations mentioned: Taking seminar details from the UI and passing them to a Seminar object that records course, seminar number, and description — messages like recordSeminar(course, number, description) — and enrolling a student by collecting student information and calling enrollStudent(studentInfo). Enrollment work and passing along relevant data are shown through successive forwarding messages from the UI through the controller to domain objects.

Sense-check: At the end, a Registration exists for a valid department and term, linked to the correct Department and Schedule. No registration is created for an invalid code. The diagram can be read in execution order without jumps, and each message has a visible receiver that holds the needed data.

10.2.4 Student Questions and Answers

Q: What is the difference between a synchronous message and an asynchronous message, especially when thinking about multi-threading?

A: Synchronous messages are shown with a filled arrowhead and imply that the sender waits for a response before continuing — the sender is blocked until the receiver returns, just like a normal method call. Asynchronous messages use an open (stick) arrowhead and allow the sender to continue without waiting, like starting a new thread with Thread.start() where the caller does not wait for Runnable.run() to finish. The distinction matters for multi-threaded environments because it affects blocking, concurrency, and ordering guarantees. When sketching quickly, people often default to stick arrows, so readers should not assume arrow shape is correct without checking intent.

Q: Can we upload a diagram we draw for the seminar use case and get feedback?

A: Yes, the guidance was to draw the sequence or collaboration diagram for the common scenario, identify objects, identify message passing and sequencing, and share the drawing. Scanning a hand-drawn diagram and submitting it through a tool was suggested as a valid way to do this — clarity matters more than tool polish. The feedback loop helps catch issues like illegal numbering or mis-placed responsibility early.

10.2.5 Industry Applications

System events such as pressing spell-check, end-of-sale, or submit seminar details show how external events from a user interface are mapped to controller handling and then delegated to domain objects. In a POS system, endSale from the register UI becomes a controller message that triggers total calculation; in a word processor, spellCheck triggers dictionary lookup. The same mapping appears in web systems where an HTTP request is the system event forwarded from a frontend controller to domain services.

10.2.6 Exam Notes

Exam note: Be able to draw both sequence and collaboration diagrams for the same scenario, apply legal numbering (including 1a/1b for mutual exclusion and * for iteration), show synchronous versus asynchronous arrows correctly, and use ref frames to split a large use case. Identify messages precisely because each message directly reveals a method that must exist in the receiver class.

Exam note: Keep diagrams simple and readable; an overly cluttered diagram signals a need to split with reference frames. Examiners can ask you to simplify a crowded diagram.

Recap + Bridge: A message is a promise that the receiver can act; interaction diagrams make those promises visible in time order, and every arrow adds a method to the class model. To know whether an arrow is even allowed, we need the next idea — visibility. → Next: what connections must exist before a message can travel.

10.3 Visibility, Scope, and Kinds of Responsibility

10.3.1 Concept Overview

Hook: You have drawn a perfect message getPrice() from Sale to ProductSpecification — but can Sale actually see a ProductSpecification at that moment? If not, the arrow is a wish, not a design.

An object can only send a message to another object if it has visibility — a connection or reference that makes the receiver accessible. Visibility means accessibility: a link, an association, or some form of access such as global access, local access, or parameter access. Scope defines where a variable or parameter is accessible in code. A parameter within a function has local (method) scope; a global variable has access in many places. Sending parameters or messages is only possible where visibility exists. This links the object-oriented notion of visibility directly to programming experience with variable scope — if you cannot name a variable in that block, you cannot send it a message either.

The four kinds of visibility (from object A to object B):

  • Attribute visibility — B is an attribute (field) of A. This is relatively permanent; it lasts as long as A and B exist. In Java: private ProductCatalog catalog; inside class Register gives Register attribute visibility to ProductCatalog. This is the most common form.
  • Parameter visibility — B is passed as a parameter to a method of A. Temporary; it lasts only within the method execution. Example: makeLineItem(ProductDescription desc, int qty) gives Sale parameter visibility to that ProductDescription instance for the duration of the call. This is the second most common form.
  • Local visibility — B is declared as a local object inside a method of A, either by creating it (SalesLineItem sli = new SalesLineItem(...)) or by assigning a return value (ProductDescription d = catalog.getProductDescription(id)). Also temporary, method-scoped.
  • Global visibility — B is globally visible (least common in well-designed OO systems). In languages like C++ a true global variable can provide this; in Java the preferred disciplined replacement is the Singleton pattern, where a single instance is accessed via a class method.

Transformations are common and intentional: parameter visibility is often turned into attribute visibility by assignment (this.description = desc in a constructor), and local visibility into attribute visibility the same way. Whenever you need a longer-lived connection, you promote the visibility.

Responsibilities divide into two broad kinds familiar from CRC cards (Class-Responsibility-Collaborator) — an early lightweight design technique where each class has a card listing what it knows and does and who it collaborates with:

  • Knowing: what information the object holds. This includes private encapsulated data, public and protected data, its attributes, and which collaborators it knows about. It also includes accessor duties such as get and set operations, and knowing about related objects (e.g., a Sale knows its SalesLineItems).
  • Doing: what the object does. This includes performing computations and calculations itself, informing other objects to do work, carrying out an operation itself, and requesting services from collaborators when it cannot complete a job alone. Initiating action in other objects and controlling or coordinating activities of other objects — knowing about others and sequencing actions one after another — are central doing responsibilities. Each object should have a clear purpose that defines what it does.

Intuition — visibility as eyesight and responsibility as job description: Think of visibility as whether you can see someone in a room. Attribute visibility is like a colleague who sits at the next desk — you can see them all day. Parameter visibility is someone handed to you for a meeting — visible only while the meeting lasts. Local visibility is someone you pull aside in the hallway after a phone call — you just obtained a reference and can talk briefly. Global visibility is the loudspeaker — everyone can hear it, but overuse creates noise. Knowing and doing responsibilities are like a job card: "knows: own schedule and team members" and "does: calculates total, asks others for subtotals, coordinates the result."

Where it breaks: Unlike people, software visibility is strict. You cannot shout across rooms to an object you do not hold a reference to, even if you know its class exists. Possibility is not visibility.

Visual intuition — visibility graph: Imagine a figure with four small object boxes: Register, Sale, ProductCatalog, SalesLineItem. Solid lines labeled "attribute" connect RegisterProductCatalog (permanent) and SaleSalesLineItem (collection). Dashed arrows labeled "parameter" show a transient link during makeLineItem(desc,qty) from Sale to ProductDescription. A small note box shows local visibility created inside enterItem() where desc appears after a return assignment. The x-axis is not numeric; the shape is about permanence: attribute lines are thick and long-lasting, parameter/local lines are thin and annotated with [during method]. Takeaway in one sentence: messages can only flow along a visibility line that exists at that moment.

10.3.2 High Cohesion as a Design Aim

Each object should do a single, well-defined job. That is described as high cohesion, where a single-responsibility object keeps its purpose focused. The behavior and data of the object stay at the same place, supporting encapsulation. Requesting services from other objects via collaborators is expected — cohesion does not mean isolation — but the core activity of the object itself should remain narrow.

A useful contrast is a Big object with 100 methods and 2,000 lines covering database, UI, and calculations (low cohesion) versus a Small object with 10 focused methods and 200 lines (high cohesion). High cohesion is evaluated alongside low coupling: keeping each object focused also keeps its dependencies lean because it only needs collaborators for its one job, not for many unrelated jobs.

Scope — when high cohesion guidance applies: It applies to every class, but especially to domain objects that model real-world concepts. It assumes you have identified responsibilities; cohesion tells you whether they belong together. Assumption: A class can delegate to others — high cohesion does not forbid collaboration. It forbids cramming unrelated responsibilities into one place. When it strains: Over-decomposing into tiny one-method classes with forced collaborations can also hurt readability. Cohesion is about functional relatedness, not just size.

Pitfall — confusing cohesion with coupling: Cohesion is about focus within one object; coupling is about dependence between objects. Beginners mix them. Ask: "Does this class have many unrelated jobs?" (cohesion) versus "Does this class know too much about many others?" (coupling).

Pitfall — exposing internal data to avoid needing visibility: To let another object compute something, beginners make fields public so anyone can grab the data. This breaks encapsulation. Instead, give the responsibility to the holder of the private data and keep the field private — visibility should be via a message to the expert, not via direct field access.

10.3.3 Student Questions and Answers

Q: How do you define visibility and scope using programming experience?

A: Visibility is the ability to access another object or variable. Global variables are accessible broadly, locals only within a function, and parameters are accessible where they are passed. Scope limits that accessibility — a variable declared inside a block is only nameable there. An object can only send a message or pass its parameters where it has visibility, which requires a link or association between sender and receiver. In code, if you cannot compile a reference to catalog in this method, you do not have visibility to ProductCatalog here, no matter how useful it would be.

10.3.4 Industry Applications

Human organization separates work among specialists so that each department focuses on its own concerns without interference, which mirrors software separation of concerns that visibility and scope rules enforce. In layered architectures, a domain object is not given global visibility to a UI widget because that would tie domain logic to presentation. Enforcing visibility boundaries keeps layers replaceable — for example, swapping a Swing UI for a web UI without touching Sale logic.

10.3.5 Exam Notes

Exam note: Explain visibility in terms of four kinds (attribute, parameter, local, global) with a code snippet for each, connect scope to where a message or parameter can legally travel, and show at least one visibility transformation (parameter → attribute in a constructor). Distinguish knowing responsibilities (attributes, collaborators, get/set, derived info) from doing responsibilities (compute, inform, delegate, coordinate) with concrete examples for each.

Recap + Bridge: No visibility, no message. Knowing vs doing tells you what an object should be responsible for; visibility tells you whether it can actually call a collaborator to help. Together they are the plumbing that makes responsibility assignment executable. → Next: GRASP names the patterns that guide which visibility and responsibility choices to prefer.

10.4 GRASP: General Responsibility Assignment Software Patterns

10.4.1 Concept Overview

Hook: Without guidance, "who does what?" becomes an opinion match. GRASP gives you nine named answers you can cite, so a design review stops being "I like this" and becomes "Expert says Sale does this because it already holds the data."

GRASP stands for General Responsibility Assignment Software Patterns. The key words are responsibility assignment. GRASP collects guidelines and principles for assigning responsibilities to objects and is presented as a learning aid and communication tool rather than as the final set of Gang of Four design solutions. The Gang of Four patterns are the concrete design ideas — Strategy, Factory, Adapter and twenty others — studied afterward as the Gang of Four (GoF) patterns; GRASP documents simple object-oriented assignment guidelines in pattern form so beginners can reason methodically before tackling the heavier GoF catalog. The name is also a mnemonic: grasp these principles to grasp object design.

There are nine GRASP patterns. The first five, often treated as the most used, are Expert, Creator, Controller, Low Coupling, and High Cohesion. The additional four are Polymorphism, Indirection, Pure Fabrication, and Protected Variation. In the lecture, Controller and Indirection are singled out as more challenging because they involve layering and indirection decisions, while the others are described as simple principles that follow quickly once Expert is understood. GRASP is sometimes read as "learning to grasp object analysis and design principles and guidelines for assigning responsibilities."

What a pattern is — problem, solution, context:

A pattern in general is a recurring solution to a standard problem in a context. That wording carries three inseparable parts: problem (what issue repeatedly appears), solution (a named, reusable structure), and context (when it applies and what forces trade off). A pattern names a problem and solution that can be applied to new contexts with adaptation. Choosing a pattern involves trade-offs with advantages and disadvantages to be weighed — there is no pattern that is always best.

The lineage is explicit in the lecture: the father of patterns, civil engineer Christopher Alexander, established this way of naming and reusing good solutions in built architecture (rooms, buildings, towns), which later inspired Beck, Cunningham, and the GoF to name software patterns. That history matters because it explains why we say "pattern language" — just as architecture has door and window patterns, software has responsibility-assignment patterns.

Formally: a pattern is a name plus a description of problem and solution that can be applied to new context, advising how to apply the solution in varying circumstances and consider trade-off forces.

A pattern is not a finished piece of code you copy-paste; it is advice you adapt. Thinking in patterns also supports low representational gap — choosing software names and structures that mirror how we already think about the domain — so a Board in the domain naturally becomes a Board in the design.

10.4.2 Naming, Communication, and Reuse

Intuition — names as handles: Imagine trying to discuss "that theorem about right triangles where the squares on the legs sum to the square on the hypotenuse" every time. Naming it Pythagoras compresses a proof, a diagram, and a use-case into one word. The lecture uses exactly this example:

Saying a decision follows a named pattern is like citing Pythagoras theorem: the name carries a whole set of intent, structure, and trade-off.

The same compression happens when you say "Sale creates SalesLineItem by Creator via composite aggregation." A teammate can reconstruct the associations, the coupling argument, and the alternative considered.

Everyday analogies reinforced in the lecture: Dress patterns for sari, plaza (salwar?), jeans illustrate naming variations — the same general garment with tailored variants. Carpenter patterns for windows and doors show that a window pattern has concrete parameters (frame, pane, hinge) adapted per building, yet the name brings the full picture to mind. Physical patterns teach that variation is expected — the pattern is not a rigid mold.

Giving a pattern a name makes communication among developers and solution architects compact. Saying that a particular pattern was applied conveys the full set of involved objects and intent without repeating every diagram. Names support chunking ideas into memory so they can be incorporated into understanding and recalled under time pressure.

The advantage of a pattern over an isolated rule is that it talks about context together with problem and solution, so intent is clearer. GRASP uses this naming and documentation practice for assignment guidelines, even though strictly they are principles and advices rather than concrete pattern solutions in the Alexander sense (where a pattern is a physically built solution). The Larman simplification is noted explicitly: many principles and guidelines are presented as patterns to help learners reason scientifically about responsibility assignment rather than claiming an intuition-only process. Design is described as constrained choice among alternatives: select the best solution within time limits, weighing coupling, cohesion, and encapsulation.

Visual intuition — GRASP as a filter: Picture a funnel. At the top, many possible assignments for a responsibility ("Sale could do it, Register could do it, a new helper could do it"). In the middle, GRASP patterns act as labeled filters — Expert ("who has the data?"), Creator ("who contains it?"), Low Coupling ("which choice adds fewer dependencies?"). At the bottom, one or two surviving options exit with a justification label attached. The x-axis is alternatives, the y-axis is evaluation depth. Takeaway: GRASP narrows choices with explicit criteria instead of gut feel.

Scope: Use GRASP during interactive design — while sketching interaction diagrams or while deciding where to add a method during coding. It assumes you are doing responsibility-driven design with Collaborations; GRASP is not a replacement for identifying use cases or domain concepts. Assumption: The domain model is available as inspiration. GRASP reasoning often starts by asking which domain object aggregates or knows the needed information. When it is over-applied: Not every method decision needs a named pattern citation in production code comments. Use the names heavily while learning and in design reviews; in mature code, the structure should speak for itself.

Pitfall — treating GRASP as Gang-of-Four: Beginners think GRASP replaces GoF. It does not. GRASP answers "who gets this method?" GoF answers "how do we structure families of classes to handle creation, adaptation, or behavioral variation?" You need both, in order.

Pitfall — naming without reasoning: Saying "by Expert" without stating what information the expert holds is hollow. Always complete the sentence: "by Expert, because Sale already holds the collection of SalesLineItems and therefore the data to compute the total."

Pitfall — pattern as excuse for a single "beautiful" design: There is no single beautiful design. Every choice has pros and cons. If you cannot name the disadvantage of the pattern you chose, you have not finished the evaluation.

10.4.3 Approach to Learning GRASP

Learning object design through GRASP is framed as applying responsibility principles rationally and in an explainable way. Instead of saying a decision was made by intuition, the designer can point to an established principle and show the trade-off. The guidance recommends studying at least four or five case studies of good designs to absorb how patterns operate in context — reading the interaction diagram, covering the answer, guessing the assignment, then checking against the stated pattern. Open-Close Principle and Liskov Substitution are examples of broader principles that complement GRASP while designing; they will appear later but already shape how you think about extensibility.

Expect to reuse accumulated wisdom from thirty to forty years of software design rather than reinvent every collaboration. That reuse is precisely the economy a pattern language provides.

Q: How is the Larman view of pattern similar to or different from the Alexander view?

A: Both describe a named problem and solution usable in new contexts and value reuse of standard solutions — the core idea transfers directly from buildings to software. The main difference highlighted is emphasis: the Larman GRASP presentation emphasizes principles and advices — rules, examples, and reasoning for assignment — while the Alexander focus is on concrete built solutions (physical structures you can inhabit). In Larman's framing, many guidelines are intentionally presented as patterns for pedagogic clarity even though, strictly, they are principles. The similarity is reuse through naming; the difference is abstract guideline versus built artifact.

10.4.4 Industry Applications

Reuse across thirty to forty years of accumulated software design experience, treated as a set of named good solutions that can be adapted rather than reinventing each problem from scratch, is standard practice in product teams, consultancy libraries, and open-source frameworks. Pattern catalogs form checklists in design reviews: "Did we consider Expert, Creator, and Low Coupling for this new use case?" This practice shortens onboarding because a newcomer who knows the pattern vocabulary can read a prior team's interaction diagrams quickly.

10.4.5 Exam Notes

Exam note: List the nine GRASP patterns by name (Expert, Creator, Controller, Low Coupling, High Cohesion, Polymorphism, Indirection, Pure Fabrication, Protected Variation), identify the first five as the primary assignment guidelines, and be able to explain why Controller and Indirection need extra attention — they involve layering, delegation, and shielding change, not just single-class data possession. Define pattern as recurring solution to a standard problem in context and explain why naming aids communication and memory — chunking plus precise trade-off discussion.

Recap + Bridge: GRASP is a pattern language for "who does what," naming nine recurring answers so teams can choose and defend assignments together. The names matter because they carry context and trade-offs, turning opinion into reasoning. → Next, we apply the first and most frequent answer: Expert — give the work to the information holder — and see precisely why persistence is the instructive exception.

10.5 The Expert Pattern: Assigning Work to the Information Holder

10.5.1 Concept Overview

Hook: A sale needs a total. Many classes could compute it — Register, Sale, a helper — but only one already holds the pieces. Who has the data already, and why does that one choice make the whole system lighter?

The Expert pattern (often called Information Expert) states that responsibility should be assigned to the class that has the information needed to carry it out. An expert is whoever holds the data and skill to do the job. For software this becomes an information expert rule: give the responsibility to the object that already holds the attributes or collaborator information required, because that object can do the work with low extra coupling and preserved encapsulation.

The intuition from everyday life is used explicitly in the lecture: the gardener does gardening, each person does the job they know, and in the same way a software object with the right attributes should hold the method. Lightweight classes collaborating to meet a responsibility follow from this: data and the behavior that needs that data reside together, and no single god class accumulates everything.

A responsibility is not just a method; it is an obligation of one object to another, a contract or guarantee that once a message is sent the receiver will perform the work. That contrasts sharply with human organizations where a person with capability might still not act; in an object system the obligation is expected to be met. Responsibilities split into knowing and doing, and Expert applies to both — here it tells us who should know the total and who should do the calculation.

Intuition — the gardener, extended: Picture a gardening crew. The soil expert knows soil type and holds the soil report; the seed expert holds seed varieties and costs. If you need "which seed for this soil," you ask the soil expert to collaborate with the seed expert, not a random laborer who must first be handed both reports. In software, Sale holds the list of line items, each SalesLineItem holds quantity and a link to ProductSpecification, which holds price. The information already lives in those three places, so the behavior should live there too. Adding a fourth helper that must be fed all the data would increase traffic without reason.

Where it breaks: A gardener could choose not to garden; a software Expert cannot refuse its contracted method. Also, human experts can be consulted informally; software experts need explicit visibility to the collaborator's data via a reference or parameter.

10.5.2 Mathematical Formulation

The spoken description given is that the subtotal for a sales line item needs quantity and product price, and the total for a sale needs the sum of line subtotals. Reconstructed alongside that description and reconciled against Larman T1 Chapter 17 and companion examples:

Let be the quantity for sales line item , where (a natural number, e.g., items) and is held by the SalesLineItem object, and let be the unit price for the product in that line, where (a non-negative real, e.g., in currency units) and is held via ProductSpecification (exposed via getPrice()).

Line subtotal — the Expert building block:

Then the subtotal for line is

where is ordinary scalar multiplication. The symbols are: is the subtotal value for line (currency), quantity, unit price. The multiplication is valid because both operands are scalars. Boundary check: since and , we have , as expected for a price subtotal.

Sale total — aggregation by the higher Expert:

Let there be sales line items in a sale, where and the line items are held as a collection inside Sale. The total for the sale is the sum of all line subtotals:

with the summation over the collection of sale line items indexed . The quantities reside on SalesLineItem and prices on ProductSpecification; Sale aggregates the line information, which supports assigning the summing behavior to Sale as the information expert. Special case : , which still fits the formula.

Derivation in one line: Substitute the subtotal expression into the total definition — no skipped algebra — so the total is directly computable from the two source attributes via their experts.

Visual intuition — income stack: Imagine a bar chart where the x-axis is line item index and the y-axis is currency (e.g., rupees). Each bar's height is . One bar might be height (), another (), another (). The total is the stacked height , shown as the top of the stacked bar. The takeaway: Sale as expert stacks what SalesLineItem experts already know individually.

10.5.3 Worked Example: Computing a Sale Total

Setup: Sale holds a collection lineItems : List<SalesLineItem> (e.g., 3 items). Each SalesLineItem holds quantity : int and a reference product : ProductSpecification that holds price : Money. Money is treated as a decimal type.

Responsibility: Computing the total for the sale needs every line subtotal and the final sum. No other object holds the complete collection.

Assignment (why Expert): Sale is the information expert for the total because it already knows about all SalesLineItems. It receives the message and therefore holds a method that returns the total. SalesLineItem is the expert for its own subtotal via ; ProductSpecification is the expert for .

Steps with real numbers — trace through:

Suppose:

  • Line 1: quantity q1 = 2, product price p1 = 120.00
  • Line 2: q2 = 3, p2 = 25.00
  • Line 3: q3 = 1, p3 = 50.00

Execution:

  1. Caller sends t = sale.getTotal() to Sale.
  2. Inside getTotal(), Sale iterates over lineItems (loop frame [for each i = 1..n]). For each lineItems[i], it sends st = lineItems[i].getSubtotal().
  3. Inside SalesLineItem.getSubtotal(), it does p = product.getPrice() then computes return quantity * p. So getSubtotal() for line 1 returns 240.00, line 2 75.00, line 3 50.00.
  4. Sale sums: and returns it.

Pseudo-code mapping:

class Sale {
  List<SalesLineItem> lineItems;
  Money getTotal() {
    Money total = 0;
    for (SalesLineItem sli : lineItems)  // iteration
      total += sli.getSubtotal();        // delegate to expert
    return total;
  }
}
class SalesLineItem {
  int quantity;
  ProductSpecification product;
  Money getSubtotal() { return quantity * product.getPrice(); }
}

The interaction diagram builds incrementally (the lecture does exactly this): start with getTotal() on Sale, then add getSubtotal() to each line object, then add product price retrieval, always asking which object holds the needed data? The result keeps behavior and data together and keeps message names abstract (getTotal, getSubtotal, getPrice), not database-specific.

Sense-check: Each subtotal is non-negative and scales linearly with quantity (double quantity → double subtotal). The total is at least as large as the largest subtotal and equals the sum of non-negative parts — matches the bar-stack picture.

A special case is pointed out and saved for the next subsection: saving a sale to a database is a common operation every persistent class would otherwise need. Although all the sale information is in Sale, giving Sale the responsibility to handle connection strings and database work would make every class heavy and duplicate persistence logic. This is an intentional exception to Expert — separation of concerns overrides information possession here.

Scope — when Expert applies: Use Expert when the needed information is already inside one class or its directly known collaborators, and the responsibility is about that information (computing a total, finding an item by key, validating a code). Expert assumes a domain model exists so you can see who aggregates what. Assumption: Information is not widely duplicated across many classes; the domain model accurately reflects who knows what. If two candidates equally hold the data, apply Low Coupling as a tie-breaker. When it does not apply cleanly: Cross-cutting concerns that touch many classes (persistence, logging, security) often have the information but should not take the responsibility, because doing so would destroy cohesion and duplicate infrastructure code.

Pitfall — "Information holder = any holder": Beginners pick any class that could be given the data as a parameter. Expert means already holds without extra parameter passing. If you must pass the data in, that class is not the expert.

Pitfall — ignoring the persistence exception: Giving Sale a saveToDB() that opens a JDBC connection seems convenient ("Sale has all the sale data!") but violates separation of concerns, creates high coupling to database APIs, and forces every domain class to duplicate connection logic. Keep persistence in a separate service or PersistenceManager.

Pitfall — anemic experts: Creating a SaleHelper that pulls quantity and price out via getters to compute the total recreates procedural code. Let the experts compute themselves; the helper merely coordinates if needed.

10.5.4 Exception, Separation of Concerns, and Encapsulation

Persistence belongs apart under separation of concerns. Database work — handling a SQL server or other persistent storage, connection strings, transaction boundaries — should live in a separate persistence concern or layer, not inside each domain class. That keeps classes highly cohesive, each focused on its own domain concern, and maintains low coupling and better encapsulation where private data is not exposed for persistence convenience. The guidance is that not every class should know how to access a database; a dedicated class or layer (often called PersistenceManager, DBService, or a Mapper/Repository) provides that service so domain objects remain focused on domain behavior.

In modern three-tier terms, this is why the domain layer does not embed database access: the same Sale logic must work regardless of whether the store is a relational DB, a file, or an in-memory mock. Encapsulation also benefits: persistence code often needs to set private fields; exposing those fields just to satisfy persistence weakens the class contract.

10.5.5 Student Questions and Answers

Q: Who should have the responsibility for computing the total? And how do we show it in a diagram?

A: Sale should have that responsibility because it knows about every SalesLineItem and, transitively via those items, the product prices — it is the information expert for the collection total. In the sequence or collaboration diagram it is shown as the message received by Sale, which implies a method in that class. From there, for each line, the subtotal per line is obtained via on each SalesLineItem, which itself asks ProductSpecification for . That chain adds methods by following the messages: each distinct arrow becomes a method in its receiver. The key test is always: who already holds the data needed for this step?

10.5.6 Industry Applications

Gardener and election booth analogies make Expert concrete in team discussions — give the task to whoever already holds the needed information, not to whoever volunteers. Persistence separation reflects modern three-tier practice where domain objects do not embed database connection handling; a dedicated persistence service does it to avoid duplication across classes, as seen in frameworks like Hibernate, JPA, or Repository patterns.

10.5.7 Exam Notes

Exam note: Be ready to walk through the sale total example step by step with real numbers (show at least one line with and the final ), naming who holds quantity (SalesLineItem), who holds price (ProductSpecification via getPrice()), and why Sale is the total expert but not the database-save expert (separation of concerns, cohesion, coupling). Expert reasoning should explicitly reference information possession, encapsulation, high cohesion, and low coupling in the justification.

Recap + Bridge: Expert says: let the holder of the data do the work — Sale sums what its line items already know, each line item multiplies what it and its product already know — and keep infrastructure concerns separate. This same data-possession test answers the next question, creation: who already holds the parts and the construction data? → Next: Creator, the Expert of instantiation.

10.6 The Creator Pattern: Responsibility for Creating Instances

10.6.1 Concept Overview

Hook: Every system constantly births new objects — a new SalesLineItem, a new Payment, a new Registration. But who should do the birthing? The class that is already holding, recording, or intimately using that kind of object usually should.

Creator addresses a frequent activity in object-oriented systems: who creates instances. Creation is done via a constructor (or factory method) that requires parameters, so whoever creates an object should have the information and access to supply those initialization parameters without extra coupling. Conceptually, Creator is Expert applied to creation: the expert in building an object should be the one that creates it, because it already knows the parts, the context, or the construction data.

Creator — when B should create A:

Assign class B the responsibility to create an instance of class A if one or more of these is true (the more that apply, the stronger the case):

  • B aggregates or contains A — B is a container/composite of A, or records A. Examples: Sale contains SalesLineItem (composite aggregation), Department conceptually contains CourseOffering. Composition is an especially strong signal because the container manages lifecycle.
  • B closely uses A — B frequently operates on A instances in its own behavior.
  • B has the initializing data for A — B holds the attribute values that will be passed to A's constructor.

Creation via Creator therefore keeps coupling low and encapsulation intact, because the creator does not need to be given data it already has, nor does it need a new dependency introduced just to create.

Why "contains" dominates: If B already aggregates many A instances, it already has visibility to A's type, manages the collection, and knows the invariant (e.g., a Sale's line items must be non-empty or quantity > 0). Creating through the aggregate keeps that invariant check in one place.

The relationship is between software objects in the Design Model; when no software classes exist yet, Larman advises using the Domain Model as inspiration with low representational gap — if the domain says a Board contains Squares, the software Board is a natural creator of software Squares.

When such a containment or close-use relationship exists, coupling remains low and encapsulation stays intact because creation uses information the creator already holds. The alternative — an unrelated helper collecting all parameters just to forward them — would introduce a new coupling and duplicate knowledge.

Intuition — the warehouse and the shelf: Think of a warehouse (container) that holds boxes on shelves. When a new box needs to be added to a specific shelf, you ask the shelf to create the placement — it already knows its capacity, what is on it, and where the new box goes. Asking a random forklift in another aisle to create the box and then hand it over would require the forklift to first learn everything about that shelf. Creator is that shelf logic: let the container that will ultimately own the thing be the one that creates it.

Where it breaks: If creation is complex — choosing among a family of subclasses, pooling recycled instances, or reading external configuration — a dedicated Factory is more appropriate, even though a container exists. Creator advises the common, simple case.

Visual intuition — containment as creation license: Picture a UML class diagram fragment. A Sale box has a diamond (composite aggregation) line to SalesLineItem with multiplicity 1 to 1..*, and SalesLineItem has a line to ProductSpecification. Next to it, a sequence diagram shows register.makeLineItem(desc, qty) arriving at Sale, then a dashed creation arrow create(desc, qty) from Sale to a new SalesLineItem lifeline appearing lower on the page, then Sale adding it to its collection. The x-axis in the class view shows structure; the y-axis in the sequence view shows time flowing down to birth. Takeaway: containment in the static view licenses creation in the dynamic view.

Scope: Apply Creator for straightforward instantiation where one class aggregates, records, or closely uses the other. It assumes simple construction with available initializing data. Assumption: The candidate creator will continue to hold an association to the created object after creation; if it will not, Creator may not be the best fit — consider passing the new instance to its real owner instead. When to prefer a Factory instead: When creation requires looking up a family of classes, conditional choice of subclass, performance pooling, or external property files. These are classic factory scenarios (Concrete Factory, Abstract Factory) covered later.

Pitfall — making any class the creator because "it can": Any object can call new SalesLineItem(), but Creator asks who should given existing relationships. Choosing an unrelated class adds a new dependency solely for creation — exactly the coupling Creator aims to avoid.

Pitfall — confusing Creator with merely having data: Holding one construction parameter is weak evidence. Prefer the class that both contains/records and has data. If only data overlaps, verify coupling impact.

Pitfall — forgetting to add the new instance to the aggregate: Beginners instantiate SalesLineItem but forget the second step — adding it to Sale's collection. The creation responsibility includes establishing the association, not just calling the constructor.

10.6.2 Worked Example: Sale Creating SaleLineItem

Setup: Sale already holds the collection lineItems : List<SalesLineItem>. A new sales line item for a particular product needs to be added to a particular sale after enterItem(itemID, quantity) has retrieved a ProductSpecification desc and a quantity qty.

Assignment — Creator test:

  • Does Sale contain/aggregate SalesLineItem? Yes — composite aggregation Sale 1 — 1..* SalesLineItem. Strong signal.
  • Does Sale closely use SalesLineItem? YesgetTotal() iterates over them constantly.
  • Does Sale have initializing data? Yes — it receives desc and qty as parameters (enterItem path) and holds the sale context.

Conclusion: Sale is the candidate Creator. No other class scores as highly.

Messages and methods:

Sale receives or equivalently and holds a corresponding method:

class Sale {
  List<SalesLineItem> lineItems;
  void makeLineItem(ProductDescription desc, int qty) {
    SalesLineItem sli = new SalesLineItem(desc, qty);
    lineItems.add(sli);           // establish the aggregation link
  }
}
class SalesLineItem {
  ProductSpecification product;
  int quantity;
  SalesLineItem(ProductSpecification desc, int qty) {
    this.product = desc;
    this.quantity = qty;
  }
  Money getSubtotal() { return quantity * product.getPrice(); }
}

Inside that method Sale calls the constructor for SalesLineItem for the given product and quantity, then adds the new item to its collection, thereby establishing visibility. The interaction shows messages that translate directly to creator methods — makeLineItem on Sale and create(desc, qty) (stereotyped «create») to SalesLineItem.

Sequence sketch:

:Register -> :Sale : makeLineItem(desc, qty)
:Sale -> :SalesLineItem : create(desc, qty)  // dashed, {new}
:Sale -> :Sale : lineItems.add(sli)          // self message, establish link

Effect: Responsibilities for creating the line item stay with the aggregate, keeping the model coherent and coupling low — Sale was already coupled to SalesLineItem type via its collection, so creation adds no new dependency. The same line of reasoning extends to other containment cases: Department creating CourseOffering, Board creating Squares (40 squares case in T1), Order creating OrderLine.

Sense-check: After the call, sale.getTotal() increases by qty * desc.getPrice() compared to before — the total reflects the new line, and the new SalesLineItem is reachable via sale.lineItems.

The discussion also notes containment terminology: part-of relationships favor creation by the whole. The overall message is that creation decisions are made by checking which object is the expert in providing the initialization data — Creator is a specialization of Expert for birth.

10.6.3 Industry Applications

Department as creator of course or seminar offering reflects containment in organizational modeling — a department owns its offerings, so it creates them. Choosing creation targets via containment and close-use relationships is described as keeping coupling low and supporting reuse of the creation responsibility. In frameworks, composite owners creating their parts appears pervasively: a Document creating its Paragraphs, a Cart creating CartItems, a Playlist creating PlaylistEntrys.

10.6.4 Exam Notes

Exam note: When asked who should create an object, look first for containment or aggregation (composite or Contains label) and for who already has the data to construct it. Be ready to propose methods such as that follow from the message, sketch the static aggregation and the dynamic creation arrow (dashed with «create» and {new}), and argue via Low Coupling why the container is preferred. Mention the Factory exception for complex creation.

Recap + Bridge: Creator keeps birth where ownership already lives — the whole creates its parts because it already holds them and the data to make more. This mirrors Expert: give creation to the information holder so no extra dependencies are introduced. → Next: one more "who first?" question — who receives system events from the outside world? That is Controller.

10.7 The Controller Pattern: Coordinating System Events Without Burdening the Interface

10.7.1 Concept Overview

Hook: Every click, swipe, or scan is a knock on the system's door — "create a registration," "end the sale," "enter seminar details." Which object should answer that knock so the door (the UI) stays light and reusable?

Controller answers who should be responsible for handling system events. A system event is a high-level event generated by an external actor operating through the user interface — the operation named in a System Sequence Diagram (SSD) such as createRegistration(deptCode, year, term), enterItem(itemID, quantity), or endSale(). The first non-GUI object to receive such events is the Controller. All business logic lives behind this point in a model-view-controller or broader three-tier view where the presentation layer and persistence/database layer flank the domain layer and its software objects.

A GUI component such as a button, text field, or scanner listener should only receive the raw input and forward it. The actual handling — validation, lookup, creation, calculation — is delegated to the Controller, which then coordinates work among domain objects. System events are identified during SSD work and then mapped to Controller responsibilities. Controllers can be named handlers in code, often with a suffix like Handler, Coordinator, or Session.

The principle cited is separation of concerns: keep user interface concerns (widget state, rendering, input handling) distinct from domain processing (business rules, calculations, persistence coordination) so the interface remains usable and reusable and the domain remains testable without a GUI.

Controller definition and where it sits:

Architecture: Actor → UI Layer (Windows, Buttons, Forms)Controller (first non-UI object)Domain Objects (Sale, Department, Seminar)Persistence. The Controller is the seam between the outside and the inside.

Responsibility: Receive a system event message, validate its parameters, delegate to the appropriate domain objects in the right order, collect results, and return or forward them. It delegates, not does everything — it coordinates, while Experts do the actual domain work.

Why an object at all: Without a Controller, every UI widget would need to know which domain objects to talk to and in what order, tying business logic to widget code.

10.7.2 Why the Interface Should Not Handle System Events

Intuition — the receptionist vs the specialist: Think of a hotel reception desk (UI). A guest asks to book a conference hall for a department event (system event). The receptionist does not personally arrange catering, AV, and housekeeping; they take the request and hand it to the events coordinator (Controller), who knows which specialists to call. If the receptionist did all the work, you could not replace the receptionist with a kiosk or a phone app without rewriting the booking logic.

Where it breaks: A human receptionist might still know some business rules; in software we deliberately forbid the UI from knowing them, because software UI turnover (web → mobile → voice) is far higher than human turnover.

If a GUI element processes business logic directly, that logic becomes tightly bound to that particular GUI. The interface cannot be reused elsewhere (e.g., the same sale logic from a Swing register needed for a web register) and the coupling between presentation and domain becomes high and undesirable. A non-GUI Controller provides reuse: the same domain handling can be reached from different interface forms because the logic is not embedded in any one screen widget. It also keeps the UI focused on its own cohesion — displaying and capturing input — rather than becoming a bloated mix of rendering plus business rules.

Consider the Monopoly example referenced in T1 and the compiler example from the lecture: a JFrame receiving actionPerformed should not itself implement playGame() rules; it should delegate playGame() to a domain-level handler. Similarly, a button labeled "End Sale" should forward endSale() to the Controller, not compute totals itself.

Scope — when Controller is needed: Any time a use case has system operations identified in its SSD. Every system event listed there needs a Controller assignment. This applies in desktop, web, and service architectures — the "UI" may be an HTTP endpoint rather than a button, but the same separation holds. Assumption: The system boundary and actors are defined, so system events are known. Controller does not invent new system events; it handles those already specified.

10.7.3 Types of Controllers and the Bloated Controller Trap

Three forms are described in the lecture (with naming variations in literature):

  • Facade or packet Controller (also called system or root Controller): A single Controller exposing a simplified surface over a subsystem, handling a modest number of events, often presented as handlers that hide many components. Example: a single SystemHandler or POSHandler receiving all sale events. The compiler is given as a classic packet Controller: a single entry point such as or with a file name and options hides the internal work of syntax tree creation, syntax checking, and semantic checking while coordinating all components. The caller sees one command; complexity is encapsulated. Use a facade when the number of system events is small (about five or six or fewer).
  • Use-case Controller: One handler per use case, useful when a use case involves many events or needs to maintain session state across several interactions. Examples: ProcessSaleHandler handling makeNewSale(), enterItem(), endSale(), makePayment() as one session; or ScheduleSeminarHandler remembering deptCode and year across steps. Session state — temporary data that must persist between system events of the same use case — is the signal to choose this form.
  • Role-based Controller: One handler per role such as head of department, dean, or operator, suitable when events cluster by actor role and session information is role-specific. Example: DepartmentHeadHandler vs RegistrarHandler each handling the events relevant to that role.

The guideline is that handling more than about five or six events with one Controller suggests splitting. Overloading a single Controller with too much work creates a bloated Controller (also called a low-cohesion Controller) that does too many jobs instead of merely delegating and coordinating. Bloated Controllers become hard to understand, test, and maintain, and they tend to accumulate high coupling because they know many domain classes for unrelated use cases.

Choosing among Controller forms:

Situation Preferred Controller Why
Few system events (≤5–6), simple coordination Facade / System Controller Simplicity, single entry point
Many events for one use case, needs state across calls Use-case Controller Maintains session state, high cohesion per use case
Events cluster by actor role, role-specific state Role-based Controller Mirrors organizational roles, reduces cross-role coupling

When in doubt beyond ~5–6 events, split. Controllers delegate rather than perform all domain behavior themselves. They may maintain use-case state and event or state transitions across calls, which matters for statecharts (e.g., a registration moves through ready → scheduling → registered states).

Bloated Controller detection: method count growing past ~6 distinct system-event handlers plus private helpers, handling unrelated use cases, or needing to import many unrelated domain packages.

Scope — Controllers and statecharts: When a use case maintains state (ready vs working, or registration lifecycle), a use-case Controller is the natural holder of that state between events. A facade Controller can remain stateless for simple cases.

Pitfall — bloated Controller doing domain work itself: Beginners let the Controller calculate totals, create line items, and access the database. The Controller should ask Experts to do those tasks (sale.getTotal(), sale.makeLineItem()), not do them. If your Controller has arithmetic, it has stolen an Expert's job.

Pitfall — GUI still doing logic via "just forwarding with a little check": Even a small business rule in the UI ("if quantity > 10 apply discount") is already a violation — move it to the Controller or better to the domain Expert where it can be tested without a UI.

Pitfall — one Controller for the whole system forever: As the system grows, the facade that was fine for three events becomes a magnet for every new event. Apply the 5–6 event heuristic early and refactor to use-case Controllers before the class becomes unmanageable.

Visual intuition — Controller as switchboard: Picture a three-layer stack: top layer UI with boxes for buttons, middle layer Controllers with one or more handler boxes, bottom layer Domain with Sale, Department, Registration. Arrows from UI always go down to a single Controller entry point, then fan out from the Controller to many Domain objects. A bloated Controller diagram would show one middle box with dozens of outgoing arrows to everywhere — visually overloaded — versus a use-case split where each Controller fans to only its relevant Domain cluster. Takeaway: fan-in to Controller is narrow, fan-out is focused; bloating breaks both.

10.7.4 Worked Example: From System Events to Delegation

Scenario — from SSD to Controller delegation:

Assume SSD-identified system operations: createRegistration(deptCode, year, term), enterSeminarDetails(course, number, description), endSale().

Delegation for createRegistration:

  1. The UI component (e.g., a form submit button) captures deptCode, year, term. It does not validate beyond basic input format. It forwards the system event as a message:

registrationHandler.createRegistration(deptCode, year, term) — note the Controller is the first non-UI receiver.

  1. The Controller (RegistrationHandler or ScheduleSeminarHandler) handles it:
  • Verifies the department code: dept = departmentCatalog.getDepartment(deptCode) — if null, return error via the UI channel; this uses an alt branch in the interaction diagram.
  • If valid, asks for the scheduling context: schedule = dept.getSchedule(year, term) (or schedulingService.getSchedule(dept, year, term)).
  • Determines capacity or sections needed: capacity = schedule.requiredCapacity() (domain logic, not in Controller).
  • Asks the domain to create the registration: reg = schedule.createRegistration(capacity) or registrationService.create(dept, year, term, nStudents).
  • Returns confirmation reg.id to the UI, which displays it.

Sequence sketch:

:Actor -> :UI : submitRegistration(deptCode, year, term)
:UI -> :RegistrationHandler : createRegistration(deptCode, year, term)
:RegistrationHandler -> :DepartmentCatalog : getDepartment(deptCode) : Department
alt [dept found]
  :RegistrationHandler -> :Department : getSchedule(year, term) : Schedule
  :RegistrationHandler -> :Schedule : createRegistration(capacity) : Registration
else [not found]
  :RegistrationHandler --> :UI : error("unknown department")
end

Key points: The UI component does not process the message; it forwards to the Controller, which calls domain methods in sequence. This refinement can be made by revisiting use cases from the presentation layer perspective so development stays aligned — each SSD system event gets exactly one Controller handler, and each handler's sequence diagram shows delegation to Experts (Department knows its schedules, Schedule knows its registrations).

Sense-check: A second UI form (mobile app) can call the same createRegistration handler without duplicating business logic. If the validation rule changes, only the Controller and its domain collaborators change, not every UI.

10.7.5 Student Questions and Answers

Q: Why should a GUI component not have the responsibility of handling a system event? Why do we need a separate Controller class?

A: Placing execution in the GUI makes that GUI hard to reuse and ties business logic to a specific screen widget. Keeping the UI focused on its own purpose — presenting and capturing — and letting the first non-GUI Controller receive the event preserves separation of concerns and avoids undesirable coupling between presentation and domain layers. Coupling and cohesion as the yin and yang of design explain why this matters: GUI-coupled logic increases coupling and lowers cohesion of both layers. A Controller decouples them so the domain logic can be tested and reused without a widget.

Q: There are several candidate Controllers for system events such as a system handler, item handler, or use-case handler. How do we choose?

A: Any of them can be chosen when fewer events are involved — a single facade Handler works and is simplest. When the number of events grows beyond about five or six, splitting into use-case or role-based Controllers is preferred so state for that use case can be maintained and no single Controller becomes overburdened (the bloated Controller trap). The approach is to reuse analysis work (use cases and roles) and assign incoming events to the appropriate Controller so coordination remains clear. In code, each Controller is often an application service or handler class; the choice is visible in its name (ProcessSaleHandler vs SystemHandler).

10.7.6 Industry Applications

Compiler as a facade Controller illustrates encapsulation of a multi-component process behind one user-visible command (cc/gcc), directly analogous to a facade application service hiding domain complexity from a UI. Session-heavy interactions, such as complex use cases maintaining many variables (shopping checkout with cart state), map naturally to use-case Controllers; role-specific entry points (admin vs student vs department head portals) map to role-based Controllers. In web architectures, MVC frameworks instantiate this pattern — the web controller receives the HTTP request (system event) and delegates to domain services.

10.7.7 Exam Notes

Exam note: Be ready to justify why system events belong to a domain-layer Controller rather than a GUI object, citing coupling, cohesion, and separation of concerns with a concrete example (e.g., button vs handler). Know the three Controller forms (facade/packet, use-case, role-based) and the about five-to-six event threshold that suggests moving from a facade to use-case or role-based Controllers, and be able to name the Controllers or handlers accordingly (e.g., ScheduleSeminarHandler). Use a sequence diagram to show UI → Controller → Domain delegation.

Exam note: Revisit presentation-layer use cases and show how to assign system events to Controllers with delegation, not with interface-embedded logic. Expect to diagnose a bloated Controller and propose a split.

Recap + Bridge: Controller is the answer to "who hears the outside world first?" — a non-GUI handler that receives the system event and orchestrates Experts without doing their work. It keeps the interface reusable and the domain testable. → Next: how to judge whether those orchestration choices are actually good — via cohesion, coupling, and the remaining GRASP guidance.

10.8 Cohesion, Coupling, and the Remaining GRASP Guidance

10.8.1 Concept Overview

Hook: Two assignments can both look "correct" — each uses a plausible Expert or Creator. How do you pick the better one? Measure two qualities that move in opposite directions: how focused each class is, and how entangled the classes are.

Two qualities are used to judge assignment decisions across all previous patterns: high cohesion and low coupling. They are the yin and yang of modular design — you cannot improve one in isolation without watching the other.

High cohesion — "does one thing well":

High cohesion means each object does a single, well-focused job; the class represents one meaningful abstraction with closely related responsibilities. Informally, cohesion measures how functionally related the operations and data of a software element are, and how much work the element is doing. A class with one clear purpose — Sale managing totals and line items — is highly cohesive. A class with 100 methods spanning UI, persistence, and calculations — Big with 2,000 SLOC — is low cohesion because its responsibilities are unrelated.

High cohesion is evaluated alongside amount and relatedness: a small class with ten methods all about one concept (e.g., SalesLineItem knowing quantity, price, subtotal) is more cohesive than a large class with many methods covering different concerns, even if both have similar size. Cohesion supports encapsulation — behavior and data stay together — and tends to make classes understandable, testable, and reusable.

Low coupling — "depends on few":

Low coupling means low dependence among objects, expressed through leaner connections, narrower interfaces, and fewer assumptions about each other's internals. Coupling informally measures how strongly one element is connected to, has knowledge of, or depends on other elements. If A calls on B's services, A is coupled to B; if B's interface changes, A may break. Lower coupling reduces the ripple effect of change — when the depended-upon element changes, fewer dependents are affected.

In object design terms, coupling arises from associations, visibility, message dependencies, and shared assumptions. Assigning a responsibility to the class that already holds the needed data (Expert) often also yields lower coupling, because no new dependency is introduced to fetch that data from elsewhere. The earlier Board-vs-Dog example in T1 makes this concrete: giving getSquare(name) to Board (which already aggregates Squares) means only Board is coupled to Square; giving it to Dog means both Dog and Board are coupled to Square, so total coupling is higher.

Why they are yin and yang:

Often, bad cohesion and bad coupling go hand in hand. A low-cohesion god class that does many jobs necessarily collaborates with many other classes, increasing coupling. Conversely, trying to reduce coupling by splitting a cohesive concept across many fragments can destroy cohesion. Good design raises cohesion (focus each class) and lowers coupling (minimize dependencies) together, pushing toward modularity — a decomposition where each module can be understood, changed, and reused independently.

Modularity in turn aids maintenance, reuse, and often improves execution considerations such as time and memory through lower complexity — fewer paths, clearer interfaces. A good design is also described in the lecture as one that yields a quality product on time and within cost while remaining extensible for future requirements — cohesion and coupling are the concrete, reviewable proxies for that abstract goal.

Both are treated as thought patterns or design guidelines for software design, not as concrete Gang of Four solutions — they are evaluative principles you apply to judge an assignment after you have a candidate.

Visual intuition — coupling vs cohesion seesaw: Imagine a scatter plot where the x-axis is coupling (left = low, right = high) and the y-axis is cohesion (bottom = low, top = high). A desirable design sits in the upper-left quadrant (high cohesion, low coupling). A god Controller with many responsibilities sits in the lower-right (low cohesion, high coupling) — visually far from desirable. Refactoring by moving a responsibility from the god to the correct Expert moves the point diagonally toward the upper-left — one arrow per move. Takeaway: each responsibility shift should be judged by its movement on this plot.

Scope: Use High Cohesion and Low Coupling as evaluation criteria for any responsibility assignment, not as creation patterns themselves. Apply them after Expert/Creator/Controller propose candidates to choose between alternatives. Assumption: The system benefits from modularity — true for most long-lived software. For throwaway scripts, the overhead of splitting may not pay off, but for products, modularity is assumed valuable.

Pitfall — chasing low coupling by hiding real needs: Beginners create an Indirection layer for everything "to reduce coupling" and end up with many pass-through classes that add indirection cost without benefit. Coupling should be low, not zero — some coupling to the domain is necessary. Remove unnecessary coupling only.

Pitfall — equating cohesion with "small class": A class with two unrelated methods is still low cohesion even if small; a class with twenty closely related methods (e.g., a Matrix with many operations that all manipulate the same data) can be highly cohesive. Judge by relatedness, not just size.

Pitfall — forgetting coupling is about change impact: Low coupling is not just "few imports." It is "if B changes, how many are affected?" A class coupled to a stable, rarely changing API is less problematic than one coupled to a volatile internal class, even with the same import count.

Pitfall — letting persistence or utility concerns lower cohesion: Adding saveToDB() to Sale lowers Sale's cohesion (now it is both a domain calculator and a database gateway) and increases coupling to DB APIs. This is the same separation-of-concerns exception that justified keeping persistence apart in Expert.

10.8.2 Additional GRASP Patterns in Preview

Intuition — the rest of the toolkit: Think of the five patterns already mastered (Expert, Creator, Controller, Low Coupling, High Cohesion) as the hand tools. The remaining four are power tools for more nuanced situations — you reach for them when the hand tools leave a specific force unresolved.

Where the analogy breaks: Power tools are not "stronger" — they solve different shapes of problem, not bigger ones.

The remaining GRASP patterns build on the same assignment logic and are previewed for the next session:

  • Polymorphism — When alternatives or behaviors vary by type, assign responsibility to the type for which the behavior varies, often through an interface or abstract superclass. Example: different Payment subclasses each know how to authorize() themselves.
  • Indirection — To avoid direct coupling between two elements, assign responsibility to an intermediate object that mediates between them. Example: a PersistenceManager between Sale and the database, or an Adapter between a domain object and an external service. The lecture singles this out as more difficult because it intentionally adds a layer.
  • Pure Fabrication — When no domain object is suitable (assigning there would destroy cohesion or raise coupling), invent a new non-domain class solely to achieve cohesion and low coupling. Example: a QuantityDiscountCalculator fabricated to hold discount rules that do not belong in Sale or ProductSpecification.
  • Protected Variation — Identify points of predicted variation or instability, and assign responsibilities to create a stable interface around them so change does not ripple. This is the GRASP expression of Open-Close and information hiding. Example: wrapping an external payment gateway behind a stable PaymentGateway interface.

Indirection and Controller are noted as more difficult members of the full set precisely because they introduce or manage layers rather than placing a method on an obvious data holder. All nine together form the responsibility-assignment guidance to be read and practiced. Other broad principles mentioned to study alongside GRASP include Open-Close Principle (open for extension, closed for modification) and Liskov Substitution (subtypes substitutable for supertypes), which later appear as Protected Variation in practice.

Comparison — how GRASP supplements Expert/Creator/Controller:

Situation after initial assignment What to try next
Alternatives vary by type (e.g., payment kinds) Polymorphism — let each subtype handle its case
Direct coupling would tie stable to volatile Indirection — insert a mediator
No domain class wants the responsibility without losing cohesion Pure Fabrication — invent a cohesive helper
A point of change is predicted (external API, rule) Protected Variation — shield it behind an interface

10.8.3 General Guidance for Learning Good Designs

Good design is learned by studying good designs, not by memorizing definitions. The suggestion emphasized in the lecture is to work through at least four or five case studies, examine original solutions, and apply standard rules while designing — cover the answer, attempt the assignment, then check which GRASP principle justifies the textbook's choice. Working problems directly and producing original solutions is emphasized over passive reading. Learners were asked to practice a few interaction diagrams and to come prepared having read the GRASP material.

The mindset is iterative: draw a collaboration, apply Expert/Creator/Controller, evaluate with Low Coupling and High Cohesion, then refine. Over time, the principles become reflexive — what initially requires deliberate reasoning becomes the "it feels right because low coupling" intuition of an experienced designer. That is exactly the transition GRASP is designed to accelerate.

Q: What is the takeaway for building high-quality modular designs?

A: Keep objects highly cohesive (one focused responsibility, data and behavior together) and keep dependencies low (lean interfaces, few assumptions), separate concerns such as persistence from domain behavior, and let delegation and coordination carry the work across lightweight collaborators rather than concentrating it in one heavy class. This supports reuse, easier maintenance, and clearer opportunities for future protection against variation. In short: distribute work by expertise, connect through narrow negotiated interfaces, and shield predicted change.

10.8.4 Industry Applications

Modularity through high cohesion and low coupling underpins large-scale software architecture across domains, including three-tier system organization that separates presentation, domain, and data tiers — each tier is a highly cohesive layer with low coupling to neighbors via defined interfaces. Indirection and protected variation are noted as the more nuanced GRASP ideas to explore for shielding a design from change, appearing as adapters, facades, and plug-in architectures in product lines.

10.8.5 Exam Notes

Exam note: Expect to discuss coupling and cohesion, define each in one precise sentence, and explain with an example how an assignment decision raises one or lowers the other — for instance, moving getSquare(name) from Dog to Board lowers coupling (one holder vs two) and raises cohesion of Board. Review the full set of nine GRASP names and understand which ones introduce more nuanced trade-offs such as Indirection and Protected Variation. Draw the coupling–cohesion quadrant and place a proposed design on it as justification.

Exam note: Practice drawing diagrams for a small scenario, then evaluate them with cohesion and coupling arguments — this is a common exam construction-and-critique format. Be ready for state information and statecharts including states such as ready and working and transitions driven by events, where a use-case Controller holds the state.

Recap + Bridge: Low Coupling and High Cohesion are not assignments themselves but the lenses that tell you whether an assignment is good — focused classes, thin connections, and isolated change. Together with Expert, Creator, and Controller they handle most assignments; the remaining four GRASP patterns handle the nuanced cases of variation and mediation. → With those lenses clear, the lecture's full loop closes: from analysis-inspired design, through messages and visibility, to justified collaboration — ready to be applied end to end in the next session.

Exam Guidance Summary

How to use this summary: This section distills the lecture's directly examinable moves into a checklist. For each item, be ready to both do the task (e.g., draw a diagram) and justify it (e.g., cite the GRASP principle). Where a threshold like "five or six events" is given, examiners expect you to apply it, not just recall it.

Core exam moves from this lecture:

  • Responsibility justification: Every assignment must be justified with a named guideline or pattern, not with intuition alone. State the pattern, the information held, and the coupling/cohesion consequence in one sentence.
  • Interaction diagrams — comparison and construction: Be able to identify and compare synchronous versus asynchronous messages, including arrow notation (filled vs open) and relevance to multi-threading. Draw interaction designs in both sequence and collaboration (communication) forms, use legal numbering (1:, 1.1:, 1a/1b for mutual exclusion, * for iteration), show conditional (opt/alt), loop (loop), and parallel (par) fragments, and use ref frames to split large use cases.
  • Visibility and scope: Define visibility and scope, distinguish global, local, parameter, and attribute access with a code snippet for each, and explain why a message can only be sent where visibility exists. Show a visibility transformation such as parameter → attribute in a constructor.
  • Knowing vs doing: Separate knowing responsibilities from doing responsibilities with concrete examples of attributes, collaborators, get and set, compute, inform, delegate, and coordinate. Place them correctly on CRC-style reasoning.
  • Expert — sale total and its exception: Work the sale total and subtotal reasoning fluently: per line via SalesLineItem + ProductSpecification, synthesis via in Sale, with messages , , . Also explain why persistence is excluded from Expert via separation of concerns — Sale has the data but a persistence service does the saving to preserve cohesion and low coupling.
  • Creator — containment test: For creation questions, test for containment or aggregation (composite ), close use, recording of instances, and possession of construction data, and be ready to propose methods such as with a static aggregation diagram and a dynamic creation arrow («create», {new}).
  • Controller — placement and split: For Controller questions, assign system events (from the SSD) to the first non-GUI Controller, keep the GUI free of business logic, choose among facade/packet (system), use-case, and role-based Controllers, and apply the about five-to-six event guideline to avoid a bloated Controller. Revisit use cases with the GUI in mind and show UI → Controller → Domain delegation.
  • Coupling and cohesion as evaluation: Review coupling and cohesion as evaluation criteria for any assignment — define each, place a design on the coupling-cohesion quadrant, and explain how a move (e.g., getSquare from Dog to Board) lowers coupling and raises cohesion.
  • GRASP breadth: Read the full GRASP set, with extra attention to Controller and Indirection (the difficult ones), and to breadth principles mentioned such as Open-Close and Liskov Substitution. At least four or five case studies of good designs were recommended as practice — examiners favor students who can reconstruct a textbook case from memory.
  • State and statecharts: State information and state charts, including states such as ready and working and transitions driven by events, were noted as an important UML view connected to use-case state held by a use-case Controller. Be ready to add a simple statechart for a registration or sale lifecycle.

Key Industry Applications

  • Election booth operations → object assignment: Mapping physical roles (queue manager, validator, marking officer, polling officer) to software objects illustrates how domain expertise guides object design. Used in domain-driven workshops to discover objects by role-playing real processes.
  • Gardener analogy → Expert: Giving the task to whoever already holds the needed information grounds the Expert rule in everyday expertise and is used to explain assignment choices in team reviews.
  • Dress, window, and door patterns → pattern reuse: Naming captures variation families in physical design (sari vs jeans, window types) and translates to software pattern reuse — variation is expected, not exceptional.
  • Reverse engineering existing programs → learning route: Reconstructing interaction diagrams from a working codebase to uncover why a design works is a practical learning route for inherited systems and for case-study practice.
  • Compiler as facade controller: A single command (cc/gcc with filename and options) hiding syntax tree creation, syntax checking, and semantic checking exemplifies a facade or packet Controller and appears wherever a complex subsystem is exposed via a simple entry point (application services, APIs).
  • Three-tier and Model-View-Controller organization: Separating presentation, domain, and persistence into layers directly motivates separation-of-concerns decisions such as excluding database handling from domain Experts. Seen in web, mobile, and enterprise architectures where the domain layer remains independent of the UI framework.
  • Sale, SalesLineItem, and ProductSpecification collaboration → lightweight collaboration: Demonstrating how behavior and data stay together across lightweight domain objects while keeping each class focused is the canonical example used to evaluate Expert, Creator, cohesion, and coupling together.
  • Department seminar scheduling → use-case realization: Modeling system events (enterScheduleInfo, createRegistration) as Controller-delegated interactions shows how an SSD scenario becomes an implemented use-case realization — the standard workflow for translating requirements into domain collaborations in iterative development.
  • Sessioned use-case Controllers → stateful coordination: Using use-case or role-based Controllers to hold session state across multiple system events (e.g., multi-step registration or checkout) illustrates how Controller choice handles state and statecharts in real systems.

OODAP Lecture 10 notes · Designing Object Systems with GRASP and Interaction Diagrams

Object Oriented Design, Analysis and Programming Architecture· postgraduate· 2026-08-19

Sections Breakdown

110.1 From Analysis to Design and Responsibility-Driven Design

Analysis inspires design; responsibilities are assigned to information holders (RDD) and justified with named patterns, keeping design focused and communicable.

210.2 Interaction Diagrams and Messages as the Path to Methods

System events expand into object messages; sequence and collaboration diagrams make those collaborations visible and each arrow directly implies a method.

310.3 Visibility, Scope, and Kinds of Responsibility

A message needs visibility; four visibility kinds plus scope govern where messages can travel, while knowing vs doing classifies responsibilities.

410.4 GRASP: General Responsibility Assignment Software Patterns

GRASP names nine responsibility-assignment patterns (five core) as a communicable pattern language for saying who does what and why.

510.5 The Expert Pattern: Assigning Work to the Information Holder

Information Expert assigns a responsibility to the class that already holds the needed data; sale totals are computed by the holders of quantity and price with persistence kept separate.

610.6 The Creator Pattern: Responsibility for Creating Instances

Creator assigns creation to the class that contains, closely uses, or has initializing data for the new instance, keeping coupling low; Sale creates SalesLineItem.

710.7 The Controller Pattern: Coordinating System Events Without Burdening the Interface

Controller receives system events as the first non-GUI object and delegates to domain experts; facade, use-case, and role-based forms prevent bloated interfaces, illustrated via compiler facade.

810.8 Cohesion, Coupling, and the Remaining GRASP Guidance

High cohesion and low coupling are evaluative lenses for any assignment; the remaining GRASP patterns (Polymorphism, Indirection, Pure Fabrication, Protected Variation) handle variation and mediation.

9Exam Guidance Summary

Checklist of examinable moves: justify assignments, draw and evaluate interaction diagrams, reason about visibility and Expert/Creator/Controller with thresholds.

10Key Industry Applications

Industry ties: booth role-play for discovery, facade compilers and three-tier separation, and case-study practice for learning good design.

Postgraduate students in Object Oriented Design, Analysis and Programming

Exam Revision Notes

Below is the distilled, exam-ready core. Every entry comes from the full explanation above. Use this section for rapid review; return to the main notes when a point needs more context.

From Analysis to Design and Responsibility-Driven Design

Must-know: RDD golden rule: give the job to the information holder and justify every assignment with a named pattern, not intuition alone.

⚠️ Top pitfall: Copying analysis objects blindly or justifying by gut feel instead of a pattern.

Self-check: Who should do a job under RDD and why?

Connects to: 10.4, 10.5

Interaction Diagrams and Messages as the Path to Methods

Must-know: Synchronous filled arrow = block and wait; asynchronous open arrow = continue; legal numbering and ref frames keep diagrams readable.

⚠️ Top pitfall: Drawing cluttered diagrams instead of splitting with ref frames or misusing arrow shapes.

Self-check: What does a filled vs open arrowhead mean and when does it matter?

Connects to: 10.3, 10.7

Visibility, Scope, and Kinds of Responsibility

Must-know: Visibility kinds: attribute, parameter, local, global (via Singleton); scope limits where a name is accessible; knowing vs doing separates information from action.

⚠️ Top pitfall: Assuming you can message any object you know exists rather than one you have a reference to.

Self-check: Name the four visibilities and how to promote parameter to attribute.

Connects to: 10.2, 10.5, 10.6

GRASP: General Responsibility Assignment Software Patterns

Must-know: GRASP = General Responsibility Assignment Software Patterns; nine patterns, first five core: Expert, Creator, Controller, Low Coupling, High Cohesion; pattern = named problem+solution+context.

⚠️ Top pitfall: Treating GRASP as replacement for GoF or citing a name without stating what information is held.

Self-check: List the nine GRASP patterns and why naming aids communication.

Connects to: 10.1, 10.5, 10.8

The Expert Pattern: Assigning Work to the Information Holder

Must-know: Expert: give work to data holder; s_i = q_i * p_i via SalesLineItem+ProductSpecification, total = sum s_i via Sale; persistence excluded by separation of concerns.

and

⚠️ Top pitfall: Giving Sale a saveToDB() because it has sale data, or creating an anemic helper that pulls data out to compute.

Self-check: Who computes s_i, who computes total, and why not saving to DB?

Connects to: 10.6, 10.8

The Creator Pattern: Responsibility for Creating Instances

Must-know: B creates A if B contains/aggregates, records, closely uses, or has initializing data for A; Sale makes SalesLineItem via makeLineItem; use Factory for complex creation.

⚠️ Top pitfall: Letting an unrelated helper create just because it can, or forgetting to add the new instance to the aggregate collection.

Self-check: List Creator's four tests and apply to Sale and SalesLineItem.

Connects to: 10.5, 10.8

The Controller Pattern: Coordinating System Events Without Burdening the Interface

Must-know: Controller = first non-UI receiver of system events; UI forwards and delegates; forms: facade (few events), use-case (session state), role-based; split beyond ~5-6 events to avoid bloated controller.

⚠️ Top pitfall: Letting Controller do domain arithmetic or leaving business logic in GUI widgets.

Self-check: Why not handle system events in the GUI and when to split a controller?

Connects to: 10.2, 10.8

Cohesion, Coupling, and the Remaining GRASP Guidance

Must-know: High cohesion = single focused job; low coupling = low dependence; evaluate designs on coupling-cohesion quadrant; remaining four: Polymorphism, Indirection, Pure Fabrication, Protected Variation.

⚠️ Top pitfall: Creating indirection layers everywhere to chase zero coupling or judging cohesion by size alone.

Self-check: How does moving getSquare from Dog to Board affect coupling and cohesion?

Connects to: 10.4, 10.5, 10.7

Exam Guidance Summary

Must-know: Be able to justify every assignment, draw sequence/collaboration with legal numbering, and apply Expert/Creator/Controller thresholds.

⚠️ Top pitfall: Reciting pattern names without stating what information is held or where state is kept.

Self-check: Map an SSD system event to its controller and domain delegation.

Connects to: 10.1, 10.2, 10.5, 10.6, 10.7

Key Industry Applications

Must-know: Map lecture patterns to real systems: election booth → Expert, compiler → facade controller, three-tier → separation of concerns.

⚠️ Top pitfall: Treating industry examples as decoration rather than as architecture drivers.

Self-check: Name a real system for each of Expert, Creator, Controller.

Connects to: 10.1, 10.5, 10.7

Was this lecture useful?

Loading comments…
🤖

BitsNotes AI Assistant

Subject Notes Assistant

Configure AI Chat

Choose how to access the chatbot
Have your own API key?

Switch to "Bring Your Own Key" tab above for unlimited access with any OpenAI-compatible provider.

🔑 Enter API key above to fetch live models from provider, or enter model name manually.
OpenAI-Compatible API Support

Choose any provider preset (Gemini, DeepSeek, Kimi, GLM, MiniMax, Qwen, OpenAI, Groq, Ollama, etc.) or enter a custom endpoint URL.

Security & Privacy First

Your API key is sent directly from your browser to your specified provider. BitsNotes servers never store or see your key.