Hey friends! In this post, I’ll share some thoughts I have concerning the conscious reading and study of source code. In my opinion, reading code is a process which can help you become a more proficient software developer. It has undoubtedly improved and influenced my software development skills.
Should I Read Source Code?
Yes, you should! The good news is, you’re already doing this, day in day out when developing software. I’ve seen various statistics over the years showing that a high percentage of our time as developers is spent reading code, rather than writing it.
When you start on a new feature or on a bug fix, you have to begin by understanding how existing code works. You may tackle this from the unit tests which should clearly describe the desired behaviour of existing code, but often you will end up delving into the implementation code as well.
For this post, I consider this form of reading a given. What I’m recommending here is that you make reading code a more conscious process and most importantly read code that you have never seen before. Reading code that you originally wrote or that you have worked on in the past is less likely to impact and inform your future coding skills than exposing yourself to previously unseen code.
Becoming better at reading and interpreting code will help you when you tackle new features or bugs. You will be able to scan relevant code for the information you need to begin work more quickly. Much as we can train ourselves to read books more quickly, we can get quicker at reading and comprehending software code.
Why Spend Time Reading Source Code?
Let’s think for a moment about how young children learn to read and write. In the book, “Young Learners” by Caroline Linse, she states that you need to read a word before you can write it. This sounds pretty logical to me. By first reading words in context, you begin to understand their meaning and appropriate use.
By reading books, you extend your vocabulary and pick up techniques which you can later apply to your writing. This is just one reason we study literature, through our formative years in school. Ultimately, as we read more, we learn what works and what doesn’t.
The same then must surely be true for software code. I’m a C# developer, but whatever your programming language of choice, there are many rules to the syntax and keywords that you can use. A few simple keywords and concepts can be combined into infinite possibilities for the code you produce. There are many ways to achieve the same outcome, just as there are many ways of saying or writing the same thing. While all may technically accomplish the same goal, some tend to be more appropriate and easier to comprehend than others. In code, some techniques may be more efficient than others too.
Have you even come across code written by a co-worker, or even yourself, which is hard to read? I know I have! Hard to read code is hard to maintain and can impede the development process. Just as in language, where a poorly constructed paragraph can be confusing and difficult to absorb, code can suffer the same fate. Those tricky paragraphs or blocks of code require multiple read-throughs to parse the meaning and intent. By learning to read more code we can also improve our writing skills to avoid producing unintelligible code.
Improving one’s skills requires some deliberate effort. Studying the work of those who are more experienced than yourself will influence your own code in the future. Doctors, as just one example, go through years of training even once qualified to practice medicine. They work alongside more experienced doctors, watching at first, before attempting procedures themselves. Great doctors will also study papers from those in their profession to learn about new techniques and approaches.
This is something I feel we do less consistently in software development. Some teams may manage this better than others. Pair or mob programming is just one way to share skills between developers. My theory here is that another vital technique for improving your own skills is to regularly expose yourself to new code as part of a healthy continuous learning cycle.
A particularly relevant quote which summarises what I’m trying to say in this section is from the great author, Stephen King.
“Can I be blunt on this subject? If you don’t have time to read, you don’t have the time (or the tools) to write. Simple as that.”
― Stephen King, On Writing: A Memoir of the Craft
What Source Code Should I Read?
If you’re still with me, I hope you’re sold on the concept of reading code as part of your routine to help you continually improve as a software developer. The next logical question then is what code should you be reading?
At a broad level, I don’t think it matters. The sheer fact that you are reading code is the important thing. Remember, though that all software code is not created equal. Some of the source code that you read will be markedly better written than other code. That’s perfectly fine. Both good and bad code can help you refine your own approaches.
You don’t have to agree with the code for the reading of it to be beneficial. Reading “bad” code can be hugely influential and informative. If you read some code and dislike the style or you spot a functional flaw, that’s fine. In doing so, you have identified a pattern or approach you don’t like, or that doesn’t work. This can save you time when writing your own code as you’ll hopefully avoid repeating the same mistake.
That said, you also want to be reading code which adds new and more solid techniques or approaches to your coding vocabulary. I’ll discuss some sources of code in the next section.
Reading code from multiple sources is crucial as you’ll consciously (and subconsciously) learn patterns which repeat across the various sources. When you see the same techniques, patterns and code trends used in many places, it’s more likely a well-proven approach.
I focus my time on studying the internals of some of the C# libraries which I use most often. Not only does this mean I improve my skills by reading code in general, but also I learn about the inner workings of those libraries which can further inform my use of them. It’s a double win.
Something I don’t do frequently enough, but I intend to attempt, is to read code written in languages that I rarely or never use day-to-day. Becoming extremely familiar with one software language is undoubtedly useful, but extending your range of languages will also have benefits. If you think about it, many of us see the benefit of learning a second, and perhaps even third, spoken language. This makes communication with people from other countries easier and will often further add to our knowledge and use of our own native language.
Not only will second programming languages extend your career options, but they will also make you appreciate the similarities and differences from your primary language. We often see features in one language, influence another. C#, for example, has more and more functional syntax evolved first in F# appearing in each release. Some .NET features, such as Channels were influenced by Go. We can prepare ourselves for these features by having one eye on that second language.
Where Can I Find Good Source Code?
There are many potential sources for code. To name a few…
This is a vast resource of code written in practically every language. Where better place to start? My personal favourites which have influenced my C# code, are the ASP.NET Core and CoreFx libraries from Microsoft. I find diving into the high-quality and considered code from the framework teams to be a great way to learn.
Frameworks like these are excellent sources to review since the code has high standards and is itself informed by the coding patterns used at Microsoft. I have personally learned enormously from reading and learning how the team structure extensible framework code. Just recently, I spent some time thinking about the Task Parallel Library and discovering more about the use of CancellationTokenSource in some code I was writing. By studying places where Microsoft use this type, I was able to appreciate conventional approaches which they use in their code.
GitHub has reasonable search functionality, so without even downloading the code, you can navigate through a repository and learn directly in the browser. For deeper dives, I prefer to clone the repository so that I can navigate the code in more detail.
I also like to widen my coding vocabulary by looking into the source of libraries I use, such as Polly and MediatR. This exposes me to other coding styles that further broaden my appreciation of how code can be written. I don’t necessarily like or agree with the structure of all code I read, but even then I am more consciously recognising what my own code preferences are. When writing code, I am more deliberately able to dodge potential traps and poor design decisions.
The internet is stock full of excellent blog posts on software development. You are sure to find many useful technical blogs which include sample code snippets. These are excellent as they are often small chunks of code which may be easier to digest in a brief sitting. Usually, the code is annotated or explained in the blog post so you can verify your analysis of the code against the author’s intent.
There are many great technical books available in both e-book and physical print formats. These two will contain code and clear explanations of how/why it works. In the last year, I learned a great deal about writing high-performance code by reading “Pro .NET Memory Management” by Konrad Kokosa.
You’re sure to find some great and some not so great code examples on StackOverflow. Here the question and answer format can be handy as you get to observe multiple opinions of different coding styles. To focus on code more specifically, check out the Code Review area on StackExchange too.
Internal Source Control
Earlier, I said an essential part of deliberate learning through reading code was exposing yourself to code that you have never seen previously. I think that is extremely important, but I do want to add that you can learn a lot about work codebases too. There are sure to be projects and repositories you’ve seldom worked with. By taking a little time to understand them, you can get a feel for how those work. Should you ever end up supporting them, you’ll have a real head start and be more familiar with code than perhaps even the original authors.
As a new member on a team or when joining a new organisation, you can swiftly get up to speed on the internal coding standards and common patterns by studying the existing code. This will expedite your onboarding and guide your personal development.
This is by no means an exhaustive list. Wherever you find code, take a little time to read and appreciate it at a deeper level than you usually would. You won’t regret investing the time to improve your software development skills in this way.
How Should I Read Source Code?
I’m sure everyone will have their own preferences within this section. Ultimately do what feels right for you! I’ll share some of my own approaches here which you may apply to kick-start your code reading adventures.
I typically like to focus on code which either does something that I want to replicate the style of in the future, or which deepens my knowledge of code I use daily. As I said earlier, this adds double the return for the time I invest.
I tend to start work in GitHub. This strips me of my usual tools and centres my attention on truly understanding what is happening in the code. I try to find a high-level abstraction as a starting point and then gradually dig deeper into the internals. I like to make notes in OneNote as I study the code, describing the flow and how the code works. These are short-form notes. This process is less about having a reference, although that can be useful, than it is about embedding the knowledge into my memory. By describing it in writing, I find that it sticks with me much longer.
Navigating code and forming a mental picture of the logical flow is a handy skill. If you can learn this through reading code, it’ll pay dividends when you’re next trying to fix a critical bug under pressure.
Once I have an overview formed the next step is to go deeper. For this, I tend to clone the repository so that I can bring it into an IDE or VS Code. There I can use the code navigation features to move around more swiftly and really delve into the behaviour of the code. At this point, I’m trying to understand why code has been written as it is. I like to think about how I’d have chosen to approach a problem and contrast it with the actual implementation. Is the author’s approach better or more efficient? Should I file it away for when I next face a similar requirement?
Often the code may use APIs that I’ve never discovered when writing code. I find that when I’m coding I will tend to use those APIs which I’m more familiar with. These may not be the best methods to call or classes to rely upon, but as I know no alternative, I keep using them. After reading some code, if there are APIs I haven’t used before, I study the description and method signature(s) to understand their designed use. This extends my code vocabulary.
This second stage also improves my skills of working with tools such as my IDE. I find tricks and shortcuts to save time when navigating the code. Something I do often is to pull out a class into a window on my second monitor so I can follow code flows more quickly. This is something I now do often when I’m writing code as well.
I’m also on the lookout for language features or patterns I don’t recognise. I quickly learn about the features of the latest version of C# by seeing them used in the wild, so to speak.
What if I Don’t Understand the Code?
That’s absolutely fine! At first, you won’t understand everything you read, and that is, in fact, our goal here. You want to expose yourself to new APIs or new syntax in the code which you read so that you further your own code vocabulary. Reading code you understand easily, much like reading a simple book, is not going to expand your writing skills.
Try to break things down into smaller chunks to work through in your head. What is the code doing and also why has it been written that way? Has the author used an approach to solving something you had not previously considered? As you come up against language syntax or keywords you don’t understand, stop and search for the documentation. Armed with an actual use case, often the documentation will make sense in the context you are approaching it from.
Similarly, when you encounter framework APIs which you have never used before, visit the code documentation if there is any. For the Microsoft libraries, all public methods include XML comments. You can either read these directly or visit the .NET API Browser to reach about a class or method.
The significant thing about consciously reading code is that it’s your own time and that your are making an investment in your skills. Contrast this to when you are in a codebase, up against a deadline, trying to finish a bug fix or feature. You will rarely have the time to extend beyond the boundaries of the code you are directly working with. That situation is much less conducive to learning.
What I Have Learned from Reading Source Code
I’ve learned so much from studying code, which is why I’m so enthusiastic about promoting this practice. Modern-day craftspeople will often study the work of masters of their craft. By doing so, they hope to one day attain their level of skill. Developers too can advance their skills by studying from the experts in their field.
For me personally, as a C#, .NET developer, I find a lot of value in studying the Microsoft source code for the .NET Core framework and ASP.NET Core. There are many great developers at Microsoft who have comprehensive expertise of specific elements of the language or runtime.
I’m a self-taught developer, or as I saw someone call it on Twitter recently (I can’t recall who, unfortunately), a community-taught developer. I’ve learned C# through trial and error, in concert with consciously studying code. Just as scholars study great works of literature, there are many secrets to be unlocked by reading great code.
One related resource I recommend for those who are intrigued by software design and want to better their appreciation of the .NET Core framework is available on YouTube. The .NET team publish most of their weekly .NET Design Reviews on YouTube. These are meetings where the team review proposals for API changes to .NET Core. While I can appreciate that the thought of watching a meeting by choice, in your own time may be too much geek for some, it’s a great way to learn. The team on these calls is made up of genuine experts who know the language, runtime and framework so profoundly, it’s quite staggering to observe. By listening to them discuss the proposed APIs you get a genuine appreciation for the considerations that have to be made on such a broad and widely used framework. There are often little gems of insight I gather just by watching these streams.
My goal for this post was to inspire a few readers to consider some more conscious study and reading of code. I honestly believe this has helped me to become a better developer and to learn more about the C# language and the .NET (Core) Framework. Investing a few hours regularly will pay off for you in the future. You’ll have more diverse opinions on coding style and techniques. You’ll understand at a deeper level how the framework you rely on daily actually works, which in turn can inform your use of it. You’ll become faster at reading code, and as a result, those next code changes you have to make will take you less time from the requirement to the completed code.
Thanks for reading!