9

I've realised that my greatest weakness as a programming student is my poor ability to comprehend other people's code.

I have no trouble whatsoever with 'textbook' code, or clearly-commented code, but when given a program of a few hundred lines, containing a dozen or so different functions and no comments, I find it very difficult to even begin.

I know this type of code is what I'm probably more likely to encounter in my career, and I think that having poor code comprehension skills is going to be a great hindrance to me, so I'd like to focus on improving my skills in this area.

What tools/techniques have helped improve code comprehension in your experience?

How do you tend to tackle unfamiliar, uncommented code? Why? What about your technique do you find helpful?

Thanks

Daniel Brose
  • 1,394
  • 10
  • 24
Eilidh
  • 1,354
  • 5
  • 21
  • 43
  • 1
    Stepping through the code with a decent debugger is a good way to get a feel for how it fits together. – Paul R Dec 02 '10 at 15:00

5 Answers5

5

Familiarizing yourself with foreign code

If the codebase is small enough, you can start reading it straight away. At some point the pieces will start falling together.

In this scenario, "small enough" varies, it will get larger as your experience increases. You will also start benefiting from "cheating" here: you can skip over pieces of code that you recognize from experience as "implementing pattern X".

You may find it helpful to make small detours while reading the code, e.g. by looking up a function as you see it being called, then spend a little time glancing over it. Do not stay on these detours until you understand what the called function does; this is not the point, and it will make you feel like you are jumping around and making no progress. The goal when detouring is to understand what the new function does in less than half a minute. If you cannot, it means that the function is too complicated. Abort the detour and accept the fact that you will have to understand your "current" function without this extra help.

If the codebase is too large, you can't just start reading it. In this case, you can start by identifying the logical components of the program at a high level of abstraction. Your goal is to associate types (classes) in the source code with these components, and then identify the role each class plays in its component. There will be classes used internally in a component and classes used to communicate with other components or frameworks. Divide and conquer here: first split the classes into related groups, then focus on a group and understand how its pieces fit together.

To help you in this task, you can use the source code's structure as a guide (not as the ultimate law; it can be misleading at times due to human error). You can also use tools such as "find usages" of a function or type to see where each one is referenced. Again, do not try to fully digest what the IDE tells you if you can't do it reasonably quickly. When this happens, it means you picked a complicated piece of metal out of a machine you don't quite understand. Put it back and try something else until you find something that you can understand.

Debugging foreign code

This is another matter entirely. I will cheat a little by saying that, until you amass tons of experience, there is no way you will be debugging code successfully as long as it is foreign to you.

Jon
  • 428,835
  • 81
  • 738
  • 806
2

I find that drawing the call-graph and inheritance trees out often works for me. You can use any tool you have handy; I usually just use a whiteboard.

Usually, the code units/functions are easy enough to understand on their own, and I can see plainly how each unit operates, but I often times have trouble seeing the bigger picture, and that's where the breakdown happens and I get this "I'm lost" feeling.

Start small. Say to yourself: "I want to accomplish x, so how is it done in the code?" where x is some small operation that you can trace. Then, just trace the code, making something visual that you can look back on after the trace.

Then, pick another x and repeat the process. You should get a better feel for the code every time you do this.

When it comes time to implement something, choose something that is similar (but not almost identical) to one of the things you traced. By doing this, you go from a trace-level understanding to an implementation-level understanding.

It also helps to talk to the person who wrote the code the first time.

San Jacinto
  • 8,774
  • 5
  • 43
  • 58
2

The first thing I try and do is figure out what the purpose of the code is at a high-level -- the detail's kind of irrelevant until you understand a bit about the problem domain. Good ways to figure that out include looking at the names of the identifiers, but it's usually even more helpful to consider the context -- where did you get this code? Who wrote it? Was it part of some application with a known purpose? Once you've figured out what the code's supposed to do, you can make a copy and start reformatting it to make it easier for you personally to understand. That can include changing the names of identifiers where necessary, sorting out any weird indentation, adding whitespace to break things up, commenting bits once you've figured out what they do, etc. That's a start, at any rate... :)

Also -- once you've figured out the purpose of the code, stepping it through a debugger on some simple examples can also sometimes give you a clearer idea of what's going on FWIW...

Stuart Golodetz
  • 20,238
  • 4
  • 51
  • 80
1

I understand your frustration, but keep in mind that there is a lot of bad code out there, so keep your chin-up. not all code is bad :)

this is the process that I tend to follow:

  1. look for any unit tests as they should document what the code is supposed to do...
  2. navigate through the code using code rush / resharper / visual studio shortcuts - this should give you some ideas about the logical and physical tiers involved...
  3. scan the code first, looking for common patterns, naming conventions, and code styles - this should give you insight into the teams standards and maybe the original coders mind set...
  4. as I navigate through the code heirarchy I make a note of the the objects being used... typically with pen & paper drawing a simple activity diagram :
  5. I tend to start from a common entry point, so if it is a UI, start from the view and work your way through to the data access code, if its a service start from the service boundary and work your way through to the data access code...
  6. look for code that could be refactored - if you can see code that can be refactored, you have learned how to simplify it without changing its behavior...
  7. practice building the same thing that you are reviewing, but in a different way...
  8. as you read through untested code, think of ways to make it testable...
  9. use code rush diagnostics tools to find methods that are of high maintenance complexity or cyclomatic complexity and pay special attention to these areas because chances are, this is where the most bugs are...

Good luck

CedricB
  • 1,157
  • 9
  • 23
0

Understand is a terrific code analysis tool. It was in wide use at my previous employer (L-3) so I purchased it where I currently work.

jacknad
  • 13,483
  • 40
  • 124
  • 194