I studied a lot of people doing this as part of my PhD. The thing is that there are not many answers that work well in a lot of situations. Given that though, my suggestions is to iterate on developing three views of the code:
1. The Mile High View: A layered architectural diagram can be really helpful to know how the main concepts in a project are related to one another. 2. The Core: Try to figure out how the code works with regards to these main concepts. Box and arrow diagrams on paper work really well. 3. Key Use Cases: I would suggest tracing atleast one key use case for your app.