The Art of Understanding Code You Didn’t Write

cover image

If you were to quietly observe a software engineer at work, you might be surprised. You’d likely see them reading, tracing, and scrutinizing code far more often than they are writing it. This is our open secret: we are perpetual readers in a profession that glorifies writing.

Yet, while we dedicate years to mastering languages, frameworks, and numerous shiny new technologies to advance our career, we rarely, if ever, are taught how to efficiently decipher a codebase we didn't build. This skill: the art of understanding foreign code; is one of the most crucial yet under-discussed disciplines in our field. It's the foundation for everything; from onboarding into a new role, or debugging a critical issue in a library, to making a meaningful contribution to an open-source project. Ultimately, this ability is what separates developers who survive from those who truly thrive.

I had the pleasure of exploring this very topic at the Open-Source Community Festival 2025 (OSCAFest ’25), framing it not just as a technical skill, but as a foundational catalyst for growth. Source diving, as it's commonly called, is more than a means to an end. It’s a career advantage that builds profound problem-solving skills and deep technical credibility. It fosters autonomy within a team and, on a broader scale, cultivates a more sustainable and inclusive open-source ecosystem by empowering a community of capable, self-sufficient contributors.

Why Source Diving is Your Unfair Advantage

We often frame "reading code" as a necessary chore, a prelude to the real work of writing it. This mindset sells short one of the most powerful practices in software engineering. Over the years, I've come to see source diving not merely as a technical skill, but as a professional multiplier.

On a personal level, it directly sharpens your core competencies: your ability to debug complex issues deepens, your understanding of software architecture becomes more intuitive, and your problem-solving skills become more creative. This isn’t just theory; it’s practical experience that delivers real-world career gains. You onboard faster, gain greater autonomy, and build unshakable technical credibility because your insights are grounded in the reality of the code.

This impact ripples outward. Within a team, a culture of effective source diving creates a resilient, self-sufficient unit. In the open-source community, it's nothing short of essential. A community of engineers who can navigate code independently reduce the constant support burden on maintainers, leads to higher-quality contributions, and ultimately forges a more sustainable and inclusive ecosystem for everyone. Source diving, therefore, is more than reading; it's the foundation of effective collaboration and growth at scale.

How Do You Quickly Get Up To Speed In Any Codebase?

Navigating a new codebase can feel like finding your way through a labyrinth. The key is to approach it systematically; starting broad and gradually narrowing down to the details. Here’s a five-step strategy to help you move from confusion to confidence.

  1. Skim the Big Picture. Begin with the README.md, architectural notes, or official documentation. Don’t worry about implementation yet; the goal is to understand what the system does, who uses it, and why it exists. That high-level map makes the deeper dive meaningful.
  2. Identify the Blueprints. Every well-structured project has architectural blueprints: the key files and directories that define its structure. These directories reveal how responsibilities are divided and give you a mental model of where things live and how they connect.
  3. Let the Tests Talk to You. Tests are often the most reliable form of documentation. Unit tests will show you how individual components are supposed to behave in isolation, while integration and end-to-end tests reveal how they work together. Reading them provides examples of expected inputs, outputs, and edge cases.
  4. Kick Down the Entry Point. Find the main gateway into the application and start tracing execution from there. Step through the runtime flow to see how requests, events, or tasks propagate. The execution will branch; but you don’t need to follow every path at once. This top-down walkthrough connects high-level architecture to the concrete program logic and validates your mental model.
  5. Trace the Critical Data Flow. Data is the lifeblood of any application, and its transformation is the core business logic. Identify a single, critical piece of data (a configuration value, a record, or an event) and shadow its entire lifecycle. Trace it from its entry point through every module, service or method that validates, mutates or transforms it, until it reaches its final state. This reveals the system's true workflows, dependencies, and implicit contracts more clearly than any code reading could.

Exploration Techniques: From Passive Reading to Active Investigation

Once you have a basic map, it's time to become an active archaeologist of the codebase. These techniques move you beyond reading and into deep, interactive understanding.

  1. Ask Git to Spill Its Secrets. The commit history is a narrative of the project's evolution, containing context you won't find elsewhere. Use git log --oneline to see the broad story, then git blame on specific files to understand why a line was changed by reading the commit message. This can reveal the original intent behind a piece of code, identify fragile areas that are frequently patched, and introduce you to the key contributors whose work you should follow.
  2. Wield the Debugger Like a Weapon. Stop guessing about the runtime state and start knowing it. Set breakpoints at the entry points and key methods you've identified, then run the code. Watching the program's state mutate in real-time is the most definitive way to verify your mental model, revealing the exact execution path and untangling complex, conditional logic.
  3. Draw the Map, Find the Treasure. If no up-to-date architectural diagrams exist, generate them using tools like GitDiagram rather than drawing them manually. These visualization tools perform static analysis to automatically produce component diagrams, class hierarchies, and dependency graphs for the codebase. The resulting visualizations make patterns immediately apparent that might take hours to discern from code alone, revealing central hubs, peripheral components, and complex dependencies at a glance.
  4. Turn Logs into a Crime Scene Report. Logs are the forensic evidence of your application's runtime behavior. Instead of seeing them as just error messages, read them like a detective. Trace a single operation or system task through the log files by following its unique correlation ID or timestamp. Trace a single transaction or user journey through the log files by following a unique ID or timestamp. This shows you the precise sequence of events, service interactions, and data changes across the entire system, often highlighting bottlenecks and failure points that are invisible in the code.

Sustain & Grow: Making Source Diving a Career-Long Habit

Mastering a single codebase is a project; mastering the skill of understanding any codebase is a career. These practices transform source diving from a reactive task into a proactive discipline for continuous growth.

  1. Consistent Deep Dives. Schedule regular, non-urgent time to explore parts of your codebase you don't normally touch. This could be a two-hour block every week dedicated to reading a subsystem you depend on. This proactive exploration builds a broad, foundational understanding that pays massive dividends when a future bug or feature request lands in that exact area, turning a potential crisis into a familiar task.
  2. Upgrade Radar. Whenever a dependency in your project gets a significant version upgrade, don't just accept the PR from dependabot or perform the tasks relating to the upgrade. Read the release notes and changelog. Skimming the pull requests or commit history for the new release shows you not just what changed, but how and why it changed. This practice deepens your understanding of the tools you use and often uncovers best practices, performance improvements, or potential breaking changes long before they affect you.
  3. Source Peek. Make a habit of quickly jumping into the source code of your external libraries and frameworks when you use them. Instead of just relying on documentation, a quick "peek" under the hood to see how a function is implemented clarifies edge cases, reveals underlying mechanisms, and often answers questions that documentation leaves ambiguous. This turns black-box dependencies into transparent and understandable tools.
  4. Inside the Minds. Actively read code written by the recognized experts in your language or framework. Study the source code of well-maintained open-source projects or internal modules written by senior colleagues on your team. Read pull requests from codebases in your organization, asking questions for clarity when you don't understand something or suggesting alternative approaches. Analyze their architectural choices, naming conventions, and patterns. You are learning from the best, absorbing their techniques and raising your own code quality and design sensibilities through osmosis.
  5. Tiny Time, Big Returns. You don't need a massive time investment to benefit. Get in the habit of spending just the last 15 minutes of your day reading a small piece of code. It could be a PR from a teammate, a utility function you frequently use, or a module you're curious about. This small, consistent investment compounds dramatically, steadily expanding your knowledge of the codebase with minimal effort and making you a more versatile and effective engineer.

From Reader to Contributor: Crossing the Chasm

Understanding a codebase is the first step; positively impacting it is the next. This transition from a passive reader to an active contributor is a skill in itself, built on strategy and communication.

  1. Start Small. Your first contribution should be a low-risk, high-clarity task. Look for well-documented bug fixes, minor documentation improvements, or "good first issue" labels. At work, productivity improvements are usually a hit and work focused on reducing local setup time are excellent candidates. A small, successful contribution builds your confidence, proves your competence to maintainers or colleagues, and helps you learn the project's contribution workflow without the pressure of a major feature.
  2. Play Safe. Before making logic changes, always ensure you can validate your work. Write or update tests that confirm the bug exists and that your fix resolves it. A pull request with passing tests is far more trustworthy and easier for maintainers to review and merge, demonstrating that you're responsibly solving a problem, not just changing code. Some projects require tests as a PR requirement, others don't; but you can hold yourself to that standard regardless.
  3. Communicate Clearly. Contribution begins long before you open a pull request. Engage in the issue tracker: ask clarifying questions, summarize your understanding of the problem, and outline your proposed solution. This proactive communication ensures you're building the right thing and shows respect for the maintainers' time, preventing wasted effort on misunderstandings. At work, extend this same proactivity to planning cycles by asking to be assigned to specific features and projects during quarterly planning when possible.
  4. Show & Tell. When you're ready to contribute, your showcase begins with your commits. Write meaningful commit messages following the project guidelines. If there are no commit guidelines in place, follow the conventional commits guidelines by default. When opening your pull request, use the project's pull request template if it exists. Craft a clear title and a detailed description that explains the what, the why, and the how. Link to the relevant issue and annotate your code changes with comments in the PR to explain your reasoning. Make the review process as easy as possible for those who will evaluate your work.
  5. Engage & Adapt. Treat code review not as criticism, but as a free masterclass from the project experts. Respond to feedback promptly and graciously. Be prepared to defend your decisions logically, but also be willing to adapt your code to fit the project's style and conventions. This collaborative spirit builds rapport and is the fastest path to becoming a trusted contributor in the community.

The Journey From Here

The ability to understand code you didn't write isn't just another skill to add to your resume; it's a fundamental shift in how you approach software engineering. It transforms you from someone who merely consumes documentation into someone who can dive deep, ask better questions, and contribute meaningfully to any project you encounter. Whether you're navigating your company's legacy systems, exploring a new framework, or making your first open-source contribution, these techniques will serve as your compass.

Man can learn nothing except by going from the known to the unknown

– Claude Bernard

Remember this profound wisdom: "Man can learn nothing except by going from the known to the unknown". Every codebase you explore expands your understanding, sharpens your intuition, and makes the next dive easier. Start small, stay consistent, and watch as this practice compounds into one of your most valuable professional assets.

You can view the slides from the talk here. If this guide resonated with you or if you have your own source-diving techniques to share, I'd love to continue the conversation. Connect with me on X/Twitter or LinkedIn; share your experiences, questions, or the "aha" moments you've had while exploring unfamiliar code. Let's build a community of developers who don't just write great code, but truly understand it.