NivaarExam PrepOfficial exam papers ↗

25-Comp-A6 Software Engineering · December 2018

Question 3 of 8: Object-Oriented Design

Nivaar worked solution (AI-drafted; not reviewed by a licensed engineer)

Notes on this paper

National Exams — December 2018 — 17-Comp-A6 Software Engineering. Three-hour, closed-book, no-calculator exam. Format: eight questions, candidates answer any five of the eight (all questions equal weight — each of the five counted questions is worth 20%; only the first five questions as they appear in the answer book are marked). All eight questions are solved below for completeness.

Reference texts: Sommerville, Software Engineering (10th ed., Pearson) — software process models, object-oriented and function-oriented design, requirements engineering, software testing, software reuse, software reliability, client-server architectures, software verification and validation; Pressman, Software Engineering: A Practitioner's Approach (9th ed.) — supplementary process, testing and architecture coverage; Gamma, Helm, Johnson & Vlissides, Design Patterns — object-oriented design/reuse vocabulary.

Question 3: Object-Oriented Design (20 marks)

Question text not reproduced: the examination questions are © Engineers and Geoscientists BC. Open the official past paper (linked at the top of this page) to read the question, then follow the worked solution below.

Candidate Objects and Their Responsibilities

Applying Sommerville's object-identification approach (identify objects from the noun phrases in the description, assign each one attributes and the operations/services it must provide, then model how the objects collaborate) to the scenario yields the following object classes:

ObjectAttributesOperations (services)
TicketMachine (session controller)currentStatestart(), abortSession(), reset()
DestinationMenudestinations[] (list of Destination)display(), selectDestination(input) → Destination
Destinationname, faregetFare()
CreditCardReadercardNumber, expiryDatereadCard(), ejectCard()
CardCompanyGateway (boundary object to the external card network)—verifyCard(cardNumber) → bool, chargeAccount(cardNumber, amount) → bool
PINPadenteredPINpromptForPIN(), capturePIN() → pin
RailTicketdestination, fare, issueTimestampissue(), print()
DisplaycurrentMessageshowMessage(text)

Each of these is a genuinely cohesive unit — DestinationMenu only knows about presenting and resolving a destination choice, CardCompanyGateway only knows about the two remote-verification operations, and so on — consistent with the cohesion/coupling principle discussed in Question 2(a): none of these objects needs to know how another is internally implemented, only the small interface (the operations listed) that it calls.

Object Interaction: The Session State Machine

Because the system is fundamentally an interactive, sequential transaction (menu → card → PIN → ticket), the cleanest way to model how the objects collaborate over time is a state-transition diagram owned by the TicketMachine controller object, which invokes the other objects' services as it moves between states.

IdleShowingDestinationMenuAwaitingCredit CardValidatingCardAwaitingPINValidating PIN& ChargingIssuingTicketReject Card(eject)RejectTransactionstartdestinationselectedcardinsertedcard validPINenteredPIN & chargeauthorizedticket printed, card returnedcard invalidPIN/chargedeclinedabortabortFig. Q3 — state-transition model of the TicketMachine controller object driving the rail-ticket-issuing session.

On start(), TicketMachine asks DestinationMenu.display() to present the list of destinations via Display; once selectDestination() resolves an input to a Destination object, control moves to awaiting a card. CreditCardReader.readCard() captures the inserted card's number and expiry, and TicketMachine calls CardCompanyGateway.verifyCard() to check it — note the source's wording distinguishes this initial validity check (format/network-level, "its validity is checked") from the later step where "the credit card has been validated" only after the PIN is also confirmed, so the design treats card verification and PIN/charge authorization as two separate remote calls to CardCompanyGateway rather than one. A card that fails the first check is ejected immediately by CreditCardReader.ejectCard() with no PIN ever requested. A card that passes moves the machine to PINPad.promptForPIN() / capturePIN(); the captured PIN together with the destination's fare (from Destination.getFare()) is sent as a single authorization request to CardCompanyGateway.chargeAccount(), which both confirms the PIN against the card and reserves/charges the fare in one remote exchange. Only when that call succeeds does TicketMachine call RailTicket.issue() and print(), then return to Idle via CreditCardReader.ejectCard() returning the card together with the printed ticket. A decline at either the card-verification or the PIN/charge-authorization step routes to a reject state that ejects the card, shows an explanatory message via Display, and returns to Idle without ever creating a RailTicket.

Check — assumptions
Single-user, single-machine system (no concurrent sessions to reason about). The two card-network exchanges (verify, then charge) are each assumed synchronous from the machine's point of view, consistent with an unattended kiosk that cannot proceed until it has an authoritative answer. A destination has a single fixed fare (no distance-banding or discount logic, since none is described in the source). The machine is assumed to time out back to Idle (not modelled explicitly above) if a user abandons a session mid-transaction without the card being ejected by an explicit decline.