Background:
I have worked for several companies with systems that have been activity used and developed on for 30+ years. The databases have been complex, containing 1000s of unique tables and views. These databases often have hundreds of in-database user defined functions that can be 1000s of lines long. The code bases have been in multiple languages, using multiple technology stacks, and multiple git repositories. These projects have been a mix of monolithic and micro-service architectures. Oftentimes, there have been multiple front-ends (to meet different types of users’ needs – e.g. internal company users, vs external public users). The user applications have typically had ~100-200 pages to do specific types of actions. It is common for the UI pages to have to comply with laws, government regulations that have changed over time. These laws and regulations comprise of 100s-1000s of pages of text. It is common for a single button on a UI page to do very complex actions (e.g. batch jobs) , including building out large data-structures, touching (e.g selecting, inserting, updating, deleting) 10-50+ database tables. It is common for UI pages to only be used at certain parts of the year or once every few years. This makes it much harder to “know about” those parts of the system. It is very common for UI Button actions to have to “know” and enforce details found withing the laws and government regulations. Aside from the application code, we also have large ETL (extract, transform, load) processes to build up data warehouses. There have also typically been a large number of batch jobs to do regular data pulls and updates from other systems.

Given this background, “What are the ways you go about getting comfortable with a new codebase?”
Here is some of what I feel/think/do:

1. In these companies, it is “understood” that a new hire will take about a year+ before they know enough to be useful. These systems took peoples entire careers’ to learn about and bill. It is “understood“ that a new hire will not learn the system “overnight”.

2. Even knowing that it is “impossible” to know the system quickly, I have a personal desire to contribute to the company (e.g. be of use) as quickly as possible. It is very important to have reasonable personal expectations. Chill out and allow yourself time to learn. You can’t avoid paying the TIME cost, to learning a complex system. You can’t skip the Time/Exposure cost required to learn a complex system. If you do skip the TIME/Exposure cost, you are fooling yourself into thinking you “know” something you do not. It will show.

3. Get access. You need access to the code base repository(s). Get access to the database(s). Get usernames and passwords (if allowed in your company). Get login credentials to your applications. Get access to the documentation store(s), ticket tracking system(s), applicable laws and regulation(s) locations, etc.

4. Get a development environment running. Checkout the code. Get it running on your local machine. I want to be able to run in debug mode where possible.

5. Define what it means for you to feel like you know the system. For me I feel like I “know” the system when:
a. all the names and acronyms are familiar (every company and system has their own “language”
b. I can look a random page in the system and known what database tables are referenced when the page loads, and what database table(s) are changed when the UI buttons on the page are pressed.
c. I have a mental model of the data and business validation that will occur when a given UI button is pressed
d. I am comfortable enough in the language(s) and technology stack(s) to make changes, review code, and deploy code
e. This standard is pretty easy for me to “say” but takes YEARS of hard work to achieve.

6. Commit to keeping a log of your daily activities. Writing what you are doing, seeing and learning can act as a form of team coding with yourself. As you write, you are forcing yourself to “teach” and “explain” what you are doing and why. This activity helps me internalize the system quicker. This can help a lot if you are in a company that requires you change problem contexts a lot during the day or week. Also take LOTS of screen shots in your log (using Snagit or ShareX, etc).

7. Commit to creating system documentation. This can be in markdown, confluence, word, etc. It can be in a git repository or file system. It must support screenshots and page links to related pages. I tend to do UML diagrams in Drawio or Visio (exported as images) but if your tool supports UML all the better. I like to organize my system documentation by UI Page. For every major UI Page, I have a system documentation page of the same name. It may have many child pages (depending on how complex the page is). This simple structure means that I can quickly find the documentation that I have 6 months later when working on the same page again. Having a documentation space to put documentation makes it easier for me to create more documentation.

8. Depending on the company, you may ask to job shadow another developer for a period of time. This can mean spending an hour a day or 8 hours a day with them in a team coding environment. Ask another developer to do this. If they say yes, you can learn a lot more quickly about the system.

9. Depending on your company you may have leeway in how you use your time. You may be given issue tickets on day one or you may be sheltered from the storm of requests and given time to learn for a month to a year+.

10. If you are given leeway to research and learn (which is rare), one of the best ways for me to learn is to try to build a mimic system. I look at the existing system and try to build my own system to do what it does. If I can produce a screen that loads data that looks like the original system than I have a high degree of confidence that I “know” how it works. If I can produce a button that saves data (and does all of the complex validation, database changes, etc) that the original system’s save button does, then I have a much higher degree of confidence that I “know” how it works. As I mimic the system, I attempt to document what I am learning about the original system. These notes can become invaluable later (when in a time crunch to fix some critical issue). Building a system mimic makes it much harder to “fool yourself” into thinking you know what is going on. Let the compiler and screen comparison be a mentor. They can be brutally honest but effective teachers.

11. If you are not given such leeway to research and learn (which is common – people pay you to produce), you can learn a lot be reviewing prior completed issue tracking tickets. You can see the most common topics and rough patches in the system (for that time period in the year – problem hotspots change over the year(s)). The existing system documentation (if any exists) may be very helpful. If there are Unit Tests, these can be very valuable learning aids as well. As you work issue tracking tickets you will be forced to learn details about that specific area of the code. It may take longer to get a “wholistic” view of the system this way (as opposed to building a mimic system) but it will eventually get you to a similar level of understanding, via a different route.

12. Some of these company’s architectures have and support Unit Tests. Count yourself luck. Make use of them and add to them. Other company’s architectures do not (or make it really hard).

13. Spend as much time as you can playing with the Application UI. Pretend to be an end-user, loading pages, entering data, clicking thru the process and saving. You will see a lot of validation errors. You can learn a lot about the workflow and pain points in the workflow. You can learn a lot about how the front end effects the database. Systems tend to get better if you (as a developer) “eat your own dogfood” that you make your end users eat. Be in and use the application(s) on a daily basis. This will help you learn the company language and help you communicate with your users. It will also help you see why users are having trouble with a process and perhaps see ways to make the workflow better. It will also expose bugs and give you an opportunity to fix those bugs and learn more about that particular part of the system.

14. One of the most useful things I can do to learn a new system is to build “UNDO” features. I am not certain why this isn't more 'popular'. It feels like it grants SUPER POWERS to me. If I am looking at an Application UI button that does a complex Batch process, the best way to “know” that I know what it does is to build a script (and another button) to undo what that Batch button did. Many of the systems I have worked with do not have an UNDO button for complex processes. This means that everyone is scared to run them because they do so much. This means they do not get run or tested as often as they should. This builds up additional fear of clicking the button. If I can create an UNDO script, I will have to document everything it does. I have to “Know” every database record that it changes. Once I have the UNDO script, it becomes easy to run the button to do the complex batch process and it becomes easy to get back to a virgin state again. The easier it is to run, the more roundtrip testing you can do and the more likely it is for you to make the code better. This all can greatly reduce fears of that process in the future and can greatly speed up supporting the feature in the future.

I am sure there are could be more added to my list. Of course every company and every position is different. You'll have to figure out what makes sense in your situation.

Hopefully it gives you some ideas. Good luck learning your system(s).