A Case Study: Understanding Unfamiliar Code Without Aid

One of the upcoming tasks on my current project is to integrate with an Enterprise Resource Planning (ERP) system. The user story was broad and was titled something like “Push transactions to ERP.” Sure… I’m supposed to do that how exactly?

These kinds of ambiguous tasks can be among the biggest stressors for developers because it’s not clear how to proceed. If it’s a feature that only involves my own code, I probably know where things are and what to edit. But when the task is heavily dependent on understanding unfamiliar code, it can be difficult to find traction.

I’d like to share how I dug into their code to find some direction so you can see how I approach this sort of problem.

Step 1: Get *something* running.

In this particular case, other business processes were integrated with the ERP, so I had an example. But, the examples were in a different Visual Studio solution that didn’t run on my machine. This wasn’t for any strange reason — I just hadn’t set up all the databases, connection strings, etc., to make it work. Based on that, the first step is to get some of that running.

I connected it to the same development database server that I had but found that it did require a couple of schemas I didn’t have cloned.

So I just commented out that code until the server would start.

The Lesson: having some baseline that *works* is tremendously valuable. Once you have something that works, you can print things out, pause it in the debugger, and generally experiment a bit. It doesn’t have to be a full setup, and I didn’t take the time to download a full dataset. But I got enough to print some data to the logs. And if I need more, then I can come back to it.

Step 2: Find the relevant example.

I browsed the code a bit, but codebases can get large and I wasn’t sure what I was looking for. After not making a ton of progress, I took a step back and decided to take a dumb, basic route: I did a text search of the unfamiliar code (using my IDE) for any files that import the ERP integration library. This wasn’t a sophisticated search; Rather, it was just a search for “using some tool.ProductName.Integrations;”

That quickly found a file that used the library. I still had to sift through all the code in the file, but I knew this was an integration point, and there was code using that library here *somewhere.*

The lesson: It’s okay to fall back on simple tools. While some opinionated frameworks make it clear where some kinds of code will live, you don’t always have that (or if you do, you might not have internalized the conventions.) If you find yourself in that case, see if you can find *something* to search for. Anything: a class name that should be commonly used, a piece of jargon from the library’s domain, the name of a configuration flag.

On a prior project, I had to do similar spelunking trying to understand a signal processing algorithm. I knew that there had to be a big array of samples somewhere, so I looked through class definitions until I found that member, and then I had something to trace.

Step 3: Follow the example through the stack.

Once you have found *something*, don’t let go!

I had found the function that called into the ERP — call it function A. So, who calls A? Remember that your IDE can help you a lot here: I used VS2019’s “Find All References” functionality and quickly found function B and controller C.

Don’t overlook how important this is: I now had a complete map of the territory of these tools:

* A request comes into an ASP MVC controller.
* It instantiates a service.
* That service gathers some data, massages it a bit, and hands it to a repository class to save it.
* And finally the repository calls the ERP library.

Okay! That’s my checklist for implementing the new functionality. Obviously, I’ll be doing things a little differently, but I have a reference implementation that I understand well.

The lesson: One way to build your understanding is to follow the connections in the unfamiliar code. The dumb grunt work of following the chain of “…and how did we get here?” will quickly show you what pieces of the system are involved. It’d be great if you had an expert to tell you that “you need to be paying attention to classes X, Y, and Z.” But when you don’t have that guidance, build it up by following the function calls from the area you care about out as far as you need to go to get to an area you understand.

Understanding unfamiliar code isn’t magic.

The scariest thing is a blank page. If you can change the problem from “fix all the things” to something more incremental, then the problem becomes far more approachable.

Build up that understanding by getting a platform to experiment on, find some piece — any piece! — of relevant code, and then manually map the connections around that piece. There’s no magic there, and there doesn’t need to be. Just keep pressing Shift-F12 and taking notes, and eventually, a picture will emerge.