Concept Explanation
Architecture sounds like a big word, but in small Python scripts it means something simple: put each responsibility in the right place. Data should be shaped in one place, formatting should happen somewhere else, and printing should stay near the edge of the program. In this lesson, you will build a tiny profile formatter. The real point is not the profiles themselves. The point is learning how to separate data from presentation so your script stays readable when it grows. A lot of beginner code becomes messy because everything happens in `main()`. That works for five lines, then quickly turns into a pile of mixed logic. Here, you will practice a cleaner layout: one function prepares data, one function formats it, and `main()` only connects the pieces. By the end of this lesson, you should be able to: • explain why printing belongs at the edge of the program, • separate data structure decisions from output formatting, • describe how this script could later swap fake data for database rows or API results. Why this matters: good architecture is not about making code look advanced. It is about making code easier to change without breaking unrelated parts.
Where to Put the Code
- Define color and position variables at the top.
- Create shape drawing or placement logic in the middle.
- Render output (print, canvas, SVG, or styled block) at the end.
Command Reference
- Keep `main()` small; it should connect pieces, not hide all the business logic.
- Use one function to load data and another to format data so each part stays easy to change.
- Return strings from rendering functions instead of printing inside them whenever possible.
- Choose names that describe the role of each function, not just what type of value it returns.
Step-by-step Guide
- Run the script once and notice that `load_learners()` prepares data while `render_profile_card()` controls presentation.
- Add one more learner to the list and confirm that no other function needs to change.
- Change only the formatting string in `render_profile_card()` and verify the data loader stays untouched.
- Add a new field such as `level` or `country` to the TypedDict and update the renderer carefully.
- Write one short note explaining why printing inside `main()` is cleaner than printing inside the data-loading function.
Practice Exercises
- Rewrite the example with a dataclass instead of TypedDict and decide which version feels clearer to you.
- Explain why storing preformatted strings inside the raw data would make future changes harder.
- Imagine the data later comes from SQLite or an API. Which function should change first, and which one should stay the same?
Coding Challenges
- Add a second renderer that prints a shorter summary line, while reusing the same data source.
- Create a small filter step that only prints learners with scores above 900 without mixing the filter logic into the renderer.
Mini Practice Tasks
- Draw three boxes in your notes: data, formatting, output.
- Say the flow aloud once: load data, format one item, print the result.
- Keep one rule from this lesson: loaders load, renderers render, main connects.
Common Mistake
Mixing x and y axes or using wrong coordinate origin causes shapes to appear in unexpected places.
Real-life Mini Challenge
Draw one square, one triangle, and one circle, then move X marker 2 steps right and 1 step down.