Methods for understanding complex, real world, C++ code?

M

mathog

Mostly when I program it is maintenance work - making little tweaks and
corrections to other people's code. The C++ books and tutorials are all
clear and wonderful about objects and methods but they only ever give
toy examples. In real world programs it seems that the code is always a
morass of object types and methods, often with similar names.
(Resulting in: "yes, 'print', but which 'print'?"). I find it extremely
difficult to find in such code where actions actually occur, or in many
cases what earlier events led to an issue later in the program.

Presumably there are tools to help with this that I should be using but
am not. What are these tools? If somebody knows of a tutorial or
reference on how to deal with complex code like this, please share it.

For instance, lately I have had to make some changes to Inkscape. The
development environment is Mingw. This program uses Cairo, GDK, GTK,
Pango, and heaven knows what else, in addition to all of its own code.
The closest thing I have to a class browser is the doxygen web
interface, example:

http://fossies.org/dox/inkscape-0.48.3.1/clipboard_8cpp_source.html

One of the tasks on my "to do" list is to add import/export of images to
the EMF extension. I found the relevant sections in the EMF extension
(switch() cases provided, but no code in them) by a grep through all of
the source code for the EMF keyword function associated with images.
Looking around for an example of how to handle images in Inkscape
located the link above by more grep's, since I knew one could paste an
image into the program from the clipboard. From this link, on line 937
we see that rather than converting directly from GDK::pixbuf to an
Inkscape object type they punted. First they save from the Pixbuf to a
PNG file, and then they use a preexisting file_import function to read
that object back in. The program pastes at the cursor (or something like
"at the cursor") but how it knows where that is lies in a code segment
far far away. Anyway, this illustrates the point I'm trying to make.
One would imagine that somewhere in this heap of code there is a
"create/import image of size W,H at position X,Y", but good luck finding it.

Figuring out the logic in real C++ programs is also challenging. In
Inkscape, for instance, much of the program is event driven, so a
backtrace will often not tell you what happened before a given execution
point. Example:

A ->
B ->
C (configure: event X will cause E) ->
D (configure: something else relevant when E runs) ->
C ->
B (event X) ->
E (stops at preset breakpoint)

So the back trace shows

A->B->E

and there is no clue that C and D are important, or even that they ever
ran. This A->E example is grossly simplified, since in the real program
there were thousands of function calls before event X. Short of tracing
every function call how would one ever know that C,D need to be looked at?

Thank you,

David Mathog
 
K

K. Frank

Hi David!

Mostly when I program it is maintenance work - making little tweaks and
corrections to other people's code.  The C++ books and tutorials are all
clear and wonderful about objects and methods but they only ever give
toy examples.  In real world programs it seems that the code is always a
morass of object types and methods, often with similar names.
(Resulting in: "yes, 'print', but which 'print'?"). I find it extremely
difficult to find in such code where actions actually occur, or in many
cases what earlier events led to an issue later in the program.

First off, "We Share Your Pain!"

By the way, you should be aware of the Microsoft WSYP program
for improving user experience:


Presumably there are tools to help with this that I should be using but
am not. What are these tools?  If somebody knows of a tutorial or
reference on how to deal with complex code like this, please share it.

A couple of comments:

Much real-world code isn't that good. It may be that the
programmers who wrote it weren't that good. It may be that
the programmers were great, but the code grew and evolved
over time, obscuring what was originally a good design, and
that the (possibly rational) decision was made not to refactor
the code base and clean up the current design.

