Most first programs are written by opening the editor and starting to type. That works for twenty lines. Past a few hundred, the program that gets written stops matching the program that was wanted, and no amount of clever coding rescues it. The software development life cycle is the ordered set of stages professionals use to stop that happening: understand the problem, design a solution, build it, prove it works, and keep it working.
| Stage | The question it answers | What comes out of it |
|---|---|---|
| Analysis | What exactly is the problem, and what must the solution do? | A written list of requirements |
| Design | How will the solution be structured? | Pseudocode, flowcharts, IPO charts, screen sketches |
| Implementation | What is the code? | Working, commented source code |
| Testing | Does it do what the requirements said? | Test cases, results, and a list of defects fixed |
| Maintenance | What needs changing now that people are using it? | Fixes, improvements, updated documentation |
The stages are not a ritual. Each one exists because skipping it is expensive. Analysis exists because the most common reason software fails is that it solves the wrong problem perfectly. Design exists because it is far quicker to move a box on a diagram than to rewrite a working module. Testing exists because a program that has only ever been run on the data its author imagined is not evidence of anything.
A requirement is a single, checkable statement about what the finished program must do. "The program should be user-friendly" is not a requirement, because nobody can ever prove it true or false. "The program must reject any mark below 0 or above 100 and display an error message" is a requirement: you can write a test for it and get a yes or a no. Vague requirements are the reason so many projects end in an argument about whether they are finished.
| Vague wish | Usable requirement |
|---|---|
| Keeps track of marks | Stores up to 30 marks per student and reports each student's average to one decimal place |
| Is fast | Displays the search result within one second for a list of 1000 records |
| Handles bad input | Rejects non-numeric input and re-prompts, without stopping the program |
| Looks good | Displays all output in a fixed-width table with column headings |
Requirements come in two kinds. Functional requirements say what the program does: calculate, store, display, validate. Non-functional requirements say how well it must do it: how fast, how reliably, on what devices, how easy it is to learn. Both matter, and beginners almost always write only the first kind — which is how you end up with a program that produces the right answer after thirty seconds of waiting.
- Finish each stage completely, then move to the next
- All requirements are settled before any code is written
- Works when the problem is well understood and stable
- Its weakness: a wrong requirement is not discovered until testing, by which point everything is built
- Build a small working slice, review it, then build the next
- Requirements are expected to change as people see the software
- Works when the problem is fuzzy or the users are unsure
- Its weakness: without discipline the design drifts and no version is ever declared finished
In plain terms: waterfall is one long trip through the stages, and iterative is many short trips. An iterative team still analyses, designs, builds and tests — they simply do all five on a two-week slice of the product rather than on the whole thing. The advantage is feedback. If the requirement was wrong, an iterative team finds out in two weeks instead of eight months, and has thrown away two weeks of work instead of eight months of it.
The single strongest argument for doing the early stages properly is arithmetic. A mistake in a requirement costs almost nothing to fix while it is still a sentence in a document. The same mistake, discovered after the software has shipped, means re-analysing, re-designing, re-coding, re-testing, and re-distributing it to everyone who already has the old version. Every stage it survives multiplies what it costs to remove.
| Defect found during | Roughly what it costs to fix | Why |
|---|---|---|
| Analysis | 1× | Change one sentence in the requirements |
| Design | About 3× | Redraw part of the design; nothing is built yet |
| Implementation | About 5× | Rewrite code and the design behind it |
| Testing | About 10× | Rewrite, then re-run the whole test set |
| After release | 30× or more | All of the above, plus redistribution and the cost of the damage already done |