Software Engineering
How software is planned, structured, tested and shipped by teams: process models, requirements, coupling and cohesion, UML, the testing pyramid, and CI/CD.
If you remember nothing else
- Verification asks 'are we building the product right?'; validation asks 'are we building the right product?'
- Good design means low coupling and high cohesion — modules that depend on each other minimally and do one thing internally.
- Waterfall fixes requirements up front; agile assumes they will change. Choose by how well the requirements are actually understood.
- Testing levels go unit → integration → system → acceptance; each catches a class of defect the previous one structurally cannot.
- Black-box testing works from the specification, white-box from the source; they find different bugs and neither replaces the other.
- The cost of fixing a defect rises steeply with the phase in which it is found — which is the entire economic argument for early testing and review.
The SDLC and process models
Requirements gathering & analysis
Establish what the system must do, and record it in an SRS.Design
Architecture, module decomposition, interfaces, data structures — high-level then detailed.Implementation
Write the code against the design.Testing
Unit, integration, system and acceptance testing.Deployment
Release to the production environment.Maintenance
Corrective, adaptive, perfective and preventive changes — typically the longest and most expensive phase.
| Model | Shape | Best when | Weakness |
|---|---|---|---|
| Waterfall | Strictly sequential; each phase completes before the next begins | Requirements are stable and well understood; regulated or safety-critical work | No working software until late; changes are extremely costly |
| V-model | Waterfall with a matching test level for each development phase | Verification and traceability matter | Same rigidity as waterfall |
| Incremental | Build and deliver in successive slices | Core requirements are clear; the rest can follow | Needs good early architecture or slices conflict |
| Spiral | Iterative loops, each with an explicit risk analysis | Large, expensive, high-risk projects | Heavy process overhead; needs risk expertise |
| Agile / Scrum | Short iterations delivering working software | Requirements are expected to change; the customer is available | Weak for fixed-price contracts; can under-document |
- Scrum roles — Product Owner (owns the backlog and priorities), Scrum Master (removes impediments, guards the process), Development Team (self-organising).
- Scrum artefacts — product backlog, sprint backlog, the increment.
- Scrum events — sprint (typically 2–4 weeks), sprint planning, daily standup, sprint review (demo to stakeholders), retrospective (improve the process).
- Velocity is story points completed per sprint — useful for a team's own forecasting, meaningless for comparing teams.
Requirements engineering
| Functional requirement | Non-functional requirement | |
|---|---|---|
| Describes | What the system does | How well it does it |
| Example | "The system shall email a receipt after payment" | "95% of pages shall load in under 2 seconds" |
| Also called | Behavioural | Quality attributes, constraints |
| Categories | Features, business rules, data handling | Performance, security, usability, reliability, scalability, maintainability, portability |
| Testing | Usually straightforward | Often needs load, security or usability testing |
Design: coupling, cohesion and modularity
| Coupling type | Modules share | Rating |
|---|---|---|
| Data coupling | Simple parameters only | Best |
| Stamp coupling | A whole record, where only part is needed | Good |
| Control coupling | A flag telling the callee what to do | Moderate |
| External coupling | An externally imposed format or device | Poor |
| Common coupling | Global data | Bad |
| Content coupling | One module modifies another's internals | Worst |
| Cohesion type | Elements grouped because | Rating |
|---|---|---|
| Functional | They all contribute to one single task | Best |
| Sequential | One's output is the next's input | Good |
| Communicational | They operate on the same data | Good |
| Procedural | They execute in a particular order | Moderate |
| Temporal | They happen at the same time (e.g. all startup code) | Poor |
| Logical | They are the same category of task, selected by a flag | Bad |
| Coincidental | No meaningful relationship — a Utils grab-bag | Worst |
UML diagrams worth naming
| Diagram | Category | Shows |
|---|---|---|
| Class | Structural | Classes, attributes, methods and their relationships |
| Object | Structural | A snapshot of instances at one moment |
| Component / Deployment | Structural | Software components and their physical placement |
| Use case | Behavioural | Actors and the system functions they invoke |
| Sequence | Behavioural | Message exchanges ordered in time |
| Activity | Behavioural | Workflow, including decisions and parallel paths |
| State machine | Behavioural | States of one object and the events that transition it |
Testing
| Level | Tests | Performed by | Catches |
|---|---|---|---|
| Unit | One function or class in isolation | Developers | Logic errors within a component |
| Integration | Interaction between modules | Developers / testers | Interface mismatches, wrong assumptions between modules |
| System | The complete integrated system | Independent testers | End-to-end behaviour, non-functional failures |
| Acceptance | Against the user's actual requirements | Customer / end users | The system solving the wrong problem |
| Black box | White box | |
|---|---|---|
| Based on | The specification | The source code |
| Tester needs | No knowledge of internals | Full knowledge of internals |
| Techniques | Equivalence partitioning, boundary value analysis, decision tables, state transition | Statement, branch, path and condition coverage |
| Finds | Missing functionality, wrong behaviour | Unreachable code, untested branches, logic errors |
| Misses | Untested internal paths that happen to produce right answers | Requirements that were never implemented at all |
Grey-box testing combines the two: specification-driven tests written with some knowledge of the implementation.
| Test type | Purpose |
|---|---|
| Regression | Confirm that a change has not broken previously working behaviour |
| Smoke | A quick check that the build is stable enough to test at all |
| Sanity | A narrow check that one specific fix works |
| Alpha | In-house testing by staff before external release |
| Beta | Real users in their own environment before general release |
| Stress | Behaviour beyond the specified limits — does it fail gracefully? |
| Load | Behaviour under expected peak load |
Version control, CI/CD and maintenance
- Version control records every change with its author, time and reason, allows parallel work on branches, and makes any prior state recoverable. Distributed systems (Git) give every clone the full history; centralised ones (SVN) keep a single authoritative server.
- Branching strategies — Git Flow (long-lived develop and release branches; suits scheduled releases), GitHub Flow (short-lived feature branches merged to main; suits continuous deployment), trunk-based (everyone commits to main behind feature flags; suits high-frequency delivery).
- Merge vs rebase — merge preserves the true history and creates a merge commit; rebase rewrites commits onto a new base for a linear history. Never rebase commits that others have already pulled.
| Practice | Means | Delivers |
|---|---|---|
| Continuous Integration | Every commit is merged to a shared branch and automatically built and tested | Integration problems surface within minutes rather than at a release |
| Continuous Delivery | Every passing build is automatically prepared for release | Deployment becomes a business decision, not an engineering event |
| Continuous Deployment | Every passing build is released to production automatically | No manual gate at all — requires strong automated testing |
| Maintenance type | Reason | Share of effort |
|---|---|---|
| Corrective | Fixing defects found in production | ~20% |
| Adaptive | Responding to a changed environment — new OS, new API version, new regulation | ~25% |
| Perfective | New features and performance improvements requested by users | ~50% |
| Preventive | Refactoring and restructuring to reduce future cost | ~5% |
The distribution is the point: most maintenance is enhancement, not bug fixing — which is why designing for change matters more than designing for correctness alone.
Self-check
10 questions on Software Engineering · nothing is stored