Year 2 / Module 16

Software engineering for interactive products

HCI2108 · 15 credits · Level 5

Delivering a product that survives release: architecture, testing, review, and the discipline that makes change affordable.

Ten units

  1. 1Programming integrated over time: evolution, maintenance and the definition of engineeringWhat separates software engineering from programming is the time horizon rather than the size of the system, so the discipline is defined by the cost of future change and its central failure is a system that can no longer be changed.
  2. 2Process, plan and organisation: how the work is divided and how it changesIterative and agile methods change who decides what and when rather than removing planning, and because the teams that adopt them are self-selected the evidence on their outcomes cannot be read as a controlled comparison of process.
  3. 3Requirements and user stories: from wishes to decisions a test can checkA requirement earns its place only when it names a decision and a condition that can be tested, so the value of a story format lies not in the sentence it prescribes but in the acceptance criterion it forces the author to write.
  4. 4Architecture as enforceable boundaries: patterns and the price of each constraintAn architecture is a set of enforceable decisions about which parts may change independently, so a pattern is worth its name only when the constraint it imposes is stated together with the price it charges.
  5. 5Version control and branching as a team protocolA branching policy is a decision about how long two people's work stays unintegrated, and its cost is paid in a merge that no test has run rather than in the conflict typing, so the choice between trunk and long-lived branches is a risk trade rather than a matter of taste.
  6. 6Testing and the contested case for test-firstTests buy information about change rather than proof of correctness, and because the evidence that writing them first improves quality is small and conditional, test-first is defensible as a design discipline rather than as a measured productivity or quality win.
  7. 7Integration, delivery and release: deployment is not the same as releaseSeparating deployment from release turns a user-facing decision into an engineering one, at the price of a configuration surface of feature flags and pipelines that grows unless it is pruned.
  8. 8Code review: what it is actually forThe defect-finding yield of review is small and mostly local, and its larger product is shared understanding of a change, so a review process judged only on defects found will be dropped in the first busy quarter.
  9. 9Technical debt and refactoring: the loan and its repaymentTechnical debt is a loan whose interest is paid in every later change, so the engineering judgement is not whether a shortcut is permissible but whether its repayment is scheduled, owned and visible.
  10. 10Quality attributes as requirements: accessibility, performance and observabilityNon-functional requirements are properties of the whole product and cannot be retrofitted, so accessibility, performance and observability have to arrive as testable acceptance criteria rather than as later audits.

10 of 10 units written. Rows marked in preparation have no body yet.

Code HCI2108Credits 15Level 5Year 2

Specification

Assessment is by coursework unless a row says otherwise.
AssessmentWeightType
Team product with test suite and pipeline55%coursework
Architecture decision record and review25%coursework
Individual contribution reflection20%coursework

What you will be able to do

  • Turn a design into user stories with acceptance criteria a test can check.
  • Choose an architecture for an interactive product and defend the boundaries.
  • Build a test suite at unit, integration and end-to-end level with a stated rationale.
  • Set up a continuous integration pipeline and interpret its failures.
  • Review another team's code and give feedback that improves it.

The reading this module rests on

  • Sommerville, I. Software Engineering. Pearson. The systematic account of requirements, architecture and process.
  • Winters, T., Manshreck, T. and Wright, H. (2020). Software Engineering at Google. O'Reilly. Free online, and honest about the trade-offs at scale.
  • Fowler, M. (2018). Refactoring: Improving the Design of Existing Code. 2nd edition. Addison-Wesley. The catalogue, and the discipline of small safe steps.
  • Beck, K. (2002). Test Driven Development: By Example. Addison-Wesley. Read it for the reasoning, not as a rule.

Software engineering for interactive products

A design that never ships has no users. Engineering decides whether an idea reaches anybody, and most of its work is invisible: the pipeline that turns a commit into a deployment, the tests that decide whether a change is safe, and the boundaries that decide which team can move alone.

Winters, Manshreck and Wright define the difference between programming and engineering as time. Software engineering is programming integrated over time, and a project is sustainable when, for its expected life span, the team can react to whatever valuable change comes along (Winters, Manshreck and Wright, 2020). A prototype optimises for showing something now; a product for being changed by people who have not been hired yet.

A backlog records wishes unless somebody writes a decision

A user story is a sentence about a need, usually in the form "as a claimant I want to check my eligibility so that I do not lose a half-completed form". It names the actor and the reason, which a feature list hides. It does not state anything a test could check.

Lucassen, Dalpiaz, van der Werf and Brinkkemper surveyed 182 practitioners and interviewed 21, who agreed that stories, a story template and quality guidelines such as the INVEST mnemonic improve their productivity and the quality of what they deliver (Lucassen and others, 2016). That is a belief about a format, reported by its users; it does not show that the product is better.

The move that turns a wish into a decision is the acceptance criterion: the condition under which the work counts as done, written so a test can check it. For the story above, one criterion could be that a claimant who has not signed in sees the eligibility check before any field is required. A backlog without such criteria is a list of intentions, and the discipline is to refuse work whose criteria nobody can write down.

Architecture is a set of boundaries, and state decides which ones hold

Krasner and Pope set out the model-view-controller factoring of Smalltalk-80. The model does the work of the application domain, the view displays the model's state, and the controller turns input into messages to the model. The model must not know about its views; when it changes it broadcasts to its dependents, which ask it for the new state (Krasner and Pope, 1988). The lasting idea is a direction of dependency, not a folder layout, and the pattern's descendants keep the model authoritative while changing the plumbing.

Take a booking application and ask where a held slot lives. If the hold sits in the server's session, a dropped connection loses it; if it lives only in the browser, two people can be told they hold the same slot. The model answers this question, because it is the only authority on what is true.

The client and the server are the other boundary, and Fielding's account of the web's design states its price. Separating the user interface from data storage improves portability and scalability and lets the two sides evolve independently. Stateless communication, in which each request carries everything needed to understand it and session state stays on the client, buys visibility, reliability and scalability (Fielding, 2000). It costs repeated data in every request and weakens the server's control once several client versions exist, while caching buys latency back and risks stale data. The boundary belongs in a written decision, because no constraint is free.

Version control is a team protocol, not a backup system

The merge problem is not the typing. It is that two people changed overlapping code for a fortnight, and now somebody must review a merged result that no test has ever run. Winters, Manshreck and Wright argue against long-lived branches on that ground. Trunk-based development, one repository with no development branches, is in their view a particularly scalable policy, and a policy that makes extensive use of development branches as a means toward product stability is inherently misguided, because the same commits will be merged to trunk eventually (Winters and others, 2020).

A branch protects an unfinished feature from users, so the comparison is between two risks: shipping something half-built, which a feature flag can prevent, and integrating a change no test has ever run. The pull request is where the protocol meets: the checks run on it, a person reads it, and the merge makes the change everybody's problem.

Testing at three levels, and the contested evidence for test-first

Three levels of test answer different questions and cost different amounts. A unit test exercises one piece of logic with its collaborators replaced, and thousands run in seconds. An integration test exercises two or more real parts together, such as a booking endpoint and its database, and catches wiring a unit test cannot see. An end-to-end test drives the assembled product, interface and confirmation email included, and is the slowest and most expensive to keep green.

A flaky end-to-end test teaches a team to ignore red, which is worse than no test at all. The mix follows the economics: many unit tests, fewer integration tests, and a few end-to-end journeys that cover the product's promises.

Beck's test-first rests on two rules: new code is written only when a failing automated test demands it, and duplication is removed. The cycle is red, green, refactor. He says the implications include designing organically with running code as feedback, and that designs must consist of highly cohesive, loosely coupled components, just to make testing easy (Beck, 2002). That last clause is a cost as well as an aim, because testability shapes the design.

The contested question is whether test-first beats writing the test afterwards, and the evidence is weaker than the advocacy. Rafique and Misic pooled 27 studies and found a small positive effect on external quality and little to no discernible effect on productivity. Their subgroup analysis found the quality gain and the productivity drop to be larger in industrial studies, with a positive correlation between task size and quality improvement (Rafique and Misic, 2013). Test-first is defensible as a discipline for feedback and design, not as a proven productivity measure.

Continuous integration is a contract, and release is a separate decision

Continuous integration means the team integrates at head often and runs the build and tests on every change. The tooling is easy to buy and the social part is not, because a red build claims that the shared state is broken and somebody must fix it first. Winters, Manshreck and Wright add two conditions teams usually miss: feedback must be accessible and actionable, and checked-in configuration should go through the same review and testing as code (Winters and others, 2020).

Deployment and release are different events, and separating them is the most useful idea in this area. A feature flag is a switch in the code that decides whether a feature is expressed, and these authors describe flag-guarding changes so that features at different stages coexist in one binary and can be toggled in production (Winters and others, 2020). Deploying then stops being a decision about users. The price is real: flags accumulate, and a team that never removes them has built a configuration problem and called it safety. A staged rollout exposes a change to a small share of traffic first, and it helps only if somebody is watching.

Code review does two jobs, and only one of them is finding defects

Bacchelli and Bird observed 17 developers across 16 teams at Microsoft, classified 570 review comments, and surveyed 165 managers and 873 programmers. Finding defects was the most common stated motivation, but defect-related comments were a small share of the total and mostly concerned local issues. Reviews also produced knowledge transfer, team awareness and better solutions, and the difficulty developers reported was understanding a change well enough to judge it (Bacchelli and Bird, 2013).

That should change how review is measured. A process judged only on defects found will look like a poor return and be dropped in the first busy quarter, though it does work nothing else does. The study suggests where to invest: a small change, a clear description and a pointer to the decision behind it, which shorten the distance to the author's intent.

Review is also where a team's social rules become visible. Winters, Manshreck and Wright put humility, respect and trust at the base of team work, and they describe a blameless post-mortem that seeks the cause rather than a person (Winters and others, 2020). A review that is technically correct and socially corrosive teaches people to hide work.

Refactoring and technical debt: when the loan is deliberate

The metaphor comes from Cunningham's experience report on a portfolio management system. Shipping first-time code, he wrote, is like going into debt: a little debt speeds development so long as it is repaid promptly with a rewrite, and every minute spent on not-quite-right code counts as interest on it. An organisation can be brought to a standstill under the load of an unconsolidated implementation (Cunningham, 1992), so the word debt was an argument for repayment, not a licence to borrow.

Fowler supplies the grammar of repayment: a catalogue of named refactorings, each a small step that changes the structure of code without changing what it does, and a vocabulary of smells that indicate where a change is worth making (Fowler, 2018). Naming the step makes it reviewable and reversible, and turns an argument about taste into a decision a team can accept.

A deliberate loan has three parts: the shortcut, the reason it is affordable now, and the repayment with a date and an owner. Take a pilot that hard-codes one benefit rule to ship within a month, with a ticket to generalise it when a second benefit arrives. The second benefit arrives, the ticket is still open, and interest is paid on every later change to that rule. The judgement is not whether debt is acceptable, but whether the repayment is scheduled and visible.

Accessibility, performance and observability are requirements, not clean-up

Non-functional requirements cannot be retrofitted, because they are properties of the whole product. WCAG 2.2 is the reference point for the first of them. It is written as testable success criteria that are not technology-specific, organised under four principles: perceivable, operable, understandable, robust. It states its own limits: it will not address every user need, and it is designed to be testable with a combination of automated testing and human evaluation (World Wide Web Consortium, 2024). Accessibility therefore has two halves: a contrast rule or a focus order can be checked automatically on every build, and a screen reader journey needs a person.

Performance has the same shape. A budget, such as a maximum time to first response on a target device, converts an argument about speed into a test that fails when it is exceeded. Observability means the product reports enough about itself for a failure to be visible before a user complains. A confirmation email that fails silently for a week is a delivery failure with no interface content, and the cure is instrumentation accepted as part of the work.

All three belong in the acceptance criteria of the stories that create them: a retrofitted accessibility fix, performance fix or monitor is a rebuild.

Working in a team, and what follows from the material

Estimation is where engineering meets politics: a number written in a planning meeting becomes a commitment other people plan around. The useful habit is to record what the estimate assumed, so the number can be revisited when an assumption fails rather than defended. A stand-up earns its place when it moves information that changes what somebody does next: a blocker, a decision, a piece of news. Reciting what each person did yesterday is a status ritual, and the first thing a busy team drops.

Disagreement is normal, and the engineering question is what kind of disagreement it is. Two people can disagree about a fact, a value or a prediction, and only the first is settled by evidence, so naming which is in dispute keeps an argument technical. The result is unglamorous: a working product, a test suite that fails when it should, and a pipeline that turns a reviewed change into a release without a meeting.

That is what makes a design reach a user, and it is the platform for what follows. The next step takes up the theories of interaction, the frameworks that make an interaction analysable rather than merely deliverable, and they are easier to use when you have a product you can change.

Check your understanding & apply it · 7 questions, 2 essays

1A team's backlog contains sixty user stories, none of them with acceptance criteria. Work starts, and three features are demonstrated at the end of the quarter. Which outcome does the module's account of requirements predict most directly?
2A booking team stores each user's half-completed form in server session state so that it survives a refresh. Using Fielding's derivation of the client-server style, which consequence follows most directly?
3A team keeps each feature on its own branch for three weeks before merging, on the ground that users must not see unfinished work. Which cost does the module treat as the decisive argument against this policy?
4A team's suite has grown to 400 end-to-end tests and no unit tests, and the ninety-minute run contains about fifteen tests that fail intermittently. Which change does the module's account of the economics of the three levels support?
5A manager wants to claim, in a funding bid, that adopting test-first development will raise team productivity by a third. Which reading of Rafique and Misic's meta-analysis supports the most defensible claim?
6A team's review policy states that a code review which finds no defect has been wasted. Which finding from Bacchelli and Bird's study is most relevant to that policy?
7A team intends to audit accessibility after release and to rely on automated scanning during each build. Which statement follows from WCAG 2.2's own account of itself?
8Essay Your team is changing the eligibility rule for a benefit claimed by about 200,000 people a year. The change is written, reviewed and merged. Describe the pipeline you would run before and after release, name what you would test at each level and why, and state the evidence that would make you stop or reverse the rollout. Say who can read each signal.
9Essay Write the substance of an architecture decision record for one decision in a booking application: where a held appointment slot lives. State the decision, the boundaries it creates, the alternative you rejected and the non-functional requirements you accept in the same record. Then write the review comment you would give a colleague who proposed moving the hold into the browser because it would be faster.