This was written entirely with AI.
These notes cover Lecture 12 (System Design) and Tutorial 6 Q1. Requirements and analysis describe the problem. Design describes the solution. This part is the first level, system design: the large parts of the system and how they connect (the software architecture). Part 10 goes down to the classes inside each part. In the exam this is Q3(a): name the one non-functional requirement (Part 2), propose an architecture, draw a detailed class diagram, and propose an alternative architecture for the NFR (8 marks for each of the last two).
How to use this page. Each section teaches one idea in a few lines, then gives concept checks. Tutorial 6 Q1 is in section 8, with the method for the class diagram. Past-paper questions are not on this page: use the original papers.
Quick reference
| Fact | Value |
|---|---|
| Architecture | {components, connectors}. Abstract. About structure and interactions. |
| Why it matters | It sets most of the non-functional qualities: performance, availability, security, scalability, maintainability. Costly to change later. |
| Inputs to an architecture | Functional requirements (what) · non-functional requirements (why this design) · design principles (how to be good) · patterns and styles (how others did it) · constraints |
| Principles | Single responsibility · separation of concerns · high cohesion, low coupling · open–closed · program to an interface · composition over inheritance · encapsulate what varies · least knowledge · DRY · modularity |
| Styles | Layered · client–server · data flow (pipe-and-filter, batch sequential) · data-centred (repository, blackboard) · event-based · virtual machine · call and return · MVC |
| Three layers | Presentation (boundary) · application logic (control) · persistent data (entity). Dependencies go down only, to the next layer. |
| Layers: benefits | Separation of concerns · low coupling · changeability · easy maintenance |
| Layers: drawbacks | Performance overhead · up-calls break the rule (use Observer) |
| Detailed class diagram | Name the architecture and justify it · layers · classes in layers · typed attributes and methods · UI → controller → entity · no boundary → entity · interfaces where flexible |
| NFR → alternative | many users → replicated servers with a load balancer · always available → redundant servers · real-time updates → event-based or MVC · security → a security layer · extensibility → interfaces + Strategy + Factory · many UIs → MVC |
1. From the problem to the solution
Requirements elicitation and analysis describe the problem. Design describes the solution. Design has two levels:
- System design decides the software architecture: the large parts of the system and how they connect.
- Object design (Parts 10–11) decides the detailed classes, interfaces and design patterns inside each part.
The analysis model (boundary, control and entity classes) is the input to system design.
Each SDLC activity produces a model. Each model builds on the model before it:
| Activity | Model it produces |
|---|---|
| Requirements elicitation | Use case model |
| Requirements analysis | Analysis model: problem-domain objects (boundary, control, entity) |
| System design | Software architecture: subsystems |
| Object design | Design model: solution-domain objects (detailed classes) |
| Implementation | Source code |
| Testing | Test cases that verify the code against the requirements |
2. Why architecture matters
Software systems become larger in every way: more code, more users, more developers, a longer life (often decades) and more versions. The technology and the hardware also change. At the same time, the budget is limited, the schedule is tight, and the system must be easy to maintain.
The architecture decides most of the non-functional qualities of a system:
- performance;
- availability;
- security;
- scalability;
- extensibility and maintainability.
A wrong architecture is very costly to change later, because every part of the system depends on it.
3. What a software architecture is
Software architecture describes the elements from which systems are built, the interactions among those elements, the patterns that guide their composition, and the constraints on these patterns. (Shaw and Garlan, 1996)
In short: Software architecture = {Components, Connectors}.
- A component is a unit of software that does a function at run time. Examples: programs, objects, processes, clients, servers, databases.
- A connector is an interaction between components: communication, coordination or cooperation. Examples: shared variables, procedure calls, remote procedure calls, communication protocols, data streams.
An architecture is:
- abstract — it hides the details of the components and connectors;
- about structure and interactions — it shows the topology, the components, and the data and control flow between them;
- purposeful — it lets the team show and analyse important properties, and it documents design knowledge for other people.
What is a component, and what is a connector? Give two examples of each.
A component is a unit of software that does a function at run time (a program, object, process, client, server or database). A connector is an interaction between components: communication, coordination or cooperation (a shared variable, a procedure call, a remote procedure call, a protocol, a data stream).
4. How to develop an architecture
The large arrow behind the five boxes means that all five feed into one result: the architecture. Read the boxes as five questions that the architect answers. The table below gives each question.
| Input | Question it answers | Examples |
|---|---|---|
| Functional requirements | What must the system do? | Dynamic models, analysis object models |
| Non-functional requirements | Why choose this design over another? | Efficiency, reliability, robustness, security, maintainability |
| Design principles | How do we make a good design? | Modularity, abstraction, open–closed, reuse |
| Design patterns and architectural styles | How have others solved this problem? | Layered, client–server, data-centred |
| Constraints | What limits do we have? | Programming languages, libraries, communication methods |
5. Design principles
| Principle | Meaning |
|---|---|
| Single responsibility | Each class has one reason to change. |
| Separation of concerns | Put different concerns (display, logic, storage) in different parts. |
| High cohesion | All the parts inside one class or module belong to the same task. |
| Low coupling | Classes depend on each other as little as possible. A change in one class does not force changes in many others. |
| Open–closed | Classes are open for extension but closed for modification. You add new behaviour with new classes, not by editing old classes. |
| Program to an interface, not an implementation | Code depends on an interface. Any class that implements the interface can then be used. |
| Favour composition over inheritance | Give an object a part that does the varying work, instead of making many subclasses. |
| Encapsulate what varies | Find what changes and separate it from what stays the same. |
| Least knowledge | A class talks only to its immediate “friends”, not to the friends of its friends. |
| Don’t repeat yourself (DRY) | Each piece of knowledge exists in one place only. |
| Modularity | Split the system into separate modules with clear interfaces. |
Read the pyramid from the bottom up, in the direction of the arrow. Design principles are the base. Design patterns, in the middle, apply the principles to common problems. The result at the top is a good design: maintainable, extensible, scalable, testable and reusable. You cannot get the top without the layers under it: a pattern used without understanding the principle behind it rarely gives a good design.
What is the difference between cohesion and coupling, and which should be high?
Cohesion is how well the parts inside one class or module belong to the same task: it should be high. Coupling is how much classes depend on each other: it should be low, so a change in one class does not force changes in many others.
State the open–closed principle and give one way to follow it.
Classes are open for extension but closed for modification: you add new behaviour with new classes, not by editing old ones. One way: depend on an interface, and add a new class that implements it (this is the base of Strategy).
“Favour composition over inheritance.” What does the principle ask you to do?
Give an object a part that does the varying work, instead of making many subclasses. For example, a Student holds a DeliveryChannel part, instead of having EmailStudent, SmsStudent and PushStudent subclasses.
6. Architectural styles
An architectural style is a pattern for how to organise a whole system. It defines:
- a vocabulary of component types (for example filters, layers, clients and servers);
- a vocabulary of connector types (for example procedure calls, data streams, sockets);
- constraints on how they combine (for example “filters do not share state”, “a layer may call only the layer below it”);
- a way to work out the properties of the whole system from the properties of its parts.
The style does not fix the number of components, the type of each connector, or the exact data. A pipe-and-filter system can have 2 filters or 20 filters.
The figure is a tree. Each brace splits a family into its styles. There are five families: independent components, data flow, data-centred, virtual machine, and call and return. The sections below take them one at a time. Note where the layered system sits: it is a call-and-return style, because each layer calls the layer below and waits for the result.
Layered architecture
The system is a stack of layers. Each layer gives services to the layer above it and uses only the services of the layer below it.
The usual three-layer architecture matches the boundary, control and entity classes:
| Layer | Contains | Stereotype |
|---|---|---|
| Presentation | Screens and interfaces | Boundary |
| Application logic | Use case logic | Control |
| Persistent data | Stored data | Entity |
How to read the figure. It is an emergency-response system. Each red frame is a layer, and the icon in its top-right corner is the stereotype of the classes inside it:
- Presentation (boundary): FieldOfficerUI and DispatcherUI, one screen per human actor.
- App Logic (control): Resource, Map and Incident Management.
- Persistent Data (entity): one Database.
Each dashed arrow is a dependency. Every arrow points down, and every arrow goes only to the next layer. A UI never reaches the Database directly. Several UIs can share one logic class: both UIs use Map Management.
A four-layer version splits the entity layer in two. Business objects are the entity classes in memory, such as an Account or a Booking. Persistent data is the database that stores them. Dependencies still go only downwards: presentation → business application logic → business objects → persistent data. Use it when the stored format should be able to change (another database, files) without a change to the business objects.
The rules for dependencies between stereotypes become rules between layers:
Read the figure left to right. An actor uses a boundary. A boundary calls a control. A control reads and writes entities. The loop on Control means that a control can call another control. The loop on Entity means that entities link to each other through associations. No arrow skips a step: there is no actor → control and no boundary → entity.
Benefits of layers:
- Separation of concerns. Each layer handles a smaller problem.
- Low coupling. A layer knows only the interface of the layer below. It does not know how the lower layer works.
- Changeability. You can replace a whole layer, if its interface stays the same. A web app and a mobile app can share the same logic and data layers.
- Easy maintenance. A change inside a lower layer does not force changes in the layers above.
Drawbacks of layers:
- Performance. Each request passes through all layers. More layers mean more overhead.
- Up-calls. Sometimes a lower layer must tell a higher layer that something changed (for example, data changed and the screen must update). A direct call upward breaks the layer rule. The Observer pattern solves this (Parts 10 and 11).
Client–server
Clients send requests to one or more servers over a network. Servers provide shared services, such as data or computation. Many clients can use one server.
- Good for: many users, shared data, web and mobile access, central security.
- Scalability: add more servers behind a load balancer.
- Risk: the server or the network is a single point of failure, unless servers are replicated.
Data flow: pipe-and-filter and batch sequential
Data passes through a series of processing steps (filters), connected by pipes. Filters do not share state. Good for data transformation, such as compilers and media processing. Batch sequential runs each step on the whole data set before the next step starts.
Data-centred: repository and blackboard
All components share one central data store. Components communicate through the data store and not directly. Good when many tools work on the same data, such as an IDE.
Independent components: event systems
Components do not call each other directly. A component announces an event. Other components that registered for that event react to it (implicit invocation). This is the architecture-level form of the Observer pattern.
| Advantages | Disadvantages |
|---|---|
| Modifiability: computation is decoupled | Components are independent, so one component does not know if another received the message |
| Concurrent execution | Needs complicated protocols to make sure that messages arrive |
| Scalability | Correctness is hard to achieve and to prove |
| Easy integration of new components |
Virtual machine: interpreter and rule-based system
The system runs a program or a set of rules that is not native code. An interpreter runs a script language. A rule-based system applies “if–then” rules to facts. Good when users must change the behaviour without recompiling.
Call and return: main program and subroutine, object-oriented
The main program calls subroutines, or objects call methods of other objects. This is the normal style inside one program.
Model–View–Controller
MVC is an architecture for interactive systems. Part 11 covers it in detail.
In a three-layer architecture, may a UI class call the database class directly?
No. Dependencies go down to the next layer only. A UI calls a controller in the application logic layer. The controller reads and writes the entities in the persistent data layer.
Give two benefits and one drawback of a layered architecture.
Benefits: separation of concerns (each layer handles a smaller problem); low coupling (a layer knows only the interface below); changeability (replace a whole layer if its interface stays); easy maintenance. Drawbacks: each request passes through all layers, which costs performance; a lower layer may need to tell a higher layer about a change (an up-call), which breaks the rule. The Observer pattern solves it.
Give two advantages and two disadvantages of an event-based (independent components) architecture.
Advantages: modifiability (computation is decoupled); concurrent execution; scalability; easy integration of new components. Disadvantages: one component does not know if another received the message; it needs complicated protocols to make sure that messages arrive; correctness is hard to achieve and to prove.
What are the components and connectors in pipe-and-filter, and when is it a good choice?
Components: the filters (processing steps that do not share state). Connectors: the pipes between them (data streams). It is good for data transformation, such as compilers and media processing. Not in the lecture: it fits badly for interactive systems, and a slow filter slows the whole chain.
Where does MVC sit among the styles, and where is it covered?
MVC is an architecture for interactive systems with several views of the same data. Part 11 covers it. In the exam it is the usual alternative to a layered design when a system has many UIs.
7. How designers work
Designers do not find the final design in one step. They:
- understand the requirements and build a model of the problem;
- propose one or more design solutions;
- check each solution against the requirements;
- revise the solution, or look for a new solution, where it does not match;
- compare the solutions and select one;
- work out the selected solution in detail, as a blueprint.
8. From architecture to a detailed class diagram
A frequent exam question: “Propose an architecture and draw a detailed class diagram with key attributes and methods that reflects the architecture.”
Method:
- Choose the architecture and say why. For most systems with a UI, logic and stored data, choose a layered architecture (three layers). For strongly interactive systems with many views of the same data, choose MVC. Give one or two reasons that come from the requirements.
- Draw each layer as a package or a labelled box: Presentation, Application Logic, Persistent Data.
- Put the classes into the layers:
- boundaries in Presentation (one UI per human actor, one interface per external system or device);
- controls in Application Logic (one manager or controller per use case group);
- entities in Persistent Data.
- Give each class key attributes and methods. Attributes: the data from the data dictionary, with types. Methods: the steps from the use case descriptions.
- Draw the dependencies. UI → controller → entity. A controller can also call a device or external-system interface (control → boundary is allowed). A UI never calls an entity directly. Add multiplicities to the entity associations.
- Add interfaces where the design must be flexible
(for example
PaymentMethod,NotificationChannel). This shows “program to an interface”. - Check that no boundary calls an entity directly.
How to read the diagram:
- Three frames, one per layer. Presentation holds the boundaries, Application Logic the controls, Persistent Data the entities.
- Visibility icons. This tool draws visibility as
icons, not signs. A hollow circle means public (
+). A hollow square means private (-). So the UI methods and controller methods are public,isInsideWindow()is a private helper, and every entity attribute is private. - UnlockDoorUI → UnlockController. The UI method
requestUnlock(doorId)callsunlock(guestId, doorId). The controller reads AccessGrant, checks the window withisInsideWindow(), callssendUnlock()on DoorLockInterface and writes ActivityLog. The arrow to DoorLockInterface points up, from control to boundary. That is allowed: a control may call the interface of a device. - GuestAccessUI → AccessController.
submitGrant(...)callsgrantAccess(...), which creates an AccessGrant.revokeAccess(grantId)changes its status. - Associations among the entities. Guest
1 — *AccessGrant: one guest can hold many grants. AccessGrant* — 1Door: each grant is for one door. - Typed attributes. Every attribute has a type
(
startTime: DateTime,isLocked: boolean). The attributes come from the data dictionary. The methods come from the steps of the use case descriptions.
Tutorial 6 Q1: Layers for boundary, control and entity objects
Grain Elevator System (GES)
- Refer to the conceptual model developed in Question 1 of Tutorial #4.
Use proper architectural styles to model dependencies among boundary, control, and entity objects.
(The question says Tutorial #4. The conceptual model is from Tutorial #3, Question 1. This is a slip in the question sheet.)
Concepts: the layered architecture style
A software architecture is the main structure of a system: its parts and how they depend on each other. An architectural style is a known pattern for this structure.
In the layered style, the system is a stack of layers. Each layer gives services to the layer above it and uses only the layer below it. So dependencies go downwards only.
The classes of the conceptual model fit the layers by their stereotypes:
| Layer | Holds | Stereotype |
|---|---|---|
| Presentation | Screens and interfaces | Boundary |
| Application (business) logic | The logic of the use cases | Control |
| Business objects | The data objects in memory | Entity |
| Persistent data | The stored data (a database) | Entity |
This is a four-layer version. The three-layer version joins the last two. The split lets the storage change (another database, files) without a change to the business objects.
Benefits: each layer is a smaller problem; a layer knows only the interface of the one below, so the coupling is low; a whole layer can be replaced. Drawbacks: each request passes through all the layers (performance), and a lower layer sometimes needs to tell a higher one that something changed. A call upwards breaks the rule, and the Observer pattern solves this (Part 10).
Answer
- Presentation layer (boundary classes): GESMainUI, ShipmentInterface, AllocationInterface, ManualAllocationInterface.
- Business App Logic layer (control classes): GESManager, ShipmentManager, AllocationManager, ManualAllocationManager.
- Business Object layer (entity classes): Shipment, Allocation, Grain, Silo.
- Persistent Data layer (entity): Database.
Every arrow points down and goes to the next layer. The screens use the managers. The managers use the business objects. The business objects are stored in the database. No screen touches an entity, and no layer calls upwards.
Two small differences from the conceptual model of Tutorial 3: the figure leaves out DisplayInterface, and it shows Shipment only, not its kinds ArrivalShipment and DepartureShipment.
General method: place the classes in layers
- Name the style and say why. One or two facts from the description (a UI, logic, stored data) justify layers.
- Sort the classes by stereotype: boundary → Presentation, control → Application logic, entity → Business objects, the database → Persistent data.
- Draw the dependencies from the conceptual model, but only downwards, and only to the next layer.
- Check:
| Check | Pass if |
|---|---|
| Direction | No arrow points up |
| Skipping | No arrow jumps over a layer (screen → entity, or screen → database) |
| Boundary rule | No boundary touches an entity |
| Up-call | If a lower layer must tell a higher one, use Observer, not an upward call |
Extension 1.1. The processing plants now get a web portal. Which layers change? Which stay the same?
Answer (Extension 1.1)
Add one boundary, PlantPortalUI, to the Presentation layer. If the portal has a new function (for example, registering for alerts), add one control for it in the Business App Logic layer.
The Business Object layer and the Persistent Data layer do not change. The portal reuses the same objects and the same database. This is the benefit of layers: a new UI does not force a change in the lower layers.
Extension 1.2. Say which of these arrows break the layer rules, and why. (a) ShipmentInterface → Shipment. (b) Silo → ShipmentManager (the silo tells the manager that its level changed). (c) GESMainUI → Database. (d) AllocationManager → Silo. (e) Database → Shipment.
Answer (Extension 1.2)
| Breaks? | Reason | |
|---|---|---|
| (a) | Yes | A boundary touches an entity, and the arrow skips the Business App Logic layer. Go through ShipmentManager. |
| (b) | Yes | It points up, from the Business Object layer to the Business App Logic layer. Use the Observer pattern: the silo is the subject and the manager is an observer, so the silo notifies without knowing the manager. |
| (c) | Yes | It skips two layers. |
| (d) | No | Next layer down. |
| (e) | Yes | It points up. The database does not call the business objects. |
9. Proposing an alternative architecture for a non-functional requirement
Another frequent question: “Identify one relevant non-functional requirement and propose an alternative architecture that addresses it.”
- Pick the NFR that the description stresses most. Look for words such as “real time”, “many users”, “secure”, “must always be available”, “notify”.
- Explain why the first architecture is weak for that NFR.
- Propose a style that fixes it, and explain how.
| NFR in the description | Weakness of a simple layered design | Alternative |
|---|---|---|
| Scalability (many users, peak load) | One server handles all requests | Client–server with several replicated servers and a load balancer |
| Availability (must always work) | One server is a single point of failure | Client–server with redundant servers and a replicated database |
| Real-time updates and notifications | Lower layers must call up to the UI | Event-based (publish–subscribe) architecture, or MVC with Observer |
| Security (authentication, roles) | Each UI checks access in its own way | Add a security layer or an authentication server that all requests pass through |
| Extensibility (new devices, new channels) | New types force changes in the logic | Layered design with interfaces plus Strategy and Factory patterns |
| Many different UIs (web, mobile, voice) | UI and logic are mixed | MVC, so that many views share one model |
A system must serve thousands of users at peak time. Which NFR, and which alternative architecture?
Scalability. A simple layered design has one server that handles all requests. Propose client–server with several replicated servers and a load balancer: add more servers when the load grows.
The description says “the guest must see the door state change at once”. Which NFR, and which alternative?
Real-time updates. In a layered design the lower layers must call up to the UI (an up-call). Propose an event-based (publish–subscribe) architecture, or MVC with Observer, so that the model tells its views when it changes.
How do you answer “propose an alternative architecture for the NFR” in three steps?
- Name the NFR and quote the words of the description that show it. 2. Explain why the first architecture is weak for it. 3. Propose the alternative, draw it simply, and explain how it meets the NFR. Always justify with the requirements.
Exam patterns
This is Q3(a) in the recent papers. Propose an architecture and draw a detailed class diagram with key attributes and methods (8 marks: AY23/24 S1, AY23/24 S2, AY24/25 S1, AY25/26 S1; the two 2023/24 papers add “your solution should address the non-functional requirements identified”). Identify the one NFR and propose an alternative architecture (8 marks: AY24/25 S1, AY25/26 S1). The older CZ3003 paper (AY18/19 S1) asked for the two meta-design principles, the components and connectors of pipe-and-filter with pros and cons, and how to add a security component to an architecture. Tutorial 6 Q1 is the layered diagram.
| Question type | How to attack it | Trap |
|---|---|---|
| Architecture and detailed class diagram | Name the style, justify with the description, layers, classes in layers, typed attributes, methods from the use cases, dependencies down | A UI calling an entity. No justification. Untyped attributes. |
| One NFR and an alternative architecture | Quote the clue, say why the first design is weak, propose the alternative, say how it meets the NFR | Naming an NFR with no quote |
| Benefits and drawbacks of layers | Two benefits, one drawback (performance, up-calls) | A drawback that is not about layers |
| Event-based architecture | Decoupled and scalable, but delivery is not guaranteed and correctness is hard | Listing only advantages |
| Principles | Name it, define it in one line, give an example | Confusing cohesion with coupling |
Common Traps
- Justify the architecture with the description. One or two facts, not a general claim.
- Dependencies go down only, and only to the next layer. A UI never calls an entity.
- A control may call a boundary to a device. The arrow points up, and that is allowed.
- Type every attribute. Take the attributes from the data dictionary and the methods from the use case descriptions.
- Show interfaces where the design must be flexible. This shows “program to an interface”.
- Cohesion high, coupling low.
- An up-call breaks the layer rule. Observer or events fix it.
- A weak NFR answer has no quote. Quote the clue first.
- Event systems do not guarantee delivery.
- The architecture sets the non-functional qualities. That is why the NFR comes first.