NivaarExam PrepOfficial exam papers ↗

25-Comp-B11 Advanced Software Design · May 2016

Question 8 of 28: Design by Contract vs. Defensive Programming

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

Notes on this paper

98-Comp-B11 Advanced Software Design — National Exams, May 2016. 3 hours, closed book exam with one aid sheet allowed (written on both sides), no calculator permitted. The paper is organized into five parts, and candidates were instructed to answer any five (5) questions in Part I, any three (3) in Part II, any four (4) in Part III, any two (2) in Part IV, and any five (5) in Part V — only the first questions answered, in each part, as they appear in the answer book are marked. All questions carry equal weight, so the 19 questions actually marked (5+3+4+2+5 of 28) each count for 100/19 ≈ 5.26% of the paper. All 28 questions are answered below for completeness.

Reference texts: Sommerville, Software Engineering (10th ed., Pearson) — software processes, requirements engineering, agile methods, design principles, dependability; Pressman, Software Engineering: A Practitioner's Approach (9th ed.) — supplementary process and quality coverage; Gamma, Helm, Johnson & Vlissides (GoF), Design Patterns: Elements of Reusable Object-Oriented Software — creational/structural/behavioural pattern catalogue (Singleton, Proxy, Template Method, Observer, etc.); Sebesta, Concepts of Programming Languages (12th ed.) — polymorphism, dynamic binding, inheritance and language-level object semantics; Bertrand Meyer, Object-Oriented Software Construction — design by contract, preconditions/postconditions/invariants, the open–closed principle; Barbara Liskov's 1987 substitutability paper for Question 11; Rogers, Sharp & Preece, Interaction Design, and Nielsen, Usability Engineering, for Question 21's HMI-specific non-functional requirements; Myers, The Art of Software Testing, for Question 28's boundary value analysis.

PART I — General Principles (answer any 5 of 7)

PART II — Design by Contract (answer any 3 of 5)

Question 8: Design by Contract vs. Defensive Programming (Part II)

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.

Both aim to keep an operation's behaviour correct in the presence of possibly-invalid input, but they place the RESPONSIBILITY for ensuring validity on opposite parties.

Design by Contract (DbC) makes the CALLER responsible for satisfying an operation's precondition (Question 10). The supplier is entitled to assume the precondition holds and need not re-check it defensively; a violated precondition is treated as a bug in the caller, not a normal input the supplier must gracefully handle. Contracts are typically verified only via debug-mode assertions (which can be compiled out in production), since a violation signals a programming error to be fixed during development, not a runtime condition to recover from.

Defensive programming makes the SUPPLIER responsible: it does not trust callers to honour any implicit obligation, so it validates and sanitizes every input itself, at every call, regardless of what the caller was "supposed" to guarantee, and handles invalid input gracefully (returning an error code, throwing a well-defined exception, substituting a safe default) rather than assuming correctness.

Example (Stack.pop()). Under DbC: the precondition is !isEmpty(); the implementation does not explicitly re-check emptiness in the production build (only via an optional debug assertion) — calling pop() on an empty stack is the caller's bug. Under defensive programming: pop() explicitly checks isEmpty() first and, if true, throws a documented EmptyStackException (or returns an Optional) every single time, in every build, regardless of whether the caller was expected to have checked already.

When each is appropriate. Defensive programming is essential at a system's TRUST BOUNDARY — public APIs, user input, data from external systems — where the caller cannot be assumed to honour any contract at all. DbC is more appropriate for internal, tightly-coupled code within one team/module, where redundant defensive checks on every internal call both waste runtime and duplicate validation that a contract already documents as the caller's job. Good practice combines both: defend rigorously at the boundary, and rely on documented, assertion-checked contracts internally.