0002.m Iterative design
On this page
Programs are rarely right the first time, and the practices in this section are ways of finding out what is wrong while it is still cheap to fix. They form a cycle. A project begins by understanding what its users need. It tries ideas out cheaply with prototypes, builds in small working steps that are each tested, and uses what it learns to revise the plan before the next round. The section follows that cycle from beginning to end, and then steps back to the scale of a whole project, where two well-known approaches, waterfall and agile, differ chiefly in how often they go around it.
The cycle#
Iterative development repeats cycles of planning, building, testing, and revising small working versions, in place of delivering everything at once at the end. Its central benefit is early, frequent feedback. A team that builds every planned feature before anyone uses it can spend months on something that doesn't meet the need, while a team that builds a small working version, watches people use it, and revises its plan exposes wrong assumptions before much has been invested.12 A student team building an app to help classmates find study partners might first build a version that only lists students by course, gather reactions, and then revise its plans before adding messaging. A student with two weeks to build a quiz app might have a working one-question quiz in the first few days, and add features after trying it. Under this approach, plans are expected to change with the evidence. If the second iteration shows that users ignore a feature that took weeks to build, the right response is to change or drop it in the next cycle, not to defend the time already spent.
Starting from needs#
Every cycle depends on knowing what the program is for, so effective programs begin with identifying users' needs and the program's requirements, usually by talking with the people who will use it. Asked to "make an app for the library," a student should first talk with the librarian and patrons, before writing any code. These conversations reveal constraints that are invisible from outside. A beautifully designed attendance app is useless to a teacher if students' phones aren't allowed in class, and only someone familiar with the setting would know that.
A well-stated requirement says what is needed, not how to build it. "Students must be able to see their grades on a phone" is a requirement, because it leaves open many ways of providing it, whereas "use a red table on the home page" is already an implementation decision. Different groups of users often want different things, and requirements work includes facing those conflicts. If teachers want detailed logs of student activity and students want privacy, the right step is to discuss the conflict with both groups and decide on an acceptable balance, not to let one group's wishes silently prevail.3
Trying ideas cheaply#
Once needs are understood, the next question is whether a proposed design meets them, and the cheapest way to find out is a prototype: an early version, anything from a paper sketch to a simple working program, built to test an idea and gather feedback before major investment. To learn whether students understand a new navigation layout, a team can test a clickable sketch with a few students. The roughness of a prototype is an advantage. A rough paper sketch signals that the design can still change, so users focus on what the app does and make suggestions freely, whereas a polished demo invites comments on colors and fonts. Prototypes can test technical risks as well as designs: a developer unsure whether a sensor can respond quickly enough for a game can write a short program that only reads the sensor and prints its timing, which tests that one risky assumption before the rest of the game is built.
Because prototypes are built to learn quickly, they aren't finished products. They usually lack the reliability, testing, and security of finished software, so shipping a working prototype as the final product carries real risks.
Building in small steps#
When the real building begins, the same principle of small steps applies to the code itself. Incremental testing means adding and testing one small feature at a time. This keeps the program working at every stage, and when a new bug appears, it is probably related to the last change, which narrows the search. A student who adds login, messaging, and profile pictures all at once, and then finds that the app crashes on launch, has three large changes to search. A student writing a function that reads a file, parses it, and prints a summary does better to write the reading step and test it, then add parsing and test it, then add the summary and test that. If a program worked before the last commit and fails now, the place to look is the small change in that commit. Teams build this into their workflow by requiring all tests to pass before any change is merged, which keeps new changes from silently breaking something that used to work. 0002.n describes testing in more detail.
Waterfall and agile#
At the scale of a whole project, the question is how many times to go around this cycle. Waterfall development completes phases such as requirements, design, implementation, and testing in sequence, finishing each before starting the next, often with formal approval at each stage. It suits projects with stable, fixed specifications, such as a government system built to a detailed specification with little contact with users after the requirements are set. Its weakness is that problems discovered late are costly. If testing in the final phase reveals that a key requirement was misunderstood, much of the work built on it has to be redone.
Agile methods instead use short cycles, frequent delivery of working versions, and regular feedback, which suits uncertainty, as for a start-up building an app for a market it doesn't yet understand. A team that holds short daily meetings, delivers a working version every two weeks, and adjusts its priorities after each customer review is working in an agile way. Agile is sometimes taken to mean that no planning or documentation is needed, but that is a misunderstanding. Agile teams plan and document continually, in small increments, instead of all at once at the start.
Iterative design assumes that errors will occur and organizes work so that they surface early. The next section looks at the errors themselves, and at the testing and debugging that find and fix them.
- iterative development: repeating cycles of planning, building, testing, and revising small working versions
- requirement: a statement of what users need a program to do, independent of how it is built
- prototype: an inexpensive early version, from a paper sketch to a simple program, built to test an idea
- incremental testing: adding and testing one small feature at a time
- waterfall: development that completes phases such as requirements, design, and testing in sequence
- agile: development that uses short cycles, frequent delivery, and feedback
Practice: practice questions for 0002.m
-
MWC1, Drawing project: planning, milestones, debugging, and version control through
mwc submit. ↩ -
MWC1, Game project: proposing, building, and revising a personally meaningful game. ↩
-
MWC2, Banjo app: a teacher portal case study, including requirements, components, and FERPA. ↩