Architecture Review
This is the Layer 6 gate. We step back and review every major structural decision made across the whole project, documenting the reasoning the way a real engineering team would.
Every major decision, written down with its reasoning.
1. Learning Objective
By the end of this session you will be able to:
- Write an Architecture Decision Record (ADR) documenting a real decision made earlier in the project
- Review the current package structure end to end and assess whether it still makes sense
- Identify one thing you would do differently if starting the project over, and explain why
- Confirm the full test suite still passes as a final Layer 6 checkpoint
- Explicitly connect the prop drilling problem from Session 39 to a documented architectural tradeoff
2. Pre-Coding Quiz
Answer these before reading the concept explanation or writing any code. It is fine to get these wrong โ that is the point. You need 4/5 to proceed to the lab.
What are the essential components of a good Architecture Decision Record (ADR), based on this session's format?
Why is it valuable to document that Session 28's repository pattern was chosen SPECIFICALLY to support later testing (Session 35) and later real-API integration (Session 42), rather than just noting "we added a repository class"?
Reviewing the prop drilling problem from Session 39, what should an honest architecture review document about it?
Why does this session explicitly re-run the full test suite as one of its checkpoints, given that Session 36 already ran it after the package reorganization?
What is the value of explicitly asking "what would I do differently if starting over" as part of this review, rather than only documenting decisions as unquestionably correct?
3. The Concept โ Conducting an Architecture Review
Four questions turn a silent choice into a durable, readable record future-you can actually use.
The ADR format
An Architecture Decision Record captures a real decision, its context, its reasoning, the alternatives considered, and its ongoing consequences โ turning tacit reasoning into a durable, readable record.
# ADR-001 โ Repository Pattern for Data Access
#
# Decision: Wrap all data access behind a CountryRepository class with a
# stable get_all()/find_by_region() interface.
#
# Session: 24 (Building a Data Access Layer)
#
# Why: Application logic should not need to know or care whether data comes
# from an in-memory mock list, a JSON file, or eventually a real API. This
# separation lets each of those be swapped in independently, and lets tests
# (Session 35) inject small, controlled fake datasets without touching real
# files or the network.
#
# Alternatives considered: Letting every part of the app import mock data
# directly. Rejected โ this would tightly couple application logic to one
# specific data source, and make testing much harder.
#
# Consequence: Any future data source (Session 42's real API) must be
# adapted to return data in the same raw shape the repository expects.
Reviewing the current package structure
Session 36 split the project into country_explorer/models.py, repository.py, validators.py, formatting.py, and search.py. A genuine review asks: does this grouping still make sense, now that the project has grown further?
# country_explorer/
# __init__.py โ re-exports the package's public interface
# models.py โ Country, CountryExplorer (data + core behavior)
# repository.py โ CountryRepository (data access)
# validators.py โ validate_country_record (data contract enforcement)
# formatting.py โ format_population (shared display logic)
# search.py โ matches_search_term (shared search logic)
#
# Does this still make sense? formatting.py and search.py are both small,
# single-function modules โ reasonable for now, but worth reconsidering if
# either grows substantially.
Documenting a known, unresolved limitation
A genuine review does not pretend the project is flawless โ Session 39's prop drilling problem is a real, currently open architectural tradeoff worth recording explicitly.
# ADR-002 โ Prop Drilling in the Composed UI-Layer Classes (UNRESOLVED)
#
# Decision: (none yet โ documenting a known problem, not a fix)
#
# Session: 35 (The Prop Drilling Problem)
#
# Why this is a problem: App -> NavigationPanel -> MenuSection ->
# CountryExplorer requires every intermediate layer to forward a reference
# it does not otherwise use, coupling unrelated classes together.
#
# Status: Deliberately left unresolved in this curriculum. A future
# iteration might explore a shared context/state object or dependency
# injection to address this, but understanding the problem clearly (as
# Session 39 did) is prioritized over reaching for a fix prematurely.
The final Layer 6 checkpoint: does everything still work?
Before considering Layer 6 complete, confirm the full test suite still passes โ proving all the structural work across Sessions 36-40 was behavior-preserving throughout, not just at one point in time.
4. Lab
What you will build
A file called ARCHITECTURE.md at the project root.
Step-by-step instructions
Create ARCHITECTURE.md with the repository pattern ADR
# Architecture Decisions
## ADR-001 โ Repository Pattern for Data Access
**Decision:** Wrap all data access behind a CountryRepository class with a
stable get_all()/find_by_region()/search() interface.
**Session:** 24 (Building a Data Access Layer)
**Why:** Application logic should not need to know or care whether data
comes from an in-memory mock list, a JSON file, or eventually a real API.
**Alternatives considered:** Letting every part of the app import mock
data directly. Rejected โ this would tightly couple application logic to
one specific data source.
**Consequence:** Any future data source must be adapted to return data in
the same raw shape the repository expects.
Add an ADR for the package reorganization from Session 36
## ADR-002 โ Package Structure (models / repository / validators / formatting / search)
**Decision:** Split the growing country.py into a country_explorer package
with focused submodules by responsibility.
**Session:** 32 (Package and Folder Organization)
**Why:** A single growing file mixed unrelated responsibilities. Splitting
by responsibility (data modeling, data access, validation, formatting,
search) keeps each module focused and easier to navigate.
**Alternatives considered:** Splitting by "layer" of the curriculum
instead of by responsibility. Rejected โ responsibility-based grouping
stays meaningful even as the curriculum's own structure changes.
**Consequence:** Every new piece of cross-cutting logic must be evaluated
for which existing module (or a new one) it belongs in.
Add an ADR documenting the unresolved prop drilling problem
## ADR-003 โ Prop Drilling in Composed UI-Layer Classes (UNRESOLVED)
**Decision:** None yet โ this documents a known problem, not a fix.
**Session:** 35 (The Prop Drilling Problem)
**Why this is a problem:** A layered App -> NavigationPanel -> MenuSection
-> CountryExplorer structure requires every intermediate layer to forward
a reference it does not otherwise use.
**Status:** Deliberately left unresolved. Future work might explore a
shared context object or dependency injection, but understanding the
problem clearly is prioritized over a premature fix.
Review the current package structure and write a short assessment
Answer explicitly: does the current models/repository/validators/formatting/search split still make sense? What, if anything, would you change?
## Package Structure Review
country_explorer/models.py, repository.py, validators.py, formatting.py,
and search.py currently reflect distinct responsibilities established in
Sessions 28, 30, 37, and 38. formatting.py and search.py are each small
single-function modules โ reasonable for the project's current size, but
worth reconsidering if either grows to contain several unrelated helpers.
Run the full test suite as the final Layer 6 checkpoint
Confirm every test from Sessions 31-38 still passes, proving all of Layer 6's structural changes were behavior-preserving.
# pytest -v
5. Expected Files Changed
| File | Action | Why |
|---|---|---|
ARCHITECTURE.md |
Created | A real architecture decision record documenting resolved and unresolved decisions. |
docs/sessions/session-40/index.html |
Created | This session document โ Layer 6 gate. |
6. Commit Checkpoint
Once the lab is complete and you can explain every line, make this exact commit:
git add ARCHITECTURE.md docs/sessions/session-40/index.html
git commit -m "session-40: conduct a full architecture review and document key decisions"
7. Code Review Checklist
Go through your code line by line and check each item:
8. Post-Coding Quiz
Same 5 questions. Take it again now that you have written and run the code. You need 4/5 to mark this session complete.
What are the essential components of a good Architecture Decision Record (ADR), based on this session's format?
Why is it valuable to document that Session 28's repository pattern was chosen SPECIFICALLY to support later testing (Session 35) and later real-API integration (Session 42), rather than just noting "we added a repository class"?
Reviewing the prop drilling problem from Session 39, what should an honest architecture review document about it?
Why does this session explicitly re-run the full test suite as one of its checkpoints, given that Session 36 already ran it after the package reorganization?
What is the value of explicitly asking "what would I do differently if starting over" as part of this review, rather than only documenting decisions as unquestionably correct?
9. Reflection Questions
Think through these after the post-quiz. No right answer โ they are for discussion.
- If you were handing this project to a new developer, which single ADR would be most valuable for them to read first, and why?
- What is one decision made earlier in this curriculum (Sessions 1-35) that you now, in hindsight, might have made differently? Why?
- Why does documenting a KNOWN limitation (ADR-003) honestly build more trust in a project's documentation than only ever documenting successes?
- How does the discipline of writing an ADR relate to the "What We Learned" section that has closed every single session in this curriculum?
10. What Breaks If This Knowledge Is Missing?
- Lost institutional knowledge: Without documented reasoning, future decisions about whether to change the repository pattern, the package structure, or address prop drilling would have to be re-derived from scratch, or worse, made without understanding the original tradeoffs at all.
- Real-world file and network work (Layer 7): The next layer adds real files and a real API โ genuinely new external dependencies. Reviewing the architecture now, before adding more complexity, ensures the foundation is well-understood before building further on top of it.
- The capstone review (Session 44): This session's ARCHITECTURE.md becomes a key artifact referenced in the final capstone review, which walks through the entire project end to end.
11. What We Learned
Python concept mastered: Writing Architecture Decision Records that document not just what was built, but why โ including honestly documenting known, unresolved limitations.
Unlocks: The project now has a durable record of its own reasoning, and Layer 6's structural work is confirmed complete and behavior-preserving via a full passing test suite.
Next session: Session 41 โ File I/O Deep Dive. Layer 7 begins. We finally touch the real world โ real files and, soon, a real network API โ building on a now well-understood, well-tested foundation.