The problem
Before any code, understand the problem. A small library keeps its loans on paper: members cannot see if a book is in, and staff chase late books by hand. Ask who will use the system, and what goes wrong for them today.
Write each need as a user story: As a [who], I want [what], so that [why]. Here: As a member, I want to borrow a book, so that I can read it at home. One short story for each need.
Requirements
Functional requirements say what the system must do. The story becomes lines you can test: members can borrow and return books, anyone can search the catalogue, and a loan lasts 21 days. Each one either works or it does not.
Non-functional requirements say how well it must work: speed, cost and security. Search answers in under 1 second, hosting costs under $20 a month, and passwords are stored hashed, never as plain text. These often shape the design most.
Constraints are limits you do not get to choose. The team knows Python, there are 2 developers, and it must go live in 8 weeks. A constraint rules options out before you start, so write it down with the requirements.
The design
Now design. Split the system into components, parts with one job each: a web app people use, a loan service that applies the rules, and a database that remembers. Each requirement lands on the part that will meet it.
The data model lists the things the system stores and how they link: Book, Member and Loan. A Loan points to one book and one member, and has a due date. Most of the design follows from this, so settle it early.
An interface is the agreed way one component calls another. The web app never touches the database; it calls borrow(member, book), and the loan service checks the rules, saves a Loan and returns it. Agree interfaces first, then build parts separately.
Write it down
Write it down in a short design doc: the goals and non-goals, the design, and the alternatives you rejected. A page or two is enough. Others can review it before any code exists, while changes are still cheap.
Every choice is a trade-off. SQLite is one file with no server to run, but only one writer at a time: fine for one small library. PostgreSQL lets many users write at once, but needs a server to look after. Record the choice and why.
What happens
;; step 1/10 · problem example a small library-loan app problem loans are kept on paper user a member wants to borrow books and see if one is in user a librarian wants to see who has which book and when it is due ask first: who uses it, and what hurts today?
The library app is an invented example. Its numbers (21-day loans, under $20 a month, 2 developers, 8 weeks) are requirements we chose for it, not facts about libraries. Real projects loop: building often uncovers new requirements, so the stories, the design and the doc change as you learn. The figure shows one pass, in order.