4.1.2.1–4.1.2.2 - Procedural design and hierarchy charts (Java)
Learn how to break a program into cooperating jobs, describe their interfaces and use a hierarchy chart to organise a design. Compare organising work around procedures with organising it around objects. This Java route is incomplete: runnable support pending; the source and design tasks are written practice with no Run.
Procedural and object-oriented paradigms
A programming paradigm is an approach to organising a solution. Procedural design centres on subroutines operating on data: a caller carries out a sequence of jobs and passes data between them. Object-oriented design centres on objects that bring related state and behaviour together, with methods acting on that state.
Java permits procedural organisation inside classes. These static methods treat a balance as explicit input:
static int deposit(int balance, int amount) {
return balance + amount;
}
static int addBonus(int balance) {
return balance + 5;
}
A caller assigns balance = deposit(balance, 10); and then balance = addBonus(balance);. The balance is carried by the caller. An object-oriented alternative gives an account its own balance and methods:
class Account {
private int balance;
Account(int openingBalance) {
balance = openingBalance;
}
void deposit(int amount) {
balance += amount;
}
int getBalance() {
return balance;
}
}
Account a = new Account(20); a.deposit(10); leaves that object's balance at 30. A second Account can hold separate state. The next lessons develop constructor, reference and encapsulation details. Here, the distinction is organisation: procedures act on supplied data; objects own related state and expose operations. Both approaches can use sequence, selection, iteration and subroutines. Java's requirement that methods sit in classes does not make every static-method algorithm an object-oriented design.
Procedural decomposition is often clear for a pipeline of calculations. Objects help model entities with persistent independent state and controlled operations. Neither approach removes the need to analyse the requirements or design appropriate interfaces.
Structured design
A structured approach breaks a large problem down into smaller modules with clear responsibilities, then combines their verified results. Top-down design begins with the overall job and repeatedly decomposes it until each lower-level job is small enough to implement. Sequence, selection and iteration express the control flow inside modules.
For a ticket report, first separate reading sales, calculating revenue and displaying the result. Next refine the calculation into choosing category prices and summing the contributions. Decide an interface for each module: readSales() could return sales data; calculateRevenue(...) accepts the data and returns a total; displayReport(int revenue) presents it. This avoids a calculation secretly reading a global total left by another job.
A useful module has a coherent purpose rather than doing several unrelated tasks. Keeping price lookup separate means a price change is made in one place. Keeping output outside the calculation lets tests inspect the returned number without parsing printed text. A team can implement separate modules once their interfaces are agreed; integrating incompatible assumptions remains a risk, so document types, units and preconditions.
Testing proceeds at two levels. A unit check can verify one module with known inputs; an integration check verifies that the modules exchange the right values and produce the full report. For example, price lookup might return 8 for an adult while the summation expects pounds, not pence. Passing the right type alone cannot detect that unit mismatch. Structured design reduces complexity, improves testing and localises changes, but only when responsibilities and contracts are coherent.
Continue this lesson.
You’re previewing NovaLearn without an account. Create a free account to read the rest.
Create free account