Ask Slashdot: How To Start Reading Other's Code?
BorgeStrand writes "I'm reviving an open source project and need to read up on a lot of existing code written by others. What are your tricks for quickly getting to grips with code written by others? The project is written in C++ using several APIs which are unknown to me. I know embedded C pretty well, so both the syntax, the APIs and the general functionality are things I wish to explore before I can contribute to the project."
If there's a lot of documentation, interpret it like your favorite religious text. Try to hit up some of the old developers from the VCS. Also, I'd like to help :)
Knowing the data structures gives you the ground work for understanding what the code is doing. The data structures are a more direct description of the design decisions.
What are your tricks for quickly getting to grips with code written by others?
For me, it comes down to a lot of mountain dew, techno music, and hours of guru meditation. As you dissect each function, sketch out its relationship to other major functions. I take a two pass approach .. first, just look at the function call outs and the return values and make a rough sketch of the 'scaffolding' of a program. On the second pass, any function that you can't see the obvious application of, or appears obfusciated or complicated, dissect into functional units and sketch out what it does in your notes. I do this by actually physically drawing the relationships using something called a mind map.
Until you get used to it, actually writing it down, even if it's just a bunch of messy arrows to blobs of circled text... it will help job your memory and help things sink in until you have the necessary 'ah ha!' moment.
YMMV.
#fuckbeta #iamslashdot #dicemustdie
I find that going through some key functions (assuming you can find them) and reformatting them to your own liking can be helpful, commenting code along the way. Then if you want to get more aggressive, start cleaning up some code in minor ways that still stay true to the function's meaning. After you've done a bit of that, you should probably have at least a vague idea what's going on.
People who say "sheeple" have about as much sophistication as an AOL user, and in fact are probably actually AOL users.
The trouble with university education, is that most people who teach there are computer scientists, not software engineers with years of experience in the trenches.
If this were actually the case, there would be a recognition that reading code is far harder than writing it. And far more emphasis would be on coming to grips, understanding, and working on large code bases. There'd be more stuff on things like unit testing, breaking dependencies, troubleshooting, and refactoring at least.
Find out what drugs the original coder was using when writing, and take the same.
You mentioned you have embedded C experience and the code of interest is written in C++. You didn't mention if you had any C++ or other object-oriented programming experience. I assume the C++ code uses the OO features of C++ that distinguish it from C -- but this assumption is not necessarily true.
So, if you lack OO experience and the code is truly OO C++ code, you might want to do a little reading up on the basics of OOP in order to spend less time spinning your wheels.
I am not a crackpot.
2) Just because the code is awful doesn't mean it has no value -- No matter how bad it is and how difficult it is to read, if it works at all it has probably got years (maybe even decades) of bug fixes and feature requests. Until you have a handle on it, any little change could cause a catastrophic cascade of side-effects.
3) No, we don't need to rewrite it. See 2. A working program now is worth more than all the pie in the sky you can promise a year from now.
4) It takes 6 months to have a reasonably good grasp of any moderately complex in-house application. It could be a year before you get to the point where someone can describe a problem and you immediately have a good idea of where in the code the problem is occurring and what functions to check.
Maintenance programming is as much about detective work as anything else. The only clues you have about the previous programmer are his source files. Once you've read them for a while you can start to tell what he was thinking, when he was confused, when he was in a hurry. Most of the atrocious in-house applications have changed hands several times and each programmer adds their own layer of crap. You can redesign these applications a chunk at a time until nothing remains of the original code if it's really bad, but it's best to save really ambitious projects until you understand the code better. I heartily encourage the wholesale replacement of "system()" calls with better code immediately, though. In several languages I've run across these calls to remove files, when they could have simply called a language library call (Typically "unlink".) If the original programmer used system("rm...") you can pretty much assume that they were a bad programmer and you're in for a lot of "fun" maintaining their code.
I'm trying to teach myself to set people on fire with my mind... Is it hot in here?
It's just how your brain works. It's a lot easier to examine a piece of mechanical machinery when it's in motion. You notice more. Do the same with the code. Run it. Run components independently. Put plenty of log statements or if it's feasible, watch under a debugger. But don't try to look at stale code just sitting there. You'll notice more as it moves.
Any guest worker system is indistinguishable from indentured servitude.
This. Looking at existing tests is also very educational. They often show where the codebase was confusing enough to cause recurring regressions.
The other place to make very, very sure to read is the repository commit logs, if you have them. They'll tell you a lot about why the code is in its current state, and will often show you where refactors have been left half-complete.
Someone had to do it.
No, unit tests are a good idea. They wouldn't be my first choice, but they're a good option when deciphering a particularly difficult project.
(1) It gets you to interact with the code. This is always a good idea when leaning how something behaves. Fiddle with it for a while and see if you can figure it out.
(2) The unit tests don't need to be particularly true to their original requirements to be useful. When you do eventually start making changes, the law-of-unintended-consequences comes into play. If you make a change and one of your unit tests starts failing, then it will give you a clue that things may be interacting in a way that you did not anticipate.
I won't join Slashcott. OTOH, If Beta goes live, I just won't be back until it's fixed. Sorry Dice.