Develop book availability in C#
Adding a feature spans input, data retrieval, domain interpretation and output. A helper that is never connected to the menu is not a completed feature.
Lab briefing

Original concept illustration (SVG)
| At a glance | Your route |
|---|---|
| Level and time | 200; 70 minutes (facilitation estimate) |
| Starting action | Specify the two-copy case before wiring the new console action. |
| Learner materials | Download 03-csharp.zip |
| Workspace | Open the extracted kit root; run the baseline from . relative to that root |
| Expected initial check | The supplied tests pass. New feature requirements still need their own tests. |
| Setup help | Download, extract, local Git and optional GitHub |
[!NOTE] An overdue unreturned loan still makes that copy unavailable.
Concepts · First task · Evidence checklist · Reset
Learning objectives
- Turn a user request into explicit acceptance cases.
- Model availability per physical copy rather than per title.
- Connect the feature through the existing console workflow.
- Preserve unrelated return and membership behavior.
Before you start
Prepare 03-csharp using the common setup.
Use the bundled
library feature fixture.
The C# setup lab describes SDK, caches and execution directories.
Concepts and use cases
Book describes a title; BookItem identifies a physical copy; Loan records one
copy’s borrowing history. A returned loan does not make a copy unavailable.
An overdue but unreturned loan remains active.
Exercise scenario
A librarian needs case-insensitive title search and a view of each physical copy’s availability. Lending, reservations, database migration and authentication are not part of this feature.
Task 1 - Investigate and run the baseline
-
Inspect
CommonActions.cs,ConsoleApp.cs, core entities andJsonData. -
Run from the copied project root:
dotnet test tests/UnitTests/UnitTests.csproj -m:1 -p:UseSharedCompilation=false -
In Ask, trace the existing patron-search menu path. Identify the equivalent insertion points for book search without duplicating the input loop.
-
Record active-loan semantics from
ReturnDate, not a guess based on due date.
Task 2 - Define acceptance before code
| ID | Case | Expected observable |
|---|---|---|
| BOOK-1 | Partial title, different case, surrounding whitespace | Matching titles after defined normalization |
| BOOK-2 | Blank search | Clear prompt/error, no accidental full-catalog dump |
| BOOK-3 | Unknown title | Explicit no-results message |
| BOOK-4 | Two copies; one active loan | One unavailable copy and one available copy |
| BOOK-5 | Returned historical loan | Copy remains available |
| BOOK-6 | Active overdue loan | Still unavailable; due date shown as historical data |
Use newly constructed synthetic records in tests rather than relying on stale dates in JSON files. Specify deterministic title/copy ordering.
Task 3 - Plan the complete path
Plan title search and per-copy availability in the existing C# library.
Map BOOK-1..6 to tests and source files. Reuse existing input handling and JSON
loading. Add a distinct CommonActions flag without renumbering existing flags.
Keep return, extension and membership behavior unchanged. Do not edit yet.
Review repository/service boundaries. If using JsonData directly in the console
to match the starter, explain the coupling; do not call it an ideal production design.
Task 4 - Implement with a failing regression first
- Add a test for the two-copy case and confirm it fails for the absent feature.
- Ask Agent to implement only the reviewed feature slice.
- Inspect matching, whitespace handling, active loans and result ordering.
- Connect menu display, input mapping and dispatch. Preserve existing action values.
- Add remaining boundary cases and run the existing/new tests together.
- Start the app from
src/Library.Consoleand manually exercise the menu. - Record the actual output and confirm the feature performs no writes.
Check yourself
A title has two physical copies and only one of them has an active loan. How must your availability check work for BOOK-4?
Choose an answer to see why it holds or fails.
- Join loans to copies by BookItemId, so the active loan marks only that one copy unavailable. Each Loan records one copy, so joining on BookItemId leaves the untouched copy available, which is what BOOK-4 expects.
- Mark the Book unavailable whenever any loan on that title is active, and show both copies as out. Book describes a title while BookItem identifies a physical copy, so checking at title level hides a copy that is still on the shelf.
- Compare each due date with today and treat a copy as unavailable only while its loan is past due. Active status comes from ReturnDate, not the due date, so a late but returned loan would look unavailable and a current loan would look free.
Verify your work
- All BOOK cases have executable or clearly labeled manual evidence.
- Two physical copies can have different availability.
- Returned versus overdue-active loans are distinguished.
- The menu reaches the implementation.
- Existing tests remain green and JSON data is not modified by search.
Troubleshooting
If one active loan hides all copies, check joins by BookItemId.
If a method passes unit tests but the menu never calls it, inspect action dispatch.
If a due date is old, do not change fixture dates merely to hide a bug.
Independent practice
Design reservations as a separate feature: states, conflicting requests, expiration, and persistence. Do not add it opportunistically to this search change.
Reset
Preserve the acceptance table and output, then restore only feature/test files in the disposable copy. A remote branch or public repository is optional, not required.