A small, repeatable workflow for turning saved code into something you can explain, change, and reuse.
Your saved repositories probably contain a very impressive future version of you.
That person understands distributed systems, builds useful AI tools, contributes to open source, and somehow has a free Saturday for every README.
Meanwhile, actual you has work, messages to answer, and another excellent repository that apparently needs saving immediately.
I have a soft spot for that optimism. Finding a good resource feels lovely. You can almost picture the things you will build with it.
But a saved folder can quietly become a collection of promises. You recognize more project names without getting much more comfortable inside unfamiliar code.
So I prefer smaller commitment here like just choose one repository, follow one behavior through it, make one change, and leave with something you can explain.
You don’t need a heroic weekend; you need a finish line that fits into your actual life.
Give the repository a job before you open it
Learn this codebase is a very generous assignment. It can absorb an entire evening and still claim you have barely started.
Choose a question with an observable answer instead: where does this page get its data, what determines the output order, or how does an invalid input reach an error message?
Now you have a reason to open particular files — and permission to leave the others alone.
For a concrete example, take the Flask tutorial app inside the official repository. It is a small blog application with application code, templates, and tests. We can use that example folder without trying to understand Flask’s entire implementation.
Our learning task will be simple: understand how the homepage chooses the order of its posts, then change the local example to show at most three.
This is a proposed practice exercise, not a missing feature the maintainers need us to submit.
If Python is not your thing, keep your own stack. Choose a small example app with setup instructions, an observable output, and a nearby test. A component library’s demo or a data pipeline’s sample job can serve the same purpose.
Before committing, check three things:
You can name the behaviour. It should fit in one sentence without the word everything.
You can find an entry point. A route, command, component, notebook cell, or documented example is enough.
You can observe a result. You need some way to compare what you expected with what actually happened.
A huge star count cannot answer those questions for you. A modest example folder sometimes can.
Follow one thread through the code
Opening files alphabetically is how a quick look develops a second season.
Start with the behaviour you chose and follow its path. For our example, the documented homepage flow leads from the request to the index function in flaskr/blog.py, through a database query, and into the blog/index.html template.
The query orders posts by their creation timestamp, descending. The template displays the returned posts. Those are different responsibilities, and separating them gives us a useful map.
You do not need to read the authentication system just because its folder is nearby.
Write a short trail in your notes:
Entry: the homepage request.
Decision: the query that chooses which posts come back and in what order.
Output: the template that turns those posts into the page.
Nearby check: the homepage coverage in tests/test_blog.py.
Keep the filenames in your notes, because tomorrow, understood the backend will be considerably less helpful than the path that got you there.
Predict something before pressing Run
Before running the unchanged example, write down what you expect. With three posts created at distinct times, the newest should appear first.
Follow the example’s README for setup and match the code version to the documentation version. Record the tag or commit you used. Otherwise, a later change on the main branch can make yesterday’s notes confusing.
Then compare the actual behaviour with your prediction. If they differ, investigate the difference before changing anything.
Maybe your sample timestamps are identical. Maybe you opened a different database. Maybe your mental model needs work. Each possibility is more useful than declaring the repository confusing and going shopping for another one.
A working page is a starting point. Being able to predict why it looks that way gives you something you can build on.
Make one change with a clear finish line
Now give your understanding a little resistance.
In a local branch, change the example so the homepage shows at most three newest posts. Keep all stored posts intact. Leave creation, editing, and authentication alone.
Before editing, describe the expected behaviour in plain language:
With no posts, the page shows no posts.
With two posts, it shows both, newest first.
With five posts created at distinct times, it shows the newest three.
Posts omitted from the homepage remain in the database.
This gives your change a boundary. A redesign, a new database, and a fresh frontend framework do not need to sneak through it.
Find the smallest place to make the change and explain why it belongs there. Limiting results in a database query and fetching everything before trimming the display may produce the same small screenshot, but they do different amounts of work.
You do not need a performance benchmark to notice that distinction. You do need to avoid claiming a speed improvement you have not measured.
Let the checks challenge your explanation
Read the existing checks before adding your own. In this example, tests/test_blog.py includes a homepage test that looks for expected content. That gives you a place to understand the project’s testing conventions.
For your practice change, add a focused check that would fail if the limit disappeared. Check which posts are shown, their order, and whether the underlying records remain available.
Use distinct timestamps initially. Equal timestamps introduce another decision: which post wins the tie? Record that as a follow-up rather than quietly pretending creation time defines a complete order.
Finally, inspect your diff. Every changed line should have a reason connected to the behaviour you chose. If you cannot explain part of it, that is where the next learning session begins.
Keep this as a local learning change unless it solves a real project need and follows its contribution rules. Maintainers do not need homework disguised as a pull request.
Use AI to find the door, then walk through it
You can absolutely get help; turning this into a purity contest would make the whole exercise unnecessarily miserable.
I prefer narrow requests that leave room to do the reasoning:
Locate the function that handles the homepage and show me the relevant file path.
Explain this expression using the surrounding function.
Suggest an edge case my proposed check would miss.
Challenge my explanation of why this change belongs in the query.
Ask for file references and inspect them. If the assistant hands you a beautiful description of a function that does not exist, the description does not get to stay in your notes.
Before accepting a patch, make your own prediction about what it will change. Afterwards, explain the diff without reading the assistant’s summary.
When that feels difficult, reduce the scope. One function you can reason about is a perfectly respectable outcome for an evening.
Leave yourself a receipt for the learning
At the end, capture a few lines that your future self can use. You can copy this structure into an ordinary note:
Behaviour: what I tried to understand.
Path: the files and functions involved.
Prediction: what I expected before running the example.
Change: what I altered and why.
Evidence: the output or check I actually observed.
Limit: what remains uncertain or outside this change.
Keep predicted and observed results separate. A planned check is not a passing check, and a convincing explanation is not evidence that the program behaved that way.
For the example above, a useful limitation might be that equal creation timestamps still need an explicit ordering rule. Another might be that a three-post homepage hides older content because we have deliberately not built pagination.
Those are excellent things to notice. They show where the tiny exercise ends and the next design decision begins.
You can spread this over three short sessions: trace and run the original behaviour, make and check the change, then explain it the next day. Set a time limit that fits your schedule. This is a suggested routine, not a promise that every repository takes the same amount of time.
If setup consumes the first session, write down the actual blocker. Choosing a smaller example is sensible. Repeatedly changing repositories without recording why is how the same evening keeps happening.
Check what travels with you
Once you can explain the change, close the repository and sketch the behaviour from memory. Reopen the files to correct the gaps rather than polishing a story around them.
Then try one variation: a different output limit, an empty result, or a tie in the ordering. If you want a separate context, choose a small unfamiliar practice problem and use the same predict, check, explain routine.
The useful question is whether you can carry the reasoning somewhere new. Remembering which line you copied is a much smaller achievement.
For an ML repository, your thread might follow one input through preprocessing to a prediction. For a data project, it might follow one row through a transformation. Keep the same finish line: an observable behaviour, a deliberate change, and an honest account of what happened.
Give one saved idea an actual afternoon
You can keep your collection. Some repositories are references; some are inspiration; some can wait until a real project needs them.
For the next learning session, though, choose just one and give it a specific job. Follow a path, make a small change, and leave a note that proves what you now understand.
I would much rather finish with one useful explanation than another beautifully organized folder of things to learn someday.
Your future self already has plenty of recommendations. Give that person something you can use.
Give a follow and subscribe for practical ways to get more confident with the code, projects, and conversations that shape an engineering career.
~ Emily




Top comments (0)