Reading Code Effectively: An Overlooked Developer Skill • Marit van Dijk & Hannes Lowette
Marit van Dijk and Hannes Lowette discuss why reading code is a critical, yet underdeveloped, skill for software developers. They explore research-backed strategies like structured code reading clubs, leveraging modern IDEs and AI assistants to comprehend complex codebases, and the importance of empathy in code reviews. The conversation emphasizes using tests as documentation and writing clear commit messages to improve collaboration and long-term maintainability.
Developers spend a significant portion of their time—up to 60% according to research—reading and trying to understand existing code, yet traditional computer science education focuses almost exclusively on writing code. This disconnect means a critical skill for professional software development is often left underdeveloped.
The Science of Learning to Code
Marit van Dijk references the work of Dutch computer science professor Felienne Hermans, who highlighted a 1992 study on teaching programming. The study found that students who learned by reading code accompanied by explanations of the design choices were better at reproducing programming concepts than students who only wrote code. This insight spurred the creation of “Code Reading Clubs,” an initiative to practice the skill of code comprehension deliberately.
Lessons from a Code Reading Club
A code reading club provides a structured environment to practice understanding unfamiliar code. The experience offers several benefits:
- Diverse Perspectives: Members with different roles (developers, testers, coaches), programming languages, and experiences notice different things in the same piece ofcode. This highlights that what is clear to one person may not be clear to another, fostering empathy.
- Structured Exercises: The club uses specific exercises, such as the “first glance,” where participants take one minute to identify the very first thing they notice. This provides an immediate entry point into the code, even if it’s unfamiliar or intimidating (like a language you don’t know).
- Building Confidence: Deliberate practice in a supportive setting helps developers feel more confident when faced with large, complex, or poorly documented codebases in their daily work.
Empathy in Code Reviews and Collaboration
The act of reading and interpreting another person’s code is deeply connected to empathy. When reviewing code, it’s crucial to assume the author wrote it to the best of their ability given the constraints they faced—time pressure, existing technical debt, personal circumstances, or knowledge gaps at the time.
Rather than simply pointing out flaws, a more constructive approach involves acknowledging well-designed parts of the code before suggesting improvements. This mindset is essential for effective pair programming, mentoring junior developers, and conducting code reviews that motivate rather than discourage.
Leveraging Tools to Understand Code
Felienne Hermans’ book, “The Programmer’s Brain,” identifies three primary reasons code can be confusing: a lack of knowledge, a lack of information, or a lack of mental processing power. Modern IDEs and other tools can help mitigate these challenges.
- Lack of Information: IDEs provide features like “quick documentation” and “quick definition” that allow developers to inspect classes or methods without navigating away and losing context. Tools to locate a file within the project structure also help maintain a mental map of the codebase.
- Lack of Processing Power: When code becomes too complex with nested loops and multiple state changes, a debugger is invaluable. It helps visualize the state of objects and variables at any given point, confirming whether the code behaves as expected.
- AI Assistants: Modern AI tools integrated into the IDE can provide crucial context. A key feature is the ability to summarize a commit, explaining what changed in plain language. This is especially helpful for large or complex commits. AI can also generate draft commit messages, which helps overcome writer’s block and encourages developers to explain the why behind a change, not just the what.
Tests as Living Documentation
One of the most effective ways to provide context for code is through well-written tests.
- Clarifying Intent: Tests should explain the intended behavior of the software. A good test name, following a pattern like Arrange-Act-Assert or Given-When-Then, makes its purpose clear. When a well-named test fails in the future, it’s much faster to diagnose whether a bug was introduced or if the system’s requirements have legitimately changed.
- Reproducing Bugs: Writing a test that reproduces a bug forces you to fully understand the problem before attempting to fix it. This test then serves as a regression check to ensure the bug stays fixed.
- Designing Better Code: Thinking about the code’s behavior from a testing perspective first (Test-Driven Development) often leads to a cleaner, more modular design because you must consider how to instantiate and interact with components in isolation.
By deliberately practicing code reading, leveraging modern tools, and writing clear, well-tested, and well-documented code, developers can become more effective and collaborative.