NivaarExam PrepOfficial exam papers ↗

25-Comp-A6 Software Engineering · December 2013

Question 6 of 9: Software Reuse

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

Notes on this paper

National Exams — December 2013 — 98-Comp-A6 Software Engineering. Three-hour, closed-book exam, no calculator permitted. Format: nine questions, candidates answer any five of the nine (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 nine 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, rapid development and prototyping, client-server architectures, software 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 6: Software Reuse (a) 10, (b) 10 — 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.

(a) Information-Hiding and Inheritance in Support of Reuse

Information-hiding encapsulates a component's internal representation and implementation behind a well-defined public interface, so that other components interact with it only through that interface and never depend on how it is implemented internally. This supports reuse because a client can safely reuse a component without understanding, or accidentally depending on, its internals — and the component's implementation can later be changed (a different internal data structure, a performance optimisation) without breaking any client, since the interface contract is preserved. Inheritance lets a new class be defined as a specialization of an existing class, automatically acquiring its attributes and operations and optionally overriding or extending a subset of them. This supports reuse because common behaviour needs to be implemented only once, in a general (often abstract) base class, and every specific variant reuses that implementation by extending it rather than re-implementing it from scratch — only the genuine differences between the general case and the specific case need new code. Together, the two mechanisms make an OO reuse library economically viable: information-hiding makes each reusable component safe to depend on without fear of hidden coupling, and inheritance makes it cheap to adapt a general component to a slightly different specific need.

(b) Reusable Interfaces for Stack and String

A reusable interface hides representation entirely (array-backed vs. linked-list-backed stack are interchangeable behind the same interface) and, where the language supports it, is parameterized by element type so the same interface serves every element type rather than being rewritten per type.

// Generic Stack ADT interface - representation-independent, reusable for any element type
interface Stack<T> {
    void push(T item);      // add item to the top
    T pop();                // remove and return the top item; error if empty
    T peek();                // return (without removing) the top item; error if empty
    bool isEmpty();
    int size();
}

// String ADT interface - immutable value type, representation-independent
interface StringADT {
    int length();
    StringADT concatenate(StringADT other);   // returns a new StringADT; does not mutate either operand
    StringADT substring(int start, int end);  // returns the substring [start, end)
    char charAt(int index);
    bool equals(StringADT other);
}

Both interfaces expose only the operations a client needs and say nothing about how the data is stored: Stack<T> could be backed by a dynamic array or a linked list without any client code changing, and StringADT could be backed by a character array, a rope, or a reference-counted immutable buffer. The generic type parameter on Stack<T> is itself a reuse mechanism in the same spirit as inheritance from part (a): one interface (and, typically, one concrete implementation) is written once and reused for every element type, rather than writing a separate IntStack, StringStack, and so on.