views:

288

answers:

5

Hi all,
I am working on a project written in C++ which involves modification of existing code. The code uses object oriented principles(design patterns) heavily and also complicated stuff like smart pointers.
While trying to understand the code using gdb,I had to be very careful about the various polymorphic functions being called by the various subclasses.

Everyone knows that the intent of using design patterns and other complicated stuff in your code is to make it more reusable i.e maintainable but I personally feel that, it is much easier to understand and debug a procedure oriented code as you definitely know which function will actually be called.

Any insights or tips to handle such situations is greatly appreciated.

P.S: I am relatively less experienced with OOP and large projects.

+2  A: 

Diagrams. Does your IDE have a tool that can reverse-engineer class diagrams from the code? That may help you understand the relationships between classes. Also, have the other developers actually written documentation on what they are doing and why? Is there a decisions document explaining why they designed and built in the way they did (Ok, sometimes this is not necessary - but if it exists, it would also help).

Also, do you know WHAT design patterns were used? Do they have names? Can you look them up and find other simpler examples of them? Maybe try writing a small app that also implements the design pattern, just to try it for yourself. That can also improve understanding.

FrustratedWithFormsDesigner
"sometimes this is not necessary" <- can you give a real-world example where documentation is not necessary?
Martinho Fernandes
@Martinho - specifically, I was referring to architecture desicion documents. Where I see them they usually cover high-level architecture such as "we will use a web service because..." and don't usually nitpick over which design patterns will be used to IMPLEMENT said web service.They have sometimes referred to design patterns when the author felt it a relevant-enough decision, usually if that decision would drive many other decisions.
FrustratedWithFormsDesigner
thanks for your answer, i use vim, and i dont think it has a capability to reverse-engineer class diagrams.. if you know one plz share :D
Neeraj
@Frustated, nevermind then, I misunderstood.
Martinho Fernandes
@Martinho - I realize I didn't quite answer your question: In my experience, the times that people don't always think it's necessary are when it's "obvious". Unfortunately, what's obvious to the senior dev/team lead is not always obvious to someone fresh out of school. The cases where I think not document a design pattern is OK are cases where using complex design patterns are overkill. Usually very small apps/utils that can be more easily explained by the comments in code. Recent example: small shell script to FTP files between servers.
FrustratedWithFormsDesigner
@Neeraj: No I don't think vim can reverse engineer code into diagrams :( In that case, I'd look and see if there are other stand-alone tools that CAN do this, but I'm not sure if there are. Time to fire up the ol' search engine and start searchin'!
FrustratedWithFormsDesigner
@Neeraj: You might look into Doxygen, which can produce simple inheritance and call-graph charts from an existing code base.
Caleb Huitt - cjhuitt
@above thanx a ton
Neeraj
A: 

I generally do the following:

  • Draw a simplified class diagram

  • Write some pseudocode

  • Ask a developer who is likely to be familiar with the code layout

Steven
+12  A: 

gdb is not a tool for understanding code, it is a low-level debugging tool. Especially when using C++ as a higher level language on a larger project, it's not going to be easy to get the big picture from stepping through code in a debugger.

If you consider smart pointers and design patterns to be 'complicated stuff' then I respectfully suggest that you study their use until they don't seem complicated. They should be used to make things simpler, not more complex.

While procedural code may be simple to understand in the small, using object oriented design principals can provide the abstractions required to build a very large project without it turning into unmaintainable spaghetti.

For large projects, reading code is a much more important skill than operating a debugger. If a function is operating on a polymorphic base class then you need to read the code and understand what abstract operations it is performing. If there is an issue with a derived class' behaviour, then you need to look at the overrides to see if these are consistent with the base class contract.

If and only if you have a specific question about a specific circumstance that the debugger can answer should you step through code in a debugger. Questions might be something like 'Is this overriden function being called?'. This can be answered by putting a breakpoint in the overriden function and stepping over the call which you believe should be calling the overriden function to see if the breakpoint is hit.

Charles Bailey
thanks.. that was helpful. I also think i need to learn more.. :D
Neeraj
gdb is a tool for understanding code. Arguably that's all it does. Other than that, this is an excellent answer. +1.
Jason Orendorff
gdb is a debugger. If you're successful in using it you are going to end up understanding some of the code you're debugging better, but if you want to understand some code and you're reaching for gdb first then you're setting yourself up for a hard slog. IMHO.
Charles Bailey
+4  A: 

Port it into Doxygen as a first step. Modifying comments should have no effect on the code. Doxygen will allow you to get an overview of the structure of the program.

Over time, as you figure out more about the program, you add comments that get picked up by Doxygen. The quality of the document grows over time, and will be helpful to the next poor SOB that gets stuck with the program

EvilTeach
+1 - you don't need to do anything except run Doxygen on the existing unchanged code to get real value from the diagrams that it can provide.
Len Holgate
+4  A: 

There is an excellent book called Object-Oriented Reengineering Patterns that, in a first part, provides patterns on how to understand legacy code (e.g. "refactor to understand").

A pdf version of the book is available for free at http://scg.unibe.ch/download/oorp/

bertolami