18 Answers
18

I start with code. Separate design documents, if there are any, are as likely to be wrong or misconceived as not. So, i start by trying to trace some simple flow through the code; if it's a webapp, it could be a request or a sequence of requests, for instance. Once i've done that, i have a sort of skeleton to hang more understanding on. Then, i might go back and read designs or other documentation, but at that point, i have something concrete to relate them to, and to validate them with, so i can detect duff information. Or i might just carry on reading code, or test cases, etc.

I would start at a higher level. If there is any user facing documentation - user manual or guide. Failing that then have a look at the requirements spec so that you have some idea as to what the software is supposed to do. I would than look at the design and try to map it onto the code files. Hopefully these are structured into folders in some sensible way. I would then pick part of the design and go into the files to follow the flow of the code without getting too bogged down into the fine detail.

I start by setting up a developers system. I use the documented procedure. This lets the cat out of the bag about how much the documentation is in sync with reality.

It also tells me what the dependencies are. This matters.

Now that I've got a developers setup, ( and I mark up the setup document with corrections as I go) I build a version. I end up asking questions all through this phase.

Now it's been built, I do the introductory exercise from the user manual. This tells me roughly what the system really does.

Now I have a partial clue about the system, I read the design documents, which I now believe in proportion to how wrong the documents have been so far.

Once I get to the actual behavioral documentation I can start looking into the code and seeing what's really there. They never line up, but I now know how much to believe.

Then I look at the IDE output for "todo" and "fixme" comments.
Things like "fix in version 2.0" are tip-off's too.

So it's all about learning the veracity, and as people point out, separate design documents are rarely up to date or correct, but it does tell you what people were thinking at a point in time. And of course, those people are probably not around to interrogate.

Always the design. With the code it's worth going through the developer setup steps (checking out the source, getting the project built, making any configuration changes required) but there's no point trying to learn an application's structure from its code. That only tells you what the structure is, not why the structure is or what the other developers think the highlights and bad points are of the architecture. Those you learn from whiteboard diagrams and chats with the developers.

For a complex piece of software I would approach it roughly as if it were a new development project. Start with the big ideas- vision, context, scope, stakeholders. Read through some user documentation and get an idea of how it is used. Get some user training with the software if possible (or applicable). Then start looking into the requirements and design documentation to get an idea of how it works at a high level. Talk to the designers if they are still around. Look at the system architecture in different perspectives. From there, start digging into the core functionality and looking at some code, returning to requirements and design as needed. As you look at code, run the software to see it in action. All the while, compile some summary documentation for future reference- you own Cliffs Notes. Branch out until you have a pretty good idea of how it all works and fits together, but concentrate on the parts that you will be working with. By now you have a top-to-bottom understanding of the whole system, or at least the parts that are applicable to you.

Of course, in the real world you may not have the time to go through all of this before you have to start getting your hands dirty, especially on the larger projects. But this is how I would do it if it were up to me.

You should work back and forth between the code itself and any design documents.

You can start at code or design, and it doesn't really matter. Read code until you're well and truly confused, then check out the design docs. Or, read the design docs to get a high-level picture then look at the code to see what it looks like. Repeat almost indefinitely as long as you're working with the code.

Be aware that design docs are almost always out of date, and incorrect in many ways. However, as long as you keep these points in mind, out-of-date docs still help you understand the mind of the author at some point in the past. Many of the high-level issues and concerns will still be valid, and you will very likely be able to more quickly understand how the code got to where it is, if you even a dated picture of where the author originally thought it was going to go.

As you work through the code and design, create your own documents that describe your understanding of the code today. Maybe these documents are a simple sketch or two, maybe they're writeups in a wiki, maybe they're something else. Don't make them too complicated: no 30-page word docs. Just get your ideas down, which will clarify your own thinking greatly.

It depends upon the type of application. If its a data-centric app, I usually start with the database design. If it has a UI you can run (or good screen designs) those can also give you a good idea what the app does very quickly (I'm talking just a few hours here at most). After that I start digging into code and it will make more sense because I know what the application is doing.

I start with the design documentation. In particular, the specification - that tells the intent of the thing being looked at.

If possible, I then look at design notes and documentation to get a general flavour of how it has been done, the thought process, the style and nature of the people concerned.

If possible I then talk to the people who worked on it - what does it do? How? Why? Where are the bodies buried?

There's a tendency amongst developers to leap into code: "Let me show you this code". This is fine for them but tends to hijack my needs - which is to understand the high level which gives context to the low level stuff.

It uses vast amounts of brain power to look at little bits of code, out of complete context, and understand anything meaningful. So if possible, getting the developers to talk about the PRINCIPLE, structure, units, modules, whatever all leads to an appreciation of the task.

Only then is it worth trying to get into the code.

In the big scheme of things, looking at the code is like looking at a page full of 0's and 1's. There is meaning but it takes a long time to figure it out. Getting a flavour of where to look and which parts are meaningful helps narrow the search space.

All that said - when there is no doco, no people, and only code - then there is nothing for it but to look at the code.

In that case, I normally don't try and understand it by a slow deep reading, I do a quick pass, skim reading over everything. Sometimes this is just open files and sit with pressing the page-down key. You can get an amazing appreciation of a big picture just by doing this. (And in some cases I even string-dump executable files and trawl those, looking for signatures and patterns. This has been amazingly fruitful over the last 20-odd years.)

I start with the tests. If the unit tests and integration tests are well written, they describe the use cases. If they are not well written, or not written at all (sadly, this is largely the case), I start with entry points in the code and match those with the design.

I'll then write tests for each use case, discovered by the tree you'll find after investigating entry points, to probe the code and use code coverage utilities to see what I'm missing. These tests tell me exactly how the code works.

Design first, then code, top-down if you wish, so I understand the context at every level I have to work.

But if I have to do a very specific change, like fixing a report or a calculation, I just go and look at the code.

More specifically, my "design first" approach is this one:

I start with de domain model if there is one, if there is none I build al least a basic one (a good starting point is the data model). It defines the "glosary" of the application and the relation between the objects (classes).

It pictures "which objects are handled" by the aplication.

Then I look for the use case model to find out "what processes are done" by the application, although I prefer a process map if the is one, that shows sequences of processes.

After that I should have a nice picture of the application and then I can go about designing the change.

By the way, the above answer is in the context of business applications.

The code doesn't lie. Certainly good idea to get an overview of the project first to understand what it does. However, if your task is to get a detailed understanding of how the project works, looking at code, at least for me, is like looking at a jigsaw puzzle piece by piece except that with each class you look at, you're adding another piece of the jigsaw puzzle. If the code is well-structured, you can see a pattern forming from the names of the classes without even investigating what the class does. In many cases, you can get hints and clues from the code which will assist you further.

Finally, you get what is irrequivocable idea of what the program does, a completed jigsaw puzzle. Documentation may be incomplete or inaccurate, but the code never lies. All of this you can do without figuring out what each individual method does. Not everyone can learn about a project this way, but if you do it often, it comes easier to you, not to mention that you can get the gist of a medium-sized application in a couple hours of studying. Though I suppose it all comes down to preference.

The functional scope and flow of the application an his linking with other system of the customer.

After I see the code of the most critical module/point of application: seeing the code, I can
to verify the goodness of the design.

Example:

You have to work in the application management of a web-app about financial reporting.

I ask and read the documentation about of the purpose: what data have to be reported? Who use this application?

What are the linked systems? There's any deadline for receive or sending data to anybody? If this system is down what other application are damages or stopped, what other department are damaged?

After I read the code about the message, the start and end application (for probable lock in db), the master process of creation of data what have to be reported etc etc (for example, in storage of gas the master process is about the computation of gas stock in storage area of the customers with supply and injection; the secondary process is the billing aabout this data previous calculated)

Neither code or design. I like to talk to the stakeholders and end users and find out how it works from their perspective. Once I can create a picture in my mind from them I have a quick look at the technical design and then onto the code.

I will go with design first then code concurrently. It is very important because every projects are different. You need to come out with a plan and high level of process workflow from A to Z before you can start working on the codes concurrently. Every decision made are to be documented so other teams (or yourself) who are/is developing the codes will know the latest update and what has been confirmed.