Also, good real-world code is often (very) complicated. Many
real-world problems are inherently complicated. So the art
of good programming is not to eliminate complexity (you can't),
but to master that complexity in as organized a way as you can.

Further, as you point out, many programming books aren't realistic.
It's legitimate to use toy examples -- otherwise the books would
become unreadably long -- but authors often leave out (purposely?)
real-world complexity that their favorite design methodology
doesn't handle well.

So ... Welcome to the real world.

How to deal with this? I don't have a good or simple answer.

What I do is try to get an overview of the code -- or, better,
the part of the code that is relevant to what I am doing. I
try to get a feel for its "shape," for lack of a better word.
Then I rely on intuition to zero in on where the action (relevant
to my problem) is.

(I know, I know ... This is hardly useful advice.)

Only at this point is it practical to look at the details.
(One can "look at details" by reading the code, running a
debugger, putting in print statements, or otherwise adding
instrumentation, according to one's taste. My preference
is to use a combination of reading the code and adding print
statements, but the exact technique doesn't really matter.)

It's hard, it's challenging, and I can't give you a detailed
recipe for how to do it, because for me, there's a lot of
intuition involved.

In my experience it's a rare talent for a developer to be able
to work effectively with a large, unfamiliar code base.

I liken it to the Radar O'Reilly character in the M.A.S.H.
story (movie, TV, etc.). The joke with him is that he'd
look up and say "Choppers." and then only after a few minutes
had passed would the other characters hear the choppers
flying in to deliver the wounded.

In my experience there is a minority of developers who, when
looking for a bug in "Other People's Code," have -- like
Radar O'Reilly -- some sort of sixth sense for where the
bodies are buried. And they are worth their weight in gold.

The only concrete advice I can give you is to gain (a lot
of) experience in working with large, unfamiliar code bases.
The more you see various chunks of code written by programmers
with differing styles and levels of talent, the more easily
you'll be able to recognize at a higher level what they're
trying to do, before drilling down into the details.

To give an overly simplistic "toy" example, when I look at
code I can say "Oh, this guy's using a bunch of nested if
statements." or "This guy's using a switch statement." or
"This guy's using virtual functions in a bunch of derived
classes." or "This guy's setting up a look-up table." all
to accomplish the same programming task. In this context
it doesn't matter whether a specific technique is "right"
or "wrong" or 'better" or 'worse," so it's not worth
arguing about. In practice you will see all manner of
code, and you need to be able to recognize what the guy
is trying to do whether or not he is doing it "right."
For instance, lately I have had to make some changes to Inkscape...
...
Figuring out the logic in real C++ programs is also challenging.  In
Inkscape, for instance, much of the program is event driven, so a
backtrace will often not tell you what happened before a given execution
point.  Example:

A ->
B ->
C (configure: event X will cause E) ->
D (configure: something else relevant when E runs) ->
C ->
B (event X) ->
E (stops at preset breakpoint)

So the back trace shows

A->B->E

and there is no clue that C and D are important, or even that they ever
ran.

Yes, you're absolutely right about this. Working with
event-driven (sometimes called "reactive") programming
is especially hard. Trying to understand "Other People's
Code" becomes even more difficult because, as you point
out, traditional procedural techniques such as reading
one line of code after another or stepping through
execution with a debugger don't map well to the actual
event-driven logic. At some point you have to hope for
the good fortune that the original programmer approached
his event-driven design in a thoughtful and well-organized
manner.

When I _write_ event-driven code, I tend to instrument it
with print statements that include a tag that indicates
which _logical_ process a particular step belongs to. So
in your example, although the backtrace would show:

A->B->E

my print-statement log file would show:

Process-Q: A
Process-Q: B
Process-Q: C: handle event X; schedule E
Process-Q: D: configure some property of E
Process-Q: E: (stops at some breakpoint)

Sometimes you can retroactively instrument existing code along
these lines, but often it's not practical.
This A->E example is grossly simplified, since in the real program
there were thousands of function calls before event X.  Short of tracing
every function call how would one ever know that C,D need to be looked at?

Very hard. You need to develop that Radar O'Reilly sixth sense,
or you need to (partially) instrument the code along the lines
described above. And if the code isn't naturally organized
into logical sequences of event processing, it can get pretty
nasty.
Thank you,

I apologize that I haven't offered any particularly good
recipe for tackling these issues. I would love to hear
what other folks think, and what procedures and tools they
use for these kinds of challenges.

The problem is that when dealing with "Other People's Code,"
you have to work with the code as it is, rather than as you
would wish it to be.
David Mathog


Good Luck ... And Happy (OPC) Hacking!


K. Frank
 
I

Ian Collins

Mostly when I program it is maintenance work - making little tweaks and
corrections to other people's code. The C++ books and tutorials are all
clear and wonderful about objects and methods but they only ever give
toy examples. In real world programs it seems that the code is always a
morass of object types and methods, often with similar names.
(Resulting in: "yes, 'print', but which 'print'?"). I find it extremely
difficult to find in such code where actions actually occur, or in many
cases what earlier events led to an issue later in the program.

Presumably there are tools to help with this that I should be using but
am not. What are these tools? If somebody knows of a tutorial or
reference on how to deal with complex code like this, please share it.

I use Oracle's version of NetBeans (Solaris studio) which has pretty
good code browsing capabilities. Standard NetBeans or Eclipse should do
much the same.
 
J

Jorgen Grahn

Mostly when I program it is maintenance work - making little tweaks and
corrections to other people's code. The C++ books and tutorials are all
clear and wonderful about objects and methods but they only ever give
toy examples. In real world programs it seems that the code is always a
morass of object types and methods, often with similar names.
(Resulting in: "yes, 'print', but which 'print'?"). I find it extremely
difficult to find in such code where actions actually occur, or in many
cases what earlier events led to an issue later in the program.

Presumably there are tools to help with this that I should be using but
am not. What are these tools? If somebody knows of a tutorial or
reference on how to deal with complex code like this, please share it.

I don't have specialized tools, but here are some I actually use. They
may be Unix-specific.

- Emacs with 'exuberant ctags' in C++ mode. Still won't work well
for looking up overloaded names though :-(

- Doxygen with full graph generation enabled.

- A gprof profiling run of the code, compiled with inlining disabled.
Not for the profiling but for showing the main code flows.

- The nm(1) symbol lister to get a rough idea what one source file
contains and what it depends on.

- Pen and paper for reconstructing class diagrams, state machines etc.

- Valgrind for detecting obvious memory handling bugs.

- Changing the code (making things private or const; changing their
type and so on) just to see what stops compiling. Works best if your
Makefile isn't broken, so the right things are rebuilt automatically.

BTW, I think most of these problems are not related to C++. Most are
there in C too. (Exception: inheritance. I really hate debugging messy
code where everything is badly designed run-time polymorphism and
nothing is documented.)

And, like K. Frank I share your pain. Remember that in maintenance
programming, at least you're creating stuff which people *really need*
and are asking for. New code on the other hand is often not used in
the end.

/Jorgen
 
M

michael.boehnisch

In real world programs it seems that the code is always a
morass of object types and methods, often with similar names.

I consider real world code that does not come with sufficient documentationto have a value close to zero. Often its less work to rewrite the stuff from scratch.

In cases where this is not an option and pressure to bother is gross, I'd recommend to reverse engineer an UML model for the code, i.e. start with a static class model depicting interfaces, inheritance and aggregation, and continue by filling in usage information who calls what else. It may also possible to group classes to components.

Once this is done, you can analyze method by method and add diagrams for the code's dynamics (sequence-, activity-, state diagrams). Whatever you findout you should also add as extra comments to the code.

If you're lucky, you end up with a usable code documentation. Many times you won't be lucky, in spite of the systematic approach.

Doxygen in combination with GraphViz is a good start if you are looking fortools. It will spare you of lots of manual work for the analysis. For modelling UML I prefer Sparxsystem's Enterprise Architect. It is a commercial product but relatively cheap compared to other tools. For reengineering purposes you'd need the "Professional" edition or better; its code-to-model import features should come handy.

best,

MiB.
 
K

K. Frank

Hello Jorgen!

I don't have specialized tools, but here are some I actually use. They
may be Unix-specific.

- Emacs with 'exuberant ctags' in C++ mode. Still won't work well
  for looking up overloaded names though :-(

I'm a big fan of using ctags with emacs, although some people find
emacs to be an acquired taste.
...
- Changing the code (making things private or const; changing their
  type and so on) just to see what stops compiling. Works best if your
  Makefile isn't broken, so the right things are rebuilt automatically.

I've only ever done this by accident, but I like this idea as a
systematic
technique. Maybe I'll add it to my bag of tricks.
...
Remember that in maintenance
programming, at least you're creating stuff which people *really need*
and are asking for.  New code on the other hand is often not used in
the end.

Hear, hear! Sometimes confusing code started out bad, but lots
of times it starts out good, and the bloat and convolution and
bit-rot you're struggling with came about because the code was
useful and being used and growing and gaining new features
because people wanted it. When you find yourself working on a
multi-man-decade code base like this, it's actually kind of
cool (if frustrating).


Thanks for your thoughts and suggestions.


K. Frank
 
G

Guest


Re: "Methods for understanding complex, real world, C++"

Rewrite it. That's what I do.
</pre>

my boss tends not to give me the time to re-write 750 KLOC when a one line change is required. Get real.
 
R

Rui Maciel

I consider real world code that does not come with sufficient
documentation to have a value close to zero. Often its less work to
rewrite the stuff from scratch.

This approach doesn't appear to be very reasonable. If a piece of code
which may not be documented is already mature then your suggestion to
reinvent the wheel may end up needlessly reintroducing bugs and other
issues. So, just because you can't access the documentation of a piece of
code you risk ending up needlessly wasting resources to make something worse
than it already is. And where's the added value in this?


Rui Maciel
 
R

Rui Maciel

my boss tends not to give me the time to re-write 750 KLOC when a one line
change is required. Get real.

Indeed.

I wonder if these proponents of this type of scorched earth approach to
documentation also believe it is a good idea to demolish their house and
rebuild it if they can't find its blueprints.


Rui Maciel
 
G

Guest

(e-mail address removed) wrote:

Indeed.

I wonder if these proponents of this type of scorched earth approach to
documentation also believe it is a good idea to demolish their house and
rebuild it if they can't find its blueprints.

I'm guessing they're thinking of someting "really large" they've encountered which they could re-write from scratch in 48 hours if they drank enough Jolt.
 
N

Noah Roberts

Yes, you're absolutely right about this.  Working with
event-driven (sometimes called "reactive") programming
is especially hard.  Trying to understand "Other People's
Code" becomes even more difficult because, as you point
out, traditional procedural techniques such as reading
one line of code after another or stepping through
execution with a debugger don't map well to the actual
event-driven logic.  At some point you have to hope for
the good fortune that the original programmer approached
his event-driven design in a thoughtful and well-organized
manner.

I'm currently having some trouble with people complaining about my
code. Having worked with event programming for years among
programmers who find it as straight forward as I do, I'm having a very
hard time it seems to express things in a way that others understand.
I've made UML diagrams to try and alleviate the problem, but they
don't look at them. I used doxygen to generate comments for
everything. I used standard constructs like function<>, bind(),
etc...but they find them confusing.

To me, in OO the event driven or observer architecture is completely
natural. You have objects that say, "I got something happening over
here!!" and you have other objects saying, "I hear you!" You map out
what's going to happen by looking at the connections. If ordering is
important you may have to learn the specific nature of a given event
system to figure out what, exactly will happen and when...but
generally you just look to see that things will happen and in what
order isn't as important (in fact usually you only have one listener
attached to any single source).

Further, to me anyway, it allows you to fully understand one part of
the program knowing that it does some things, tracks a resource or
pipe or something, and then generates events for others to observe.
You don't need to know what's going to happen then to fully understand
everything there is to understand about that. I find that much easier
to understand than trying to follow a spaghetti of traces to this and
that.

I've written trace logs for EVERYTHING. If you turn on trace in the
log it will very rapidly take up huge amounts of space spewing out
every function call that's happening. It's multithreaded though so
it's hard to say what order is happening. I used log4cplus so that we
can turn on and off various logs that are named by class.

Now I'm being asked by my manager to comment every line of code
basically. He's been around longer than I have but this still seems
very strange to me.

What can be done to bridge the gap so that "procedural" programmers
can keep up?
 
L

Lynn McGuire

I'm currently having some trouble with people complaining about my
code. Having worked with event programming for years among
programmers who find it as straight forward as I do, I'm having a very
hard time it seems to express things in a way that others understand.
I've made UML diagrams to try and alleviate the problem, but they
don't look at them. I used doxygen to generate comments for
everything. I used standard constructs like function<>, bind(),
etc...but they find them confusing.

To me, in OO the event driven or observer architecture is completely
natural. You have objects that say, "I got something happening over
here!!" and you have other objects saying, "I hear you!" You map out
what's going to happen by looking at the connections. If ordering is
important you may have to learn the specific nature of a given event
system to figure out what, exactly will happen and when...but
generally you just look to see that things will happen and in what
order isn't as important (in fact usually you only have one listener
attached to any single source).

Further, to me anyway, it allows you to fully understand one part of
the program knowing that it does some things, tracks a resource or
pipe or something, and then generates events for others to observe.
You don't need to know what's going to happen then to fully understand
everything there is to understand about that. I find that much easier
to understand than trying to follow a spaghetti of traces to this and
that.

I've written trace logs for EVERYTHING. If you turn on trace in the
log it will very rapidly take up huge amounts of space spewing out
every function call that's happening. It's multithreaded though so
it's hard to say what order is happening. I used log4cplus so that we
can turn on and off various logs that are named by class.

Now I'm being asked by my manager to comment every line of code
basically. He's been around longer than I have but this still seems
very strange to me.

What can be done to bridge the gap so that "procedural" programmers
can keep up?

You can't. If a programmer does not understand
event driven code then they will never transition
to the new device driven interface model.

Lynn
 
J

Jorgen Grahn

I'm currently having some trouble with people complaining about my
code. Having worked with event programming for years among
programmers who find it as straight forward as I do, I'm having a very
hard time it seems to express things in a way that others understand.
I've made UML diagrams to try and alleviate the problem, but they
don't look at them. I used doxygen to generate comments for
everything. I used standard constructs like function<>, bind(),
etc...but they find them confusing.

To me, in OO the event driven or observer architecture is completely
natural. You have objects that say, "I got something happening over
here!!" and you have other objects saying, "I hear you!" You map out
what's going to happen by looking at the connections. If ordering is
important you may have to learn the specific nature of a given event
system to figure out what, exactly will happen and when...but
generally you just look to see that things will happen and in what
order isn't as important (in fact usually you only have one listener
attached to any single source).

Further, to me anyway, it allows you to fully understand one part of
the program knowing that it does some things, tracks a resource or
pipe or something, and then generates events for others to observe.
You don't need to know what's going to happen then to fully understand
everything there is to understand about that. I find that much easier
to understand than trying to follow a spaghetti of traces to this and
that.

I've written trace logs for EVERYTHING. If you turn on trace in the
log it will very rapidly take up huge amounts of space spewing out
every function call that's happening. It's multithreaded though so
it's hard to say what order is happening. I used log4cplus so that we
can turn on and off various logs that are named by class.

Now I'm being asked by my manager to comment every line of code
basically. He's been around longer than I have but this still seems
very strange to me.

What can be done to bridge the gap so that "procedural" programmers
can keep up?

Talk to them and work together with them. If it's straightforward to
you and they aren't stupid, they can ask the right questions and
eventually understand the way you think.

But it seems to me that if you use this kind of design /everywhere/,
you're the one who should adjust. I've been doing this for many years,
and I can't say I recognize the style you describe. Unless it's
another way to say "state machine". Perhaps your application domain is
different from mine.

(Not that people generally understand *my* architectures ...)

/Jorgen
 
J

Joe keane

The C++ books and tutorials are all clear and wonderful about objects
and methods but they only ever give toy examples.

This was one of my disappointments with college 'education'.

They teach you how to write programs, from scratch, all by yourself,
which are probably no more than ten pages long.

Employers don't give a s--- about that, they want to know if you can
grok an existing codebase, get up to speed, interact with the people who
know about it, deal with people who are no longer there, and mentor the
'new guys' so they can do something useful.
 
N

Noah Roberts

This was one of my disappointments with college 'education'.

They teach you how to write programs, from scratch, all by yourself,
which are probably no more than ten pages long.

Employers don't give a s--- about that, they want to know if you can
grok an existing codebase, get up to speed, interact with the people who
know about it, deal with people who are no longer there, and mentor the
'new guys' so they can do something useful.

Perhaps one way of instructing classes then would be to shuffle up
peoples' answers from one assignment, hand them out to the students,
ask them to extend the code to do more stuff...and assign them the
task of grading the code they were given to work with.

I can see issues with it, but maybe some variation on that theme could
be instructive?
 
K

K. Frank

Hi Noah!

I'm currently having some trouble with people complaining about my
code.  Having worked with event programming for years among
programmers who find it as straight forward as I do, I'm having a very
hard time it seems to express things in a way that others understand.
I've made UML diagrams to try and alleviate the problem, but they
don't look at them.  I used doxygen to generate comments for
everything.  I used standard constructs like function<>, bind(),
etc...but they find them confusing.
...

I've written trace logs for EVERYTHING.  If you turn on trace in the
log it will very rapidly take up huge amounts of space spewing out
every function call that's happening.  It's multithreaded though so
it's hard to say what order is happening.  I used log4cplus so that we
can turn on and off various logs that are named by class.

One comment about the multi-threading: Some of my event-driven
code is multi-threaded, and the events that drive a given
logical-processing sequence often come in on several different
threads. This can play havoc with the trace logs when several
logical-processing sequences are going on simultaneously.

This is the main reason I add a logical-process tag to my log
messages. (I also like to add a time-stamp.) Now all I have
to do is grep my log for, say, "Process-Q" and I get a pretty
readable trace for Process-Q. (If, say, Process-P sends an
important event to Process-Q, I can separately grep for
"Process-P" to get the trace for Process-P, and use the
time-stamps to cross-correlate the two traces. Or I can
jointly grep for "Process-P" and "Process-Q" and get the
combined Process-P--Process-Q trace properly sequenced.)

Yeah, I know ... Pretty simple-minded. But, hey, it works.
...

What can be done to bridge the gap so that "procedural" programmers
can keep up?

My advice would be to not use event-driven programming unless
you need to. You mentioned some benefits of event-driven
programming (that I would generally lump under the heading
of "looser coupling") that are applicable in situations where
event-driven programming isn't absolutely necessary. But I
find event-driven programming enough harder that I think the
cost outweighs the benefit when applied to problems that are
basically procedural in nature.

But when a problem is inherently event-driven in nature,
event-driven programming is the only way to go. Even if
you write procedural-style code, you're still doing
event-driven programming, whether or not you admit it.

And if you don't admit it, you're going to end up with
nested if-then spaghetti code that will collapse under
its own weight. You need to use explicit event-driven
programming to master the fact that event-driven problems
are inherently harder than procedural problems.

So the way I look at it is using an event-driven style
for a procedural problem is harder than using a procedural
style. (So cut your colleagues a break, and write
procedural code.) But using a procedural style for
an event-driven problem is vastly harder -- almost
impossible -- than using an event-driven style.
(Trust me on this -- I've bit myself with this more
times than I care to remember.)

So use event-driven programming for event-driven problems.

How to bridge the gap with your procedural colleagues?
I guess it's an issue of education and gentle persuasion.

Tell your colleagues (and your boss) "Look, this problem
is really hard -- it's inherently event-driven and that
makes it hard. Now this event-driven code that addresses
the problem is harder to understand than some other code
that isn't trying to address as hard a problem. But it's
the problem that's hard, not the code."

Maybe they buy it, and maybe they don't. But if they're
set in their procedural ways and try to solve some
event-driven problem with procedural code, they will
probably fail, and maybe that will make them more open
to your way of thinking.


Good luck.


K. Frank
 
M

Miles Bader

@Jeff-Relf.Me said:
Uncommented, <A hRef="http://Jeff-Relf.Me/X.CPP">my code</A> looks
like...

Hey wait, isn't that a bit over the IOCCC size limit?! :O

-miles

p.s. To anybody who didn't bother following the link, do!
[Tho I'm suspicious that the code was run through some sort of
obfuscator...]
 
C

Christopher Pisz

To me, in OO the event driven or observer architecture is completely
natural. You have objects that say, "I got something happening over
here!!" and you have other objects saying, "I hear you!" You map out
what's going to happen by looking at the connections. If ordering is
important you may have to learn the specific nature of a given event
system to figure out what, exactly will happen and when...but
generally you just look to see that things will happen and in what
order isn't as important (in fact usually you only have one listener
attached to any single source).
What can be done to bridge the gap so that "procedural" programmers
can keep up?

I am very much for OO design and have been brought up under the strict
discipline of this newgroup :) However, I have seen good things used in
bad ways. Your description of the use of event being "natural" reminds
me of a library I just got done debugging.

Every single class in the library contained a custom wrapper for
boost::bind, boost::asio, boost::thread, to make a "callback queue"

No class called methods on another, they were all posting callbacks to
this queue and then handling them. It made it a son of a bitch to debug.

when I cleaned it up, it ran much faster and was much more
maintanable...IMO anyway.


Events make sense sometimes, but not all the time. Do not be one of
those guys that uses some pattern in every situation, even when it's not
warranted.
 
M

mathog

Jorgen said:
Talk to them and work together with them. If it's straightforward to
you and they aren't stupid, they can ask the right questions and
eventually understand the way you think.

Most likely the information that makes the code easy for the original
programmer to understand exists nowhere else but inside that
programmer's skull. If the code is event driven, and especially if the
handling of those events does not pass through some sort of queue or
other mechanism that funnels it through a single place in the code, then
from the maintenance programmer's viewpoint they are dealing with
spaghetti code, using events and handlers in place of goto's. This sort
of code can be understood, of course, but one needs a complete list of
the events that are handled, an overview of where each type of event may
be encountered, and the handlers that may be called in each case. This
is exactly the information often only found encoded in somebody else's
synapses.

If a project includes more than handful of source files it should have
an architecture document, describing in natural language the way the
whole thing works. The existence of this document should be noted in
the README. Burying it without mention among thousands of other files
pretty much negates the purpose of having it in the first place.

Regards.

David Mathog
 
P

Pavel

K. Frank said:
Hello Jorgen!



I'm a big fan of using ctags with emacs, although some people find
emacs to be an acquired taste.
Those use ctags with vim :). It does not have that taste and works reasonably
well for overloaded names while there is less than 30-40 overloads..

But ultimately, grep (or fgrep) is your only friend..

-Pavel
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,733
Messages
2,569,440
Members
44,832
Latest member
GlennSmall

Latest Threads

Top