Every now and then, I have to fix up a project, generally huge and spaghettified. Don’t get me wrong, my own projects must look that way to other developers as well… The question is not about relative qualities of code styles and habits, it’s about getting in a boat steered by ghosts and guide it to calmer waters.
So how do you get to understand someone else’s code? We all have our own techniques, obviously, but I’ll list here a few that will help desperate people.
First off, run a Doxygen auto-documentation, with call and caller graphs. Doxygen is a freely available tool that you can download at this address, that can deal with many many languages. Make sure you have dot (available here) installed as well.
Go to the root of your project folder, type
It will produce a Doxyfile text file in which there’s a bunch of options for generation. Edit it in your text editor of choice (I like BBEdit the most), and make sure the following options are set
HAVE_DOT = YES CALL_GRAPH = YES CALLER_GRAPH = YES
Go make yourself a cup of coffee or something, it can be a long process. In the end, you have an html tree of files that gives you the class hierarchy, class documentations, and for each function, the caller and call graphs (what this function calls in the code, and what it’s called by). Ideal to identify the “major” functions called by a lot of others, and to evaluate the damage the changes you make will do to the rest of the code.
If for some reason, no code file is examined, you may have forgotten to tinker with the input section (folder in which the code resides and recursive search).
Alright, so, now you have a static and broad view of the code. It’ll help setting up the breakpoints in the bottlenecks and get a better idea of the overall architecture.
Now, the problem is dynamic. How does the program behave in time? To learn about that, depending on the language and the platform, there’s a variety of tools that can provide you with this information, but since I’m mainly a Mac/iOS coder, I’ll mention Instruments. Instruments is bundled with the developer tools, and you have nothing to set up to use them. Just open your project, and in the “Product” menu, run “Profile”.
Now, there’s a bunch of types of profiles you can get. What matters most to the project is dependent on what you’re supposed to do… If it’s “making it speedy”, then you want to go for the time profile, which will give you the percentage of time spent in various functions. If it’s a memory optimization, you have the object allocations and leaks tools. Etc etc… I won’t write a manual up here, you can find a relatively thorough documentation on Apple’s website.
The important thing is that for these tools, you will get the functions the program spends the most time in, that use the most memory, that leak the most, that handle the most complex CoreData queries, or whatever else strikes your fancy. In other word, you’ll get a better picture of how the program behaves in time.
It takes a little practice to identify what’s mostly relevant from what’s highly relevant, but it’s less of a daunting task than figuring it out through printf, NSLog, or NSLogger…
Tying it up together
To take an overused metaphor, you now know where the engine(s) is (are), and how the beast handles on the road. Make sure you take time to study the bottlenecks, both in the structure and in the profiles you built. That way, tinkering with stuff will be comparatively easier.
If the structural and temporal (or memory-usage) bottlenecks overlap, you have your work cut out for you. They should be the focus of your attention. If not, then it’s a little trickier, and vastly depends on the perimeter of your mission.
Just try to remember something: most of the time, the developer who wrote the code had a different set of constraints than your own. While it feels good to rant at these dimwitted douchebags, it’s not fair. Most people who would have to take over your code would say the same.
Coding is a matter of education, style, and constraints/objectives. If you switch any or all of these parameters, you end up with very different code blocks. Understanding how it works and how to fix it should take precedence, and ultimately provides the best feeling ;)