views:

3779

answers:

8

Reading source code is a good way to improve as a programmer, but I've never seen a great explanation of how to do it. We often read textbooks & novels linearly, perhaps taking notes along the way. What do you do when trying to understand how a program works?

  • Try the user-facing version of the program with your own inputs
  • Read the API
  • Trace through the core functions in your head, transforming imaginary inputs
  • Start at "main" and fire off the debugger!

I read the Ruby on Rails source code when I studied the MVC pattern. Many discussions leave out critical parts of MVC as done in Rails:

  • The web server negotiating the communication with the browser (the controller's HTML output has to get to the browser somehow)
  • The dispatcher translating the incoming HTTP request to function parameters and instantiating the controller (you don't want this logic in the web server!)

When people say MVC they really mean "MVC + the subsystem to run it". Since I'd used Rails for a while before digging in, I had an idea of what to expect but this was nevertheless enlightening. But if I had never touched Rails (or MVC) and used it for a few projects I wouldn't be sure where to start.

I'm curious: How do you go about understanding the source for a project?


Edit: Thanks for the comments! To clarify my question: "They say the best way to write well is to read. How do you read literature with the goal of improving as a writer?" The analogous question is:

  • How do you read acknowledged "well-written code" with the intent of improving as a programmer?

With Rails, reading the code demonstrates several techniques (such as "Convention over configuration" -- put files in named directories so the program can automatically find them) and design patterns (MVC) that make the code clean, functional, and elegant. How do you go about extracting these & other lessons from code to improve your own skill?

+3  A: 

Hi,

How I read code depends on two main factors:

  • The task I am performing
  • The size / complexity of the code I need to read

If I'm looking to fix a simple bug the way I read the code is going to be very different than if I want to understand the whole codebase as you seem to with rails. When debugging I'm going to attempt to read the smallest amount of code I need to in order to fix the bug, and while I'm reading it I'm always going to be thinking in terms of what code could be causing the bug.

If I'm looking for a deeper understanding of the code I'd probably start running it through a debugger, line by line. I'd be thinking much more about why the codebase might have been put together the way it was, possible alternatives and whether I like the code or not.

In terms of size & complexity, you can just basically read through small / uncomplex bits of code. If the code in question is large or complex, your best off with a debugger and you may well want to draw some kind of diagram to map out the system, or if the code is just complex but there is not that much of it writing out what it does in pseudo code could be good.

+15  A: 

Generally, just "reading code" isn't particularly useful. You need to really have something specific that you're trying to get out of it, whether it is a bug you're trying to fix, or you want to understand how a particular feature is implemented.

If you jump in thinking "hey, I'll just read through the code" then you'll most likely be falling asleep at your desk in within 10 minutes.

How you approach a body of code has a lot to do with what exactly it is that you want to accomplish. Are you trying to fix a bug in it? Are you implementing code that is using an API? Do you want to add a new feature? Are you curious to know what algorithm the code used to implement feature X?

17 of 26
<i>If you jump in thinking "hey, I'll just read through the code" then you'll most likely be falling asleep at your desk in within 10 minutes.</i>I feel that way about most textbooks as well...
Brian Postow
+7  A: 

Joel had an article about this once that I remember finding useful when I was doing alot of reverse engineering.

shsteimer
Thanks for the link to the article. I am going to try these ideas out on my introductory programming class for a simple selection sort program.
Vern Takebayashi
+1  A: 

Deciding to read the entire of, say, the postfix source code because it's well written will likely teach you nothing.. however, reading source code that does something you need to do, then finding, reading and understanding the bits of code that do this will help..

dbr
+13  A: 

Excellent question. I know of only three ways: implement a feature, fix a bug, or write a test case.

Bernard
You could also write a test case.
Bill the Lizard
agreed and edited (albeit putting words in Bernard's mouth)
Ed Guiness
+1  A: 

A few tools can really help out when reading source. An IDE that will track down references or pull up definitions quickly is one. That way you can take a peek at some other part of the code without getting lost while digging.

Another big help for me personally is to have that context that others have mentioned. Generated documentation and diagrams can make a good companion when reading through source.

Also when reading through a web app in particular, it's helpful to pick a page flow and trace that in code.

hydeph
+1  A: 

I try to understand the relationships between the objects. Often I have to go backwards and forwards between them many times until I can understand what exactly they're supposed to to. That or I just start from main!

Yes Fish...
+2  A: 

It depends (of course), but often I find that the best way to really understand code is not merely reading it, but to interact with it.

I usually begin by writing some small unit tests, to verify that I have understood the behaviour of the code I'm reading. If I am to modify the code later, this has the added benefit of increasing the test coverage as well. (Unless I'm just duplicating already existing tests. I'd still write my own, though, but in that case I'd probably end up throwing them away).

If the project contains unit tests, I find that an excellent place to begin reading. Well written unit tests will show you the big picture - how to instantiate certain objects, what to expect from them (and what will make them fail), what dependencies they have etc.

Also, I often find myself refactoring the code as I read it. Nothing big, usually, just renaming functions, extracting methods and so on. It depends on how well the code reads to begin with, of course, but I find this sometimes improves the readability of the code as well. Fowler calls this Refactoring to understanding (PDF). This works really well together with unit tests, as you can be more confident you havent accidentally broken anything.

Note that refactoring like this, when you don't really know the big picture yet, might not always improve the code - there might be a good reason why the code is written the way it is. So if you are doing this to get into a new project at work, don't check in the code afterwards (at least not without running all the original tests first).

Haugholt