25-Comp-A6 Software Engineering · December 2014
Nivaar worked solution (AI-drafted; not reviewed by a licensed engineer)
National Exams — December 2014 — 98-Comp-A6 Software Engineering. Three-hour, closed-book exam, no calculator permitted. Format: ten questions, candidates answer any six (all questions equal weight — each question carries 20 marks, so the paper is marked out of 120; only the first six questions as they appear in the answer book are marked). All ten questions are solved below for completeness.
Reference texts: Sommerville, Software Engineering (10th ed., Pearson) — software process models, object-oriented and function-oriented design, real-time systems, software testing, configuration management, dependable/critical systems, reliability engineering, component-based software engineering; Pressman, Software Engineering: A Practitioner's Approach (9th ed.) — supplementary process/testing/quality coverage; IEEE/ISO 12207 — software life-cycle processes; SWEBOK — body-of-knowledge cross-reference.
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.
A single-threaded program has a single thread of control: for a given input, it always follows exactly one, deterministic sequence of statement executions. This has two direct consequences for validation. First, any failure found during testing is reproducible — re-running the same input reliably re-creates the same execution path and the same failure, which is what makes systematic debugging and regression testing possible in the first place. Second, the space of behaviours that must be tested is, in principle, enumerable from the program's input domain and its (finite) set of control-flow paths, so structural testing techniques (path coverage, branch coverage) can meaningfully claim to have exercised "most" of the program's behaviour.
A design involving multiple threads loses both properties. The actual order in which operations from different threads interleave at run time depends on scheduler decisions, relative timing, and system load — factors outside the program's own logic — so the same inputs can produce different interleavings, and therefore potentially different outcomes, on different runs. A defect that depends on one specific interleaving (a race condition on shared data, a deadlock that only occurs when two threads acquire locks in a particular order) may simply not occur again when the test is re-run, making such failures notoriously hard to reproduce and debug. Worse, the number of distinct interleavings grows combinatorially with the number of threads and the number of operations each performs — even a handful of threads with a handful of steps each can produce many thousands of distinct legal interleavings — so exhaustively enumerating and testing every possible interleaving quickly becomes computationally infeasible, unlike the single-threaded case where the path space, while it can still be large, is at least fixed and does not additionally depend on run-time scheduling